Merges to android Pi release (part 6)
These are a set of CLs merged from the wv cdm repo to the android repo. * Enable Cast for Android Things build. Author: Thoren Paulson <thoren@google.com> [ Merge of http://go/wvgerrit/29941 ] Added a path to make_cast_libwvlevel3 for Android Things. Added the new system id to the preprocessor guards in android_keybox.cpp. Guarded the references to stderr in page_allocator.cpp because for some reason they don't get resolved when we link against the resulting library. BUG: 63443584 * Resolve memory leaks in use of OpenSSL. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/32700 ] Use of EVP_CIPHER_CTX requires a call to EVP_CIPHER_CTX_cleanup(). * Memory leak in OpenSSL RSA key handling. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/32621 ] This fixes a range of tests. --gtest_filter="CdmDecrypt*" runs five tests and still loses 5 objects totalling 1320 bytes (down from 6200 bytes). * Unit test and mock OEMCrypto memory leaks. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/32640 ] More memory leak cleanup. All remaining leaks are due to calls to CRYPTO_malloc() without the matching free (i.e., calls into openssl). * Clean up memory leaks in tests. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/32600 ] This is the first pass at cleaning up memory leaks. These leaks were affecting a lot of tests, making it hard to identify more serious leaks. Switch to unique_ptr<> pointers for CdmEngine in generic_crypto_unittest tests for FileSystem object in mock OEMCrypto's CryptoEngine object. * Fix broken tests - linux-only & address sanitizer failures. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/32460 ] Fix broken test: WvCdmEnginePreProvTestStaging.ServiceCertificateInitialNoneTest Fix failures found by address sanitizer: DeviceFilesUsageInfoTest.RetrieveByProviderSessionToken DeviceFilesUsageInfoTest.UpdateUsageInfo NOTE: address sanitizer cannot handle EXPECT_CALL macros containing a call with a Contains matcher as an argument, e.g.: EXPECT_CALL(file, Write(Contains(certificate, wrapped_private_key, 0), Gt(certificate.size() + wrapped_private_key.size()))) The address sanitizer reports a crash, issues a report, and stops. A temporary fix is to replace the "Contains()" argument with "_". * Usage license handling corrections Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/28540 ] Validate that offline licenses that do not contain a provider session token are not handled by the TEE. BUG: 38490468 Test: WV Unit/integration tests, GtsMediaTestCases, WvCdmRequestLicenseTest.ReleaseRetryL3OfflineKeySessionUsageDisabledTest * UsageTableEntry::CopyOldUsageEntry memcpy read out of range. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/32220 ] The function copies the pst from a variable length input vector into a 256 byte character array. But the length argument was a fixed value - MAC_KEY_SIZE. Depending on the actual PST length this can lead to memcpy reading out of bounds or the PST getting truncated. BUG: 71650075 Test: Not currently passing. Will be addressed in a subsequent commit in the chain. Change-Id: I81a4593d7d04d0ef6069ce48d0601b6fbdd85de9
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "file_store.h"
|
||||
#include "initialization_data.h"
|
||||
#include "lock.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
#include "scoped_ptr.h"
|
||||
#include "service_certificate.h"
|
||||
@@ -290,7 +291,7 @@ class CdmEngine {
|
||||
// dead lock.
|
||||
virtual void OnTimerEvent();
|
||||
|
||||
virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; }
|
||||
virtual metrics::EngineMetrics* GetMetrics() { return &metrics_; }
|
||||
|
||||
private:
|
||||
// private methods
|
||||
@@ -320,7 +321,7 @@ class CdmEngine {
|
||||
* ensure that all data has been properly recorded in the group before
|
||||
* it is published.
|
||||
*/
|
||||
metrics::MetricsGroup metrics_;
|
||||
metrics::EngineMetrics metrics_;
|
||||
metrics::TimerMetric life_span_;
|
||||
|
||||
CdmSessionMap session_map_;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "file_store.h"
|
||||
#include "initialization_data.h"
|
||||
#include "license.h"
|
||||
#include "metrics_group.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
#include "policy_engine.h"
|
||||
#include "scoped_ptr.h"
|
||||
@@ -28,13 +28,30 @@ class UsageTableHeader;
|
||||
|
||||
class CdmSession {
|
||||
public:
|
||||
CdmSession(FileSystem* file_system);
|
||||
// Creates a new instance of the CdmSession with the given |file_system|
|
||||
// and |metrics| parameters. Both parameters are owned by the caller and
|
||||
// must remain in scope througout the scope of the new instance. |metrics|
|
||||
// must not be null.
|
||||
CdmSession(FileSystem* file_system, metrics::SessionMetrics* metrics);
|
||||
virtual ~CdmSession();
|
||||
|
||||
void Close() { closed_ = true; }
|
||||
bool IsClosed() { return closed_; }
|
||||
|
||||
// Initializes this instance of CdmSession with the given property set.
|
||||
// |cdm_client_property_set| MAY be null, is owned by the caller,
|
||||
// and must remain in scope throughout the scope of this session.
|
||||
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set);
|
||||
|
||||
// Initializes this instance of CdmSession with the given parmeters.
|
||||
// All parameters are owned by the caller.
|
||||
// |service_certificate| is caller owned, cannot be null, and must be in
|
||||
// scope as long as the session is in scope.
|
||||
// |cdm_client_property_set| is caller owned, may be null, but must be
|
||||
// in scope as long as the session is in scope.
|
||||
// |forced_session_id| is caller owned and may be null.
|
||||
// |event_listener| is caller owned, may be null, but must be in scope
|
||||
// as long as the session is in scope.
|
||||
virtual CdmResponseType Init(ServiceCertificate* service_certificate,
|
||||
CdmClientPropertySet* cdm_client_property_set,
|
||||
const CdmSessionId* forced_session_id,
|
||||
@@ -171,7 +188,7 @@ class CdmSession {
|
||||
CdmSigningAlgorithm algorithm,
|
||||
const std::string& signature);
|
||||
|
||||
virtual metrics::MetricsGroup* GetMetrics() { return &metrics_; }
|
||||
virtual metrics::SessionMetrics* GetMetrics() { return metrics_; }
|
||||
|
||||
private:
|
||||
friend class CdmSessionTest;
|
||||
@@ -190,20 +207,14 @@ class CdmSession {
|
||||
void set_file_handle(DeviceFiles* file_handle);
|
||||
|
||||
// instance variables
|
||||
|
||||
/*
|
||||
* The metrics group must be the first variable declared to ensure
|
||||
* that it is the last member destroyed so that no child members
|
||||
* try to use a reference to it after it is destroyed. This will
|
||||
* ensure that all data has been properly recorded in the group before
|
||||
* it is published.
|
||||
*/
|
||||
metrics::MetricsGroup metrics_;
|
||||
metrics::SessionMetrics* metrics_;
|
||||
metrics::CryptoMetrics* crypto_metrics_;
|
||||
metrics::TimerMetric life_span_;
|
||||
|
||||
bool initialized_;
|
||||
bool closed_; // Session closed, but final shared_ptr has not been released.
|
||||
CdmSessionId session_id_;
|
||||
FileSystem* file_system_;
|
||||
scoped_ptr<CdmLicense> license_parser_;
|
||||
scoped_ptr<CryptoSession> crypto_session_;
|
||||
scoped_ptr<PolicyEngine> policy_engine_;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "crypto_session.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "metrics_group.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
#include "scoped_ptr.h"
|
||||
#include "wv_cdm_types.h"
|
||||
@@ -21,7 +21,7 @@ class ServiceCertificate;
|
||||
|
||||
class CertificateProvisioning {
|
||||
public:
|
||||
CertificateProvisioning(metrics::MetricsGroup* metrics,
|
||||
CertificateProvisioning(metrics::CryptoMetrics* metrics,
|
||||
ServiceCertificate* service_certificate) :
|
||||
crypto_session_(metrics),
|
||||
cert_type_(kCertificateWidevine),
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "lock.h"
|
||||
#include "metrics_group.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
#include "timer_metric.h"
|
||||
#include "wv_cdm_types.h"
|
||||
@@ -36,7 +36,10 @@ class CryptoSession {
|
||||
bool rsa_cast;
|
||||
};
|
||||
|
||||
CryptoSession(metrics::MetricsGroup* metrics);
|
||||
// Creates an instance of CryptoSession with the given |crypto_metrics|.
|
||||
// |crypto_metrics| is owned by the caller, must NOT be null, and must
|
||||
// exist as long as the new CryptoSession exists.
|
||||
explicit CryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
||||
virtual ~CryptoSession();
|
||||
|
||||
virtual bool GetClientToken(std::string* client_token);
|
||||
@@ -220,7 +223,7 @@ class CryptoSession {
|
||||
static bool initialized_;
|
||||
static int session_count_;
|
||||
|
||||
metrics::MetricsGroup* metrics_;
|
||||
metrics::CryptoMetrics* metrics_;
|
||||
metrics::TimerMetric life_span_;
|
||||
|
||||
bool open_;
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "lock.h"
|
||||
#include "metrics_group.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "scoped_ptr.h"
|
||||
#include "timer_metric.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -67,29 +66,29 @@ class UsageTableHeader {
|
||||
// should not be in use by any open CryptoSession objects when calls
|
||||
// to DeleteEntry and MoveEntry are made.
|
||||
CdmResponseType DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
metrics::CryptoMetrics* metrics);
|
||||
|
||||
private:
|
||||
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
|
||||
const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to /* usage entry number */,
|
||||
DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
metrics::CryptoMetrics* metrics);
|
||||
|
||||
CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
CdmUsageEntry* usage_entry);
|
||||
CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
const CdmUsageEntry& usage_entry);
|
||||
|
||||
CdmResponseType Shrink(metrics::MetricsGroup* metrics,
|
||||
CdmResponseType Shrink(metrics::CryptoMetrics* metrics,
|
||||
uint32_t number_of_usage_entries_to_delete);
|
||||
|
||||
CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
metrics::CryptoMetrics* metrics);
|
||||
bool UpgradeLicensesFromUsageTable(DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
metrics::CryptoMetrics* metrics);
|
||||
bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics);
|
||||
metrics::CryptoMetrics* metrics);
|
||||
|
||||
virtual bool is_inited() { return is_inited_; }
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ static const std::string QUERY_VALUE_SECURITY_LEVEL_L1 = "L1";
|
||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_L2 = "L2";
|
||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_L3 = "L3";
|
||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_UNKNOWN = "Unknown";
|
||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_DEFAULT = "Default";
|
||||
static const std::string QUERY_VALUE_DISCONNECTED = "Disconnected";
|
||||
static const std::string QUERY_VALUE_UNPROTECTED = "Unprotected";
|
||||
static const std::string QUERY_VALUE_HDCP_V1 = "HDCP-1.x";
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "file_store.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "metrics_front_end.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
@@ -188,7 +187,8 @@ CdmResponseType CdmEngine::OpenSession(
|
||||
|
||||
CloseExpiredReleaseSessions();
|
||||
|
||||
scoped_ptr<CdmSession> new_session(new CdmSession(file_system_));
|
||||
scoped_ptr<CdmSession> new_session(new CdmSession(file_system_,
|
||||
metrics_.AddSession()));
|
||||
CdmResponseType sts = new_session->Init(&service_certificate_, property_set,
|
||||
forced_session_id, event_listener);
|
||||
if (sts != NO_ERROR) {
|
||||
@@ -545,13 +545,13 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
const std::string& query_token,
|
||||
std::string* query_response) {
|
||||
LOGI("CdmEngine::QueryStatus");
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
|
||||
if (security_level == kLevel3) {
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = crypto_session.Open(
|
||||
kLevel3),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_open_,
|
||||
status,
|
||||
kLevel3);
|
||||
@@ -567,7 +567,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
CdmSecurityLevel level;
|
||||
M_TIME(
|
||||
level = crypto_session.GetSecurityLevel(),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_get_security_level_,
|
||||
level);
|
||||
switch (level) {
|
||||
@@ -594,7 +594,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
M_TIME(
|
||||
got_id = crypto_session.GetExternalDeviceUniqueId(
|
||||
&deviceId),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_get_device_unique_id_,
|
||||
got_id);
|
||||
if (!got_id) {
|
||||
@@ -609,7 +609,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
M_TIME(
|
||||
got_id = crypto_session.GetSystemId(
|
||||
&system_id),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_get_system_id_,
|
||||
got_id,
|
||||
system_id);
|
||||
@@ -646,7 +646,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
M_TIME(
|
||||
got_info = crypto_session.UsageInformationSupport(
|
||||
&supports_usage_reporting),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_usage_information_support_,
|
||||
got_info);
|
||||
if (!got_info) {
|
||||
@@ -854,7 +854,8 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
|
||||
if (NULL == cert_provisioning_.get()) {
|
||||
cert_provisioning_.reset(
|
||||
new CertificateProvisioning(&metrics_, &service_certificate_));
|
||||
new CertificateProvisioning(metrics_.GetCryptoMetrics(),
|
||||
&service_certificate_));
|
||||
}
|
||||
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
|
||||
cert_provisioning_requested_security_level_, cert_type, cert_authority,
|
||||
@@ -896,12 +897,12 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
if (NULL == cert_provisioning_.get()) {
|
||||
// Certificate provisioning object has been released. Check if a concurrent
|
||||
// provisioning attempt has succeeded before declaring failure.
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = crypto_session.Open(
|
||||
cert_provisioning_requested_security_level_),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_open_,
|
||||
status,
|
||||
cert_provisioning_requested_security_level_);
|
||||
@@ -914,7 +915,7 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
CdmSecurityLevel security_level;
|
||||
M_TIME(
|
||||
security_level = crypto_session.GetSecurityLevel(),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_get_security_level_,
|
||||
security_level);
|
||||
if (!IsProvisioned(security_level)) {
|
||||
@@ -968,14 +969,15 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) {
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession(&metrics_));
|
||||
scoped_ptr<CryptoSession> crypto_session(
|
||||
new CryptoSession(metrics_.GetCryptoMetrics()));
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = crypto_session->Open(
|
||||
security_level == kSecurityLevelL3 ?
|
||||
kLevel3 :
|
||||
kLevelDefault),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_open_,
|
||||
status,
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||
@@ -986,11 +988,12 @@ CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) {
|
||||
}
|
||||
M_TIME(
|
||||
status = crypto_session->DeleteAllUsageReports(),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_delete_all_usage_reports_,
|
||||
status);
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("CdmEngine::DeleteUsageTable: error deleteing usage reports: %d", status);
|
||||
LOGE("CdmEngine::DeleteUsageTable: error deleteing usage reports: %d",
|
||||
status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -1049,7 +1052,8 @@ CdmResponseType CdmEngine::DeleteUsageRecord(const std::string& app_id,
|
||||
}
|
||||
|
||||
// Got provider token. Remove from OEMCrypto.
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession(&metrics_));
|
||||
scoped_ptr<CryptoSession> crypto_session(
|
||||
new CryptoSession(metrics_.GetCryptoMetrics()));
|
||||
CdmResponseType status = crypto_session->Open(
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||
if (status == NO_ERROR) {
|
||||
@@ -1079,7 +1083,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
}
|
||||
usage_property_set_->set_security_level(kLevelDefault);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
|
||||
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error: %d", status);
|
||||
@@ -1099,7 +1103,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
ssid, &usage_data)) {
|
||||
usage_property_set_->set_security_level(kLevel3);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
|
||||
status = usage_session_->Init(usage_property_set_.get());
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error");
|
||||
@@ -1176,7 +1180,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
usage_property_set_->set_security_level(requested_security_level);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
|
||||
|
||||
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
|
||||
if (NO_ERROR != status) {
|
||||
@@ -1257,7 +1261,8 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(
|
||||
}
|
||||
|
||||
// Got at least one provider token. Remove from OEMCrypto.
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession(&metrics_));
|
||||
scoped_ptr<CryptoSession> crypto_session(
|
||||
new CryptoSession(metrics_.GetCryptoMetrics()));
|
||||
CdmResponseType status = crypto_session->Open(
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||
if (status == NO_ERROR) {
|
||||
@@ -1285,7 +1290,7 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
usage_property_set_->set_security_level(security_level);
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
|
||||
usage_session_->Init(usage_property_set_.get());
|
||||
|
||||
switch (usage_session_->get_usage_support_type()) {
|
||||
@@ -1730,19 +1735,20 @@ void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
|
||||
|
||||
if (!file_system_->Exists(device_base_path_level1) &&
|
||||
!file_system_->Exists(device_base_path_level3)) {
|
||||
scoped_ptr<CryptoSession> crypto_session(new CryptoSession(&metrics_));
|
||||
scoped_ptr<CryptoSession> crypto_session(
|
||||
new CryptoSession(metrics_.GetCryptoMetrics()));
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = crypto_session->Open(
|
||||
cert_provisioning_requested_security_level_),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_open_,
|
||||
status,
|
||||
cert_provisioning_requested_security_level_);
|
||||
if (NO_ERROR == status) {
|
||||
M_TIME(
|
||||
status = crypto_session->DeleteAllUsageReports(),
|
||||
&metrics_,
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_delete_all_usage_reports_,
|
||||
status);
|
||||
if (NO_ERROR != status) {
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "clock.h"
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
#include "metrics_front_end.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
@@ -25,10 +24,10 @@ const size_t kKeySetIdLength = 14;
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
CdmSession::CdmSession(FileSystem* file_system) :
|
||||
CdmSession::CdmSession(FileSystem* file_system,
|
||||
metrics::SessionMetrics* metrics) :
|
||||
metrics_(metrics),
|
||||
initialized_(false),
|
||||
closed_(false),
|
||||
crypto_session_(new CryptoSession(&metrics_)),
|
||||
file_handle_(new DeviceFiles(file_system)),
|
||||
license_received_(false),
|
||||
is_offline_(false),
|
||||
@@ -45,6 +44,9 @@ CdmSession::CdmSession(FileSystem* file_system) :
|
||||
usage_entry_number_(0),
|
||||
mock_license_parser_in_use_(false),
|
||||
mock_policy_engine_in_use_(false) {
|
||||
assert(metrics_); // metrics_ must not be null.
|
||||
crypto_metrics_ = metrics_->GetCryptoMetrics();
|
||||
crypto_session_.reset(new CryptoSession(crypto_metrics_));
|
||||
life_span_.Start();
|
||||
}
|
||||
|
||||
@@ -55,7 +57,10 @@ CdmSession::~CdmSession() {
|
||||
}
|
||||
Properties::RemoveSessionPropertySet(session_id_);
|
||||
|
||||
M_RECORD(&metrics_, cdm_session_life_span_, life_span_.AsMs());
|
||||
if (metrics_) {
|
||||
M_RECORD(metrics_, cdm_session_life_span_, life_span_.AsMs());
|
||||
metrics_->SetCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::Init(
|
||||
@@ -80,16 +85,15 @@ CdmResponseType CdmSession::Init(
|
||||
}
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
sts = crypto_session_->Open(
|
||||
requested_security_level_),
|
||||
&metrics_,
|
||||
sts = crypto_session_->Open(requested_security_level_),
|
||||
crypto_metrics_,
|
||||
crypto_session_open_,
|
||||
sts,
|
||||
requested_security_level_);
|
||||
if (NO_ERROR != sts) return sts;
|
||||
M_TIME(
|
||||
security_level_ = crypto_session_->GetSecurityLevel(),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_get_security_level_,
|
||||
security_level_);
|
||||
if (!file_handle_->Init(security_level_)) {
|
||||
@@ -126,7 +130,7 @@ CdmResponseType CdmSession::Init(
|
||||
M_TIME(
|
||||
get_client_token_sts = crypto_session_->GetClientToken(
|
||||
&client_token),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_get_token_,
|
||||
get_client_token_sts);
|
||||
if (!get_client_token_sts) {
|
||||
@@ -144,7 +148,7 @@ CdmResponseType CdmSession::Init(
|
||||
M_TIME(
|
||||
load_cert_sts = crypto_session_->LoadCertificatePrivateKey(
|
||||
wrapped_key),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_load_certificate_private_key_,
|
||||
load_cert_sts);
|
||||
if(!load_cert_sts) {
|
||||
@@ -166,6 +170,7 @@ CdmResponseType CdmSession::Init(
|
||||
|
||||
session_id_ =
|
||||
Properties::AlwaysUseKeySetIds() ? key_set_id_ : GenerateSessionId();
|
||||
metrics_->SetSessionId(session_id_);
|
||||
|
||||
if (session_id_.empty()) {
|
||||
LOGE("CdmSession::Init: empty session ID");
|
||||
@@ -222,14 +227,20 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
return GET_RELEASED_LICENSE_ERROR;
|
||||
}
|
||||
|
||||
std::string provider_session_token;
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
CdmResponseType sts = usage_table_header_->LoadEntry(crypto_session_.get(),
|
||||
usage_entry_,
|
||||
usage_entry_number_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("CdmSession::RestoreOfflineSession: failed to load usage entry = %d",
|
||||
sts);
|
||||
return sts;
|
||||
if (!license_parser_->ExtractProviderSessionToken(
|
||||
key_response_, &provider_session_token)) {
|
||||
provider_session_token.clear();
|
||||
} else {
|
||||
CdmResponseType sts =
|
||||
usage_table_header_->LoadEntry(crypto_session_.get(), usage_entry_,
|
||||
usage_entry_number_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("CdmSession::RestoreOfflineSession: failed to load usage entry = "
|
||||
"%d", sts);
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +257,8 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
}
|
||||
}
|
||||
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
if (usage_support_type_ == kUsageEntrySupport &&
|
||||
!provider_session_token.empty()) {
|
||||
CdmResponseType sts =
|
||||
usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_);
|
||||
if (sts != NO_ERROR) {
|
||||
@@ -432,7 +444,8 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
if (sts != KEY_ADDED) {
|
||||
CdmResponseType sts =
|
||||
usage_table_header_->DeleteEntry(usage_entry_number_,
|
||||
file_handle_.get(), &metrics_);
|
||||
file_handle_.get(),
|
||||
crypto_metrics_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts);
|
||||
}
|
||||
@@ -449,8 +462,10 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
license_parser_->provider_session_token().c_str());
|
||||
|
||||
if (is_offline_ || has_provider_session_token()) {
|
||||
if (usage_support_type_ == kUsageEntrySupport)
|
||||
if (has_provider_session_token() &&
|
||||
usage_support_type_ == kUsageEntrySupport) {
|
||||
usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_);
|
||||
}
|
||||
|
||||
if (!is_offline_)
|
||||
usage_provider_session_token_ =
|
||||
@@ -614,7 +629,8 @@ CdmResponseType CdmSession::GenerateReleaseRequest(
|
||||
|
||||
if (KEY_MESSAGE != status) return status;
|
||||
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
if (has_provider_session_token() &&
|
||||
usage_support_type_ == kUsageEntrySupport) {
|
||||
status = usage_table_header_->UpdateEntry(crypto_session_.get(),
|
||||
&usage_entry_);
|
||||
if (status != NO_ERROR) {
|
||||
@@ -645,7 +661,8 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
if (is_offline_ || has_provider_session_token()) {
|
||||
DeleteLicense();
|
||||
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
if (usage_support_type_ == kUsageEntrySupport &&
|
||||
has_provider_session_token()) {
|
||||
sts = DeleteUsageEntry(usage_entry_number_);
|
||||
if (NO_ERROR != sts) return sts;
|
||||
}
|
||||
@@ -654,7 +671,8 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
|
||||
if (usage_support_type_ != kUsageEntrySupport) {
|
||||
if (usage_support_type_ != kUsageEntrySupport ||
|
||||
!has_provider_session_token()) {
|
||||
LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d",
|
||||
usage_support_type_);
|
||||
return INCORRECT_USAGE_SUPPORT_TYPE_1;
|
||||
@@ -664,10 +682,10 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
|
||||
// it, so close and reopen session.
|
||||
CdmResponseType sts;
|
||||
crypto_session_->Close();
|
||||
crypto_session_.reset(new CryptoSession(&metrics_));
|
||||
crypto_session_.reset(new CryptoSession(crypto_metrics_));
|
||||
M_TIME(
|
||||
sts = crypto_session_->Open(requested_security_level_),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_open_,
|
||||
sts,
|
||||
requested_security_level_);
|
||||
@@ -688,7 +706,7 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
|
||||
|
||||
return usage_table_header_->DeleteEntry(usage_entry_number,
|
||||
file_handle_.get(),
|
||||
&metrics_);
|
||||
crypto_metrics_);
|
||||
}
|
||||
|
||||
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
|
||||
@@ -838,7 +856,7 @@ CdmResponseType CdmSession::DeleteMultipleUsageInformation(
|
||||
M_TIME(
|
||||
sts = crypto_session_->DeleteMultipleUsageInformation(
|
||||
provider_session_tokens),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_delete_multiple_usage_information_,
|
||||
sts);
|
||||
return sts;
|
||||
@@ -852,7 +870,7 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() {
|
||||
if (sts == NO_ERROR && usage_support_type == kUsageTableSupport) {
|
||||
M_TIME(
|
||||
sts = crypto_session_->UpdateUsageInformation(),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_update_usage_information_,
|
||||
sts);
|
||||
return sts;
|
||||
@@ -862,7 +880,8 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::UpdateUsageEntryInformation() {
|
||||
if (usage_support_type_ != kUsageEntrySupport) {
|
||||
if (usage_support_type_ != kUsageEntrySupport ||
|
||||
!has_provider_session_token()) {
|
||||
LOGE("CdmSession::UpdateUsageEntryInformation: Unexpected usage type "
|
||||
"supported: %d", usage_support_type_);
|
||||
return INCORRECT_USAGE_SUPPORT_TYPE_2;
|
||||
@@ -900,7 +919,7 @@ CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer,
|
||||
iv,
|
||||
algorithm,
|
||||
out_buffer),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_generic_encrypt_,
|
||||
sts,
|
||||
metrics::Pow2Bucket(in_buffer.size()),
|
||||
@@ -925,7 +944,7 @@ CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer,
|
||||
iv,
|
||||
algorithm,
|
||||
out_buffer),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_generic_decrypt_,
|
||||
sts,
|
||||
metrics::Pow2Bucket(in_buffer.size()),
|
||||
@@ -948,7 +967,7 @@ CdmResponseType CdmSession::GenericSign(const std::string& message,
|
||||
key_id,
|
||||
algorithm,
|
||||
signature),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_generic_sign_,
|
||||
sts,
|
||||
metrics::Pow2Bucket(message.size()),
|
||||
@@ -967,7 +986,7 @@ CdmResponseType CdmSession::GenericVerify(const std::string& message,
|
||||
key_id,
|
||||
algorithm,
|
||||
signature),
|
||||
&metrics_,
|
||||
crypto_metrics_,
|
||||
crypto_session_generic_verify_,
|
||||
sts,
|
||||
metrics::Pow2Bucket(message.size()),
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include "crypto_key.h"
|
||||
#include "log.h"
|
||||
#include "metrics_front_end.h"
|
||||
#include "openssl/sha.h"
|
||||
#include "properties.h"
|
||||
#include "pst_report.h"
|
||||
@@ -45,7 +44,7 @@ uint64_t CryptoSession::request_id_index_ = 0;
|
||||
UsageTableHeader* CryptoSession::usage_table_header_l1_ = NULL;
|
||||
UsageTableHeader* CryptoSession::usage_table_header_l3_ = NULL;
|
||||
|
||||
CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
|
||||
CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
|
||||
: metrics_(metrics),
|
||||
open_(false),
|
||||
update_usage_table_after_close_session_(false),
|
||||
@@ -234,34 +233,43 @@ bool CryptoSession::GetProvisioningToken(std::string* token) {
|
||||
CdmSecurityLevel CryptoSession::GetSecurityLevel() {
|
||||
LOGV("CryptoSession::GetSecurityLevel");
|
||||
if (!initialized_) {
|
||||
M_RECORD(metrics_, oemcrypto_security_level_, 0,
|
||||
kSecurityLevelUninitialized, requested_security_level_);
|
||||
return kSecurityLevelUninitialized;
|
||||
}
|
||||
|
||||
std::string security_level;
|
||||
M_TIME(
|
||||
security_level = OEMCrypto_SecurityLevel(
|
||||
requested_security_level_),
|
||||
metrics_,
|
||||
oemcrypto_security_level_,
|
||||
security_level,
|
||||
requested_security_level_);
|
||||
wvcdm::metrics::TimerMetric timer;
|
||||
timer.Start();
|
||||
|
||||
std::string security_level =
|
||||
OEMCrypto_SecurityLevel(requested_security_level_);
|
||||
double clock_time = timer.AsUs();
|
||||
|
||||
if ((security_level.size() != 2) || (security_level.at(0) != 'L')) {
|
||||
M_RECORD(metrics_, oemcrypto_security_level_, clock_time,
|
||||
kSecurityLevelUnknown, requested_security_level_);
|
||||
return kSecurityLevelUnknown;
|
||||
}
|
||||
|
||||
CdmSecurityLevel cdm_security_level;
|
||||
switch (security_level.at(1)) {
|
||||
case '1':
|
||||
return kSecurityLevelL1;
|
||||
cdm_security_level = kSecurityLevelL1;
|
||||
break;
|
||||
case '2':
|
||||
return kSecurityLevelL2;
|
||||
cdm_security_level = kSecurityLevelL2;
|
||||
break;
|
||||
case '3':
|
||||
return kSecurityLevelL3;
|
||||
cdm_security_level = kSecurityLevelL3;
|
||||
break;
|
||||
default:
|
||||
return kSecurityLevelUnknown;
|
||||
cdm_security_level = kSecurityLevelUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
return kSecurityLevelUnknown;
|
||||
M_RECORD(metrics_, oemcrypto_security_level_, clock_time,
|
||||
cdm_security_level, requested_security_level_);
|
||||
return cdm_security_level;
|
||||
}
|
||||
|
||||
bool CryptoSession::GetInternalDeviceUniqueId(std::string* device_id) {
|
||||
@@ -444,8 +452,10 @@ uint8_t CryptoSession::GetSecurityPatchLevel() {
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
||||
LOGV("CryptoSession::Open: Lock: requested_security_level: %d",
|
||||
requested_security_level);
|
||||
LOGD("CryptoSession::Open: Lock: requested_security_level: %s",
|
||||
requested_security_level == kLevel3
|
||||
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
|
||||
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!initialized_) return UNKNOWN_ERROR;
|
||||
if (open_) return NO_ERROR;
|
||||
@@ -719,6 +729,10 @@ CdmResponseType CryptoSession::LoadKeys(
|
||||
} else if (OEMCrypto_ERROR_TOO_MANY_KEYS == sts) {
|
||||
LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts);
|
||||
result = INSUFFICIENT_CRYPTO_RESOURCES;
|
||||
} else if (OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE == sts) {
|
||||
// Handle vendor specific error
|
||||
LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts);
|
||||
result = NEED_PROVISIONING;
|
||||
} else {
|
||||
LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts);
|
||||
result = LOAD_KEY_ERROR;
|
||||
@@ -1750,11 +1764,15 @@ bool CryptoSession::GetSrmVersion(uint16_t* srm_version) {
|
||||
}
|
||||
|
||||
OEMCryptoResult status = OEMCrypto_GetCurrentSRMVersion(srm_version);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status);
|
||||
return false;
|
||||
switch (status) {
|
||||
case OEMCrypto_SUCCESS:
|
||||
return true;
|
||||
case OEMCrypto_ERROR_NOT_IMPLEMENTED:
|
||||
return false;
|
||||
default:
|
||||
LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoSession::IsSrmUpdateSupported() {
|
||||
|
||||
@@ -163,7 +163,7 @@ bool DeviceFiles::ExtractDeviceInfo(const std::string& device_certificate,
|
||||
uint32_t* system_id) {
|
||||
LOGI("ExtractDeviceInfo Entry");
|
||||
if (!serial_number && !system_id) {
|
||||
LOGE("Invalid paramters to DeviceFiles::ExtractDeviceInfo");
|
||||
LOGE("DeviceFiles::ExtractDeviceInfo: invalid parameter.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1239,7 +1239,7 @@ bool DeviceFiles::FileExists(const std::string& name) {
|
||||
bool DeviceFiles::ListFiles(std::vector<std::string>* names) {
|
||||
std::string path;
|
||||
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
|
||||
LOGW("DeviceFiles::RemoveFile: Unable to get base path");
|
||||
LOGW("DeviceFiles::ListFiles: Unable to get base path");
|
||||
return false;
|
||||
}
|
||||
return file_system_->List(path, names);
|
||||
|
||||
@@ -486,13 +486,11 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
license.policy().can_persist())
|
||||
is_offline_ = true;
|
||||
|
||||
LOGV("Get Provider_session_token:");
|
||||
if (license.id().has_provider_session_token()) {
|
||||
if (license.id().has_provider_session_token())
|
||||
provider_session_token_ = license.id().provider_session_token();
|
||||
LOGV("Provider_session_token=%s", provider_session_token_.c_str());
|
||||
} else {
|
||||
LOGV("NO Provider_session_token");
|
||||
}
|
||||
|
||||
LOGV("provider_session_token: %s", provider_session_token_.empty() ?
|
||||
"N/A" : provider_session_token_.c_str());
|
||||
|
||||
if (license.policy().has_renewal_server_url()) {
|
||||
server_url_ = license.policy().renewal_server_url();
|
||||
@@ -803,7 +801,8 @@ bool CdmLicense::ExtractProviderSessionToken(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (license.id().has_provider_session_token()) {
|
||||
if (license.id().has_provider_session_token() &&
|
||||
!license.id().provider_session_token().empty()) {
|
||||
*provider_session_token = license.id().provider_session_token();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
#include "level3.h"
|
||||
#include "lock.h"
|
||||
#include "log.h"
|
||||
#include "metrics_front_end.h"
|
||||
#include "metrics_group.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "properties.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
@@ -41,6 +40,8 @@ using wvcdm::kLevel3;
|
||||
namespace {
|
||||
|
||||
static const size_t kMaxGenericEncryptChunkSize = 100*1024;
|
||||
const OEMCryptoResult kOemCryptoResultVendorSpecificError1 =
|
||||
static_cast<OEMCryptoResult>(10008);
|
||||
|
||||
typedef struct {
|
||||
const uint8_t* key_id;
|
||||
@@ -375,6 +376,162 @@ void clear_cache_function(void *page, size_t len) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// The WatchDog looks after a worker thread that is trying to initialize L3.
|
||||
// Once in a rare while, the L3 init does not finish and eats up CPU cycles.
|
||||
// If that happens, the watchdog thread will give up and return an error.
|
||||
class WatchDog {
|
||||
public:
|
||||
// Created by main thread.
|
||||
WatchDog() {
|
||||
pthread_mutex_init(&mutex_, NULL);
|
||||
pthread_cond_init(&condition_, NULL);
|
||||
status_ = OEMCrypto_SUCCESS;
|
||||
gave_up_ = false;
|
||||
}
|
||||
|
||||
// Deleted by either thread.
|
||||
~WatchDog() {
|
||||
pthread_cond_destroy(&condition_);
|
||||
}
|
||||
|
||||
// Starts worker thread.
|
||||
void StartThread() {
|
||||
running_ = true;
|
||||
if(pthread_create(&thread_, NULL, RunWatchDog, this)) {
|
||||
LOGE("Could not create watch dog thread.");
|
||||
status_ = OEMCrypto_ERROR_INIT_FAILED;
|
||||
running_ = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Function called by new worker thread in pthread_create.
|
||||
static void *RunWatchDog(void *watcher) {
|
||||
WatchDog* dog = reinterpret_cast<WatchDog *>(watcher);
|
||||
dog->DoInit();
|
||||
dog->SignalDoneAndCleanUp();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Called by worker thread.
|
||||
void DoInit() {
|
||||
std::string base_path;
|
||||
wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
|
||||
&base_path);
|
||||
status_ = Level3_Initialize(clear_cache_function,
|
||||
base_path.c_str());
|
||||
}
|
||||
|
||||
std::string FailureFilename() {
|
||||
std::string path;
|
||||
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
|
||||
&path)) {
|
||||
LOGW("WatchDog::FailureFilename: Unable to get base path");
|
||||
return "/data/l3_failure_file";
|
||||
}
|
||||
path += "l3_failure_file";
|
||||
return path;
|
||||
}
|
||||
|
||||
// Check to see if the failure file was created before that last abort.
|
||||
void CheckForPreviousFailure(wvcdm::metrics::CryptoMetrics* metrics) {
|
||||
wvcdm::FileSystem file_system;
|
||||
std::string filename = FailureFilename();
|
||||
if (!file_system.Exists(filename)) return;
|
||||
wvcdm::File* file = file_system.Open(filename, file_system.kReadOnly);
|
||||
if (file) {
|
||||
uint32_t flag = 0;
|
||||
ssize_t size = sizeof(flag);
|
||||
ssize_t size_read = file->Read(reinterpret_cast<char*>(&flag), size);
|
||||
file->Close();
|
||||
file_system.Remove(filename);
|
||||
if (size == size_read && flag) {
|
||||
LOGE("Previous L3 Init failed.");
|
||||
if (metrics == nullptr) return;
|
||||
M_RECORD(
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_L3_INITIALIZATION_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save the failure file before we abort.
|
||||
void SaveFailureInformation() {
|
||||
wvcdm::FileSystem file_system;
|
||||
std::string filename = FailureFilename();
|
||||
LOGD("failure filename = %s", filename.c_str());
|
||||
wvcdm::File* file = file_system.Open(
|
||||
filename, file_system.kCreate | file_system.kTruncate);
|
||||
if (!file) {
|
||||
LOGE("Could not create file %s", filename.c_str());
|
||||
return;
|
||||
}
|
||||
uint32_t flag = 0x6261640a; // bad
|
||||
ssize_t size = sizeof(flag);
|
||||
ssize_t size_written = file->Write(reinterpret_cast<char*>(&flag), size);
|
||||
file->Close();
|
||||
if (size != size_written) {
|
||||
LOGE("Wrote %d bytes, not %d, to file %s", size_written, size,
|
||||
filename.c_str());
|
||||
} else {
|
||||
LOGE("I wrote %d to %s", size_written, filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Called by worker thread after DoInit has finshed.
|
||||
void SignalDoneAndCleanUp() {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
running_ = false;
|
||||
pthread_cond_signal(&condition_);
|
||||
// If the main thread gave up, it won't delete this, so we must.
|
||||
bool should_delete = gave_up_;
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
// https://isocpp.org/wiki/faq/freestore-mgmt#delete-this
|
||||
if (should_delete) delete this;
|
||||
}
|
||||
|
||||
// Called by main thread to wait for worker thread.
|
||||
OEMCryptoResult WaitForStatusAndCleanUp() {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
struct timespec time_to_giveup;
|
||||
clock_gettime(CLOCK_REALTIME, &time_to_giveup);
|
||||
time_to_giveup.tv_sec += 5; // wait 5 seconds.
|
||||
if (running_) {
|
||||
pthread_cond_timedwait(&condition_, &mutex_, &time_to_giveup);
|
||||
}
|
||||
if (running_) {
|
||||
gave_up_ = true;
|
||||
status_ = OEMCrypto_ERROR_INIT_FAILED;
|
||||
LOGE("XXX WATCH DOG ERROR XXX");
|
||||
SaveFailureInformation();
|
||||
// This is controversial. The argument for an abort here is that if we
|
||||
// do not abort, we will suck all the life out of the user's battery. By
|
||||
// saving information to the file system, above, we can still track
|
||||
// metrics.
|
||||
abort();
|
||||
}
|
||||
// If we gave up waiting for init thread, we should not delete the mutex
|
||||
// out from under it.
|
||||
bool should_delete = !gave_up_;
|
||||
OEMCryptoResult status = status_;
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
if (should_delete) delete this;
|
||||
return status;
|
||||
}
|
||||
|
||||
OEMCryptoResult status() { return status_; }
|
||||
|
||||
private:
|
||||
OEMCryptoResult status_;
|
||||
pthread_t thread_;
|
||||
pthread_mutex_t mutex_;
|
||||
pthread_cond_t condition_;
|
||||
bool running_;
|
||||
bool gave_up_;
|
||||
};
|
||||
|
||||
struct LevelSession {
|
||||
FunctionPointers* fcn;
|
||||
OEMCrypto_SESSION session;
|
||||
@@ -423,17 +580,20 @@ class Adapter {
|
||||
* To avoid changing the function signature and function contract - declare
|
||||
* a one-off metrics group to collect detailed information about how
|
||||
* oemcrypto was intialized.
|
||||
*
|
||||
* TODO(blueeyes): Refactor this to allow Initialize to provide the
|
||||
* details to the caller or to use the metrics instance provided by
|
||||
* the caller.
|
||||
*/
|
||||
wvcdm::metrics::MetricsGroup metrics;
|
||||
wvcdm::metrics::CryptoMetrics metrics;
|
||||
|
||||
level1_ = FunctionPointers(); // start with all null pointers.
|
||||
level3_ = FunctionPointers(); // start with all null pointers.
|
||||
LoadLevel3();
|
||||
std::string base_path;
|
||||
wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
|
||||
&base_path);
|
||||
OEMCryptoResult result = Level3_Initialize(clear_cache_function,
|
||||
base_path.c_str());
|
||||
WatchDog *watcher = new WatchDog();
|
||||
watcher->CheckForPreviousFailure(&metrics);
|
||||
watcher->StartThread();
|
||||
OEMCryptoResult result = watcher->WaitForStatusAndCleanUp();
|
||||
if (Level3_IsInApp()) {
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
@@ -472,7 +632,7 @@ class Adapter {
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED);
|
||||
return result;
|
||||
}
|
||||
if (LoadLevel1(metrics)) {
|
||||
if (LoadLevel1(&metrics)) {
|
||||
LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1.");
|
||||
} else {
|
||||
level1_ = FunctionPointers(); // revert to all null pointers.
|
||||
@@ -483,7 +643,10 @@ class Adapter {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LoadLevel1(wvcdm::metrics::MetricsGroup& metrics) {
|
||||
bool LoadLevel1(wvcdm::metrics::CryptoMetrics* metrics) {
|
||||
if (metrics == nullptr) {
|
||||
return false;
|
||||
}
|
||||
level1_valid_ = true;
|
||||
const uint32_t kMinimumVersion = 8;
|
||||
const uint32_t kMaximumVersion = 13;
|
||||
@@ -493,7 +656,7 @@ class Adapter {
|
||||
LOOKUP_ALL(8, Terminate, OEMCrypto_Terminate);
|
||||
if (!level1_valid_) {
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_INVALID_L1);
|
||||
@@ -503,7 +666,7 @@ class Adapter {
|
||||
if (st != OEMCrypto_SUCCESS) {
|
||||
LOGW("Could not initialize L1. Falling Back to L3.");
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1);
|
||||
@@ -511,7 +674,7 @@ class Adapter {
|
||||
}
|
||||
level1_.version = level1_.APIVersion();
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_l1_api_version_,
|
||||
NO_TIME,
|
||||
level1_.version,
|
||||
@@ -520,7 +683,7 @@ class Adapter {
|
||||
LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.",
|
||||
level1_.version, kMinimumVersion);
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION);
|
||||
@@ -598,7 +761,7 @@ class Adapter {
|
||||
// If we have a valid keybox, initialization is done. We're good.
|
||||
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX);
|
||||
@@ -610,7 +773,7 @@ class Adapter {
|
||||
if (level1_.version > 11 &&
|
||||
(level1_.GetProvisioningMethod() == OEMCrypto_OEMCertificate)) {
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0);
|
||||
@@ -630,13 +793,13 @@ class Adapter {
|
||||
LOGE("OEMCrypto uses cert as identification, but cdm does not!");
|
||||
LOGE("This will not work on a production device.");
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX);
|
||||
} else {
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE);
|
||||
@@ -649,7 +812,7 @@ class Adapter {
|
||||
LOGW("Bad Level 1 Keybox. Falling Back to L3.");
|
||||
level1_.Terminate();
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX);
|
||||
@@ -661,7 +824,7 @@ class Adapter {
|
||||
LOGW("Could not open %s. Falling Back to L3.", filename.c_str());
|
||||
level1_.Terminate();
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX);
|
||||
@@ -675,7 +838,7 @@ class Adapter {
|
||||
filename.c_str());
|
||||
level1_.Terminate();
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX);
|
||||
@@ -683,7 +846,7 @@ class Adapter {
|
||||
}
|
||||
LOGI("Installed keybox from %s", filename.c_str());
|
||||
M_RECORD(
|
||||
&metrics,
|
||||
metrics,
|
||||
oemcrypto_initialization_mode_,
|
||||
NO_TIME,
|
||||
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX);
|
||||
@@ -1156,18 +1319,26 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
} else {
|
||||
if (pair.fcn->LoadKeys_V9_or_V10 == NULL)
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
return pair.fcn->LoadKeys_V9_or_V10(pair.session, message, message_length,
|
||||
signature, signature_length,
|
||||
enc_mac_key_iv, enc_mac_key, num_keys,
|
||||
&key_array_v10[0], pst, pst_length);
|
||||
OEMCryptoResult result = pair.fcn->LoadKeys_V9_or_V10(
|
||||
pair.session, message, message_length, signature, signature_length,
|
||||
enc_mac_key_iv, enc_mac_key, num_keys, &key_array_v10[0], pst,
|
||||
pst_length);
|
||||
// Convert a vendor specific error, to make it actionable
|
||||
if (result == kOemCryptoResultVendorSpecificError1)
|
||||
result = OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE;
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
if (pair.fcn->version < 13) {
|
||||
if (pair.fcn->LoadKeys_V11_or_V12 == NULL)
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
return pair.fcn->LoadKeys_V11_or_V12(
|
||||
OEMCryptoResult result = pair.fcn->LoadKeys_V11_or_V12(
|
||||
pair.session, message, message_length, signature, signature_length,
|
||||
enc_mac_key_iv, enc_mac_key, num_keys, key_array, pst, pst_length);
|
||||
// Convert a vendor specific error, to make it actionable
|
||||
if (result == kOemCryptoResultVendorSpecificError1)
|
||||
result = OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE;
|
||||
return result;
|
||||
} else {
|
||||
if (pair.fcn->LoadKeys == NULL) return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
return pair.fcn->LoadKeys(pair.session, message, message_length,
|
||||
|
||||
@@ -94,6 +94,7 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out,
|
||||
reinterpret_cast<uint8_t*>(&(*iv)[0])) == 0) {
|
||||
LOGE("AesCbcKey::Encrypt: AES CBC setup failure: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -105,6 +106,7 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out,
|
||||
in.size()) == 0) {
|
||||
LOGE("AesCbcKey::Encrypt: encryption failure: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -113,8 +115,10 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out,
|
||||
&padding) == 0) {
|
||||
LOGE("AesCbcKey::Encrypt: PKCS7 padding failure: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
return false;
|
||||
}
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
out->resize(out_length + padding);
|
||||
return true;
|
||||
@@ -178,6 +182,7 @@ bool RsaPublicKey::Encrypt(const std::string& clear_message,
|
||||
return false;
|
||||
}
|
||||
|
||||
FreeKey(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -256,10 +261,15 @@ bool RsaPublicKey::VerifySignature(const std::string& message,
|
||||
return false;
|
||||
}
|
||||
EVP_PKEY *pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL ||
|
||||
EVP_PKEY_set1_RSA(pkey, rsa_key) != 1) {
|
||||
if (pkey == NULL) {
|
||||
LOGE("RsaPublicKey::VerifySignature: EVP_PKEY allocation failed");
|
||||
FreeKey(rsa_key);
|
||||
return false;
|
||||
}
|
||||
if (EVP_PKEY_set1_RSA(pkey, rsa_key) != 1) {
|
||||
LOGE("RsaPublicKey::VerifySignature: failed to wrap key in an EVP_PKEY");
|
||||
FreeKey(rsa_key);
|
||||
EVP_PKEY_free(pkey);
|
||||
return false;
|
||||
}
|
||||
FreeKey(rsa_key);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "crypto_session.h"
|
||||
#include "license.h"
|
||||
#include "log.h"
|
||||
#include "metrics_group.h"
|
||||
|
||||
namespace {
|
||||
std::string kEmptyString;
|
||||
@@ -139,7 +138,7 @@ CdmResponseType UsageTableHeader::UpdateEntry(CryptoSession* crypto_session,
|
||||
|
||||
CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number,
|
||||
DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics) {
|
||||
metrics::CryptoMetrics* metrics) {
|
||||
LOGV("UsageTableHeader::DeleteEntry: Lock");
|
||||
AutoLock auto_lock(usage_table_header_lock_);
|
||||
if (usage_entry_number >= usage_entry_info_.size())
|
||||
@@ -188,14 +187,13 @@ CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number,
|
||||
number_of_entries_to_be_deleted =
|
||||
usage_entry_info_.size() - swap_entry_number;
|
||||
}
|
||||
|
||||
return Shrink(metrics, number_of_entries_to_be_deleted);
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::MoveEntry(
|
||||
uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to_usage_entry_number, DeviceFiles* handle,
|
||||
metrics::MetricsGroup* metrics) {
|
||||
metrics::CryptoMetrics* metrics) {
|
||||
LOGV("UsageTableHeader::MoveEntry");
|
||||
|
||||
// crypto_session points to an object whose scope is this method or a test
|
||||
@@ -372,7 +370,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::Shrink(
|
||||
metrics::MetricsGroup* metrics,
|
||||
metrics::CryptoMetrics* metrics,
|
||||
uint32_t number_of_usage_entries_to_delete) {
|
||||
if (usage_entry_info_.empty()) {
|
||||
LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty");
|
||||
@@ -413,14 +411,14 @@ CdmResponseType UsageTableHeader::Shrink(
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::UpgradeFromUsageTable(
|
||||
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
|
||||
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
|
||||
UpgradeLicensesFromUsageTable(handle, metrics);
|
||||
UpgradeUsageInfoFromUsageTable(handle, metrics);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
|
||||
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
|
||||
// Fetch the key set IDs for each offline license. For each license
|
||||
// * retrieve the provider session token,
|
||||
// * create a new usage entry
|
||||
@@ -509,7 +507,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
}
|
||||
|
||||
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable(
|
||||
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
|
||||
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
|
||||
// Fetch all usage files. For each file retrieve all the usage info records
|
||||
// within the file. For each piece of usage information
|
||||
// * create a new usage entry
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "cdm_engine.h"
|
||||
#include "config_test_env.h"
|
||||
#include "initialization_data.h"
|
||||
#include "file_store.h"
|
||||
#include "license_request.h"
|
||||
#include "log.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
@@ -118,6 +119,10 @@ class WvCdmEnginePreProvTest : public testing::Test {
|
||||
virtual ~WvCdmEnginePreProvTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
session_opened_ = false;
|
||||
}
|
||||
|
||||
virtual void OpenSession() {
|
||||
CdmResponseType status =
|
||||
cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
|
||||
if (status == NEED_PROVISIONING) {
|
||||
@@ -129,6 +134,12 @@ class WvCdmEnginePreProvTest : public testing::Test {
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
if (cdm_engine_.IsProvisioned(kSecurityLevelL1)) {
|
||||
cdm_engine_.Unprovision(kSecurityLevelL1);
|
||||
}
|
||||
if (cdm_engine_.IsProvisioned(kSecurityLevelL3)) {
|
||||
cdm_engine_.Unprovision(kSecurityLevelL3);
|
||||
}
|
||||
if (session_opened_) {
|
||||
cdm_engine_.CloseSession(session_id_);
|
||||
session_opened_ = false;
|
||||
|
||||
@@ -144,8 +144,7 @@ using ::testing::StrEq;
|
||||
class CdmSessionTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
service_cert_ = new ServiceCertificate;
|
||||
cdm_session_.reset(new CdmSession(NULL));
|
||||
cdm_session_.reset(new CdmSession(NULL, &metrics_));
|
||||
// Inject testing mocks.
|
||||
license_parser_ = new MockCdmLicense(cdm_session_->session_id());
|
||||
cdm_session_->set_license_parser(license_parser_);
|
||||
@@ -157,12 +156,18 @@ class CdmSessionTest : public ::testing::Test {
|
||||
cdm_session_->set_file_handle(file_handle_);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
// Force the cdm_session_ to be deleted. This enforces a requirement that
|
||||
// the CDM session metrics exist at least as long as the CDM session.
|
||||
cdm_session_.reset();
|
||||
}
|
||||
|
||||
metrics::SessionMetrics metrics_;
|
||||
scoped_ptr<CdmSession> cdm_session_;
|
||||
MockCdmLicense* license_parser_;
|
||||
MockCryptoSession* crypto_session_;
|
||||
MockPolicyEngine* policy_engine_;
|
||||
MockDeviceFiles* file_handle_;
|
||||
ServiceCertificate* service_cert_;
|
||||
};
|
||||
|
||||
TEST_F(CdmSessionTest, InitWithBuiltInCertificate) {
|
||||
|
||||
@@ -2780,7 +2780,7 @@ TEST_P(DeviceFilesUsageInfoTest, RetrieveByProviderSessionToken) {
|
||||
std::string path = device_base_path_ + file_name;
|
||||
|
||||
size_t max_index_by_app_id = 0;
|
||||
for (size_t i = 0; i <= sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) {
|
||||
for (size_t i = 0; i < sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) {
|
||||
if (app_id == kUsageInfoTestData[i].app_id) max_index_by_app_id = i;
|
||||
}
|
||||
std::string file_data =
|
||||
@@ -2840,7 +2840,7 @@ TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) {
|
||||
std::vector<std::string> usage_data_fields;
|
||||
|
||||
size_t max_index_by_app_id = 0;
|
||||
for (size_t i = 0; i <= sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) {
|
||||
for (size_t i = 0; i < sizeof(kUsageInfoTestData) / sizeof(UsageInfo); ++i) {
|
||||
if (app_id == kUsageInfoTestData[i].app_id) {
|
||||
max_index_by_app_id = i;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "cdm_engine.h"
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "log.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "../../oemcrypto/mock/src/oemcrypto_key_mock.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "url_request.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
@@ -81,22 +83,21 @@ class WvGenericOperationsTest : public testing::Test {
|
||||
virtual void SetUp() {
|
||||
::testing::Test::SetUp();
|
||||
|
||||
ConfigTestEnv config(kContentProtectionStagingPlusProv30);
|
||||
ConfigTestEnv config(kContentProtectionStagingLicense);
|
||||
Properties::set_provisioning_messages_are_binary(false);
|
||||
|
||||
g_provisioning_service_certificate.assign(
|
||||
config.provisioning_service_certificate());
|
||||
g_license_service_certificate.assign(config.license_service_certificate());
|
||||
g_provisioning_server.assign(config.provisioning_server());
|
||||
|
||||
cdm_engine_ = NULL;
|
||||
|
||||
// TODO(fredgc or gmorgan): This should be updated for provisioning 3.0
|
||||
// Load test keybox. This keybox will be used by any CryptoSession
|
||||
// created by the CDM under test.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox());
|
||||
|
||||
// Perform CdmEngine setup
|
||||
cdm_engine_ = new CdmEngine(&file_system_);
|
||||
cdm_engine_.reset(new CdmEngine(&file_system_));
|
||||
|
||||
Provision();
|
||||
|
||||
@@ -124,7 +125,7 @@ class WvGenericOperationsTest : public testing::Test {
|
||||
|
||||
virtual void TearDown() {
|
||||
oec_util_session_.close();
|
||||
if (cdm_engine_ != NULL) {
|
||||
if (cdm_engine_.get() != NULL) {
|
||||
cdm_engine_->CloseSession(session_id_);
|
||||
}
|
||||
// OEMCrypto_Terminate() will be performed during the test class's
|
||||
@@ -246,25 +247,12 @@ class WvGenericOperationsTest : public testing::Test {
|
||||
LOGV("WvCdmEnginePreProvTest::Provision: http_message: \n%s\n",
|
||||
http_message.c_str());
|
||||
|
||||
// extract provisioning response from received message
|
||||
// Extracts signed response from JSON string, decodes base64 signed response
|
||||
const std::string kMessageStart = "\"signedResponse\": \"";
|
||||
const std::string kMessageEnd = "\"";
|
||||
std::string base64_response;
|
||||
EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd,
|
||||
&base64_response)) <<
|
||||
"Failed to extract signed serialized response from JSON response";
|
||||
|
||||
LOGV("WvCdmEnginePreProvTest::Provision: extracted response "
|
||||
"message: \n%s\n", base64_response.c_str());
|
||||
|
||||
ASSERT_EQ(NO_ERROR,
|
||||
cdm_engine_->HandleProvisioningResponse(base64_response,
|
||||
cdm_engine_->HandleProvisioningResponse(http_message,
|
||||
&cert, &wrapped_key));
|
||||
|
||||
ASSERT_EQ(NO_ERROR,
|
||||
cdm_engine_->SetServiceCertificate(
|
||||
g_license_service_certificate));
|
||||
cdm_engine_->SetServiceCertificate(g_license_service_certificate));
|
||||
}
|
||||
|
||||
// This CryptoSession object handles Initialization and Termination
|
||||
@@ -274,7 +262,7 @@ class WvGenericOperationsTest : public testing::Test {
|
||||
CryptoSession crypto_session_;
|
||||
|
||||
FileSystem file_system_;
|
||||
CdmEngine* cdm_engine_;
|
||||
std::unique_ptr<CdmEngine> cdm_engine_;
|
||||
std::string key_msg_;
|
||||
std::string session_id_;
|
||||
std::string server_url_;
|
||||
|
||||
@@ -81,7 +81,6 @@ class MockCdmEventListener : public WvCdmEventListener {
|
||||
class PolicyEngineConstraintsTest : public Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
mock_clock_ = new NiceMock<MockClock>();
|
||||
current_time_ = 0;
|
||||
|
||||
policy_engine_.reset(new PolicyEngine(kSessionId, &mock_event_listener_,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include "crypto_session.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
@@ -42,26 +41,9 @@ const std::string kTestSignedCertificate = a2bs_hex(
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
class MockCryptoSession : public CryptoSession {
|
||||
public:
|
||||
MockCryptoSession() : CryptoSession(NULL) { }
|
||||
MOCK_METHOD2(GetRandom, bool(size_t, uint8_t*));
|
||||
};
|
||||
|
||||
class ServiceCertificateTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() { crypto_session_ = new MockCryptoSession(); }
|
||||
|
||||
virtual void TearDown() {
|
||||
if (crypto_session_) delete crypto_session_;
|
||||
}
|
||||
|
||||
void CreateServiceCertificate() {
|
||||
service_certificate_ = new ServiceCertificate();
|
||||
}
|
||||
|
||||
ServiceCertificate* service_certificate_;
|
||||
MockCryptoSession* crypto_session_;
|
||||
ServiceCertificate service_certificate_;
|
||||
};
|
||||
|
||||
class StubCdmClientPropertySet : public CdmClientPropertySet {
|
||||
@@ -78,11 +60,11 @@ class StubCdmClientPropertySet : public CdmClientPropertySet {
|
||||
virtual bool use_privacy_mode() const { return use_privacy_mode_; }
|
||||
|
||||
virtual const std::string& service_certificate() const {
|
||||
return service_certificate_;
|
||||
return raw_service_certificate_;
|
||||
}
|
||||
|
||||
virtual void set_service_certificate(const std::string& cert) {
|
||||
service_certificate_ = cert;
|
||||
raw_service_certificate_ = cert;
|
||||
}
|
||||
|
||||
virtual bool is_session_sharing_enabled() const {
|
||||
@@ -99,7 +81,7 @@ class StubCdmClientPropertySet : public CdmClientPropertySet {
|
||||
|
||||
private:
|
||||
std::string security_level_;
|
||||
std::string service_certificate_;
|
||||
std::string raw_service_certificate_;
|
||||
bool use_privacy_mode_;
|
||||
bool is_session_sharing_enabled_;
|
||||
uint32_t session_sharing_id_;
|
||||
@@ -107,11 +89,8 @@ class StubCdmClientPropertySet : public CdmClientPropertySet {
|
||||
};
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitSuccess) {
|
||||
MockCryptoSession crypto_session;
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1);
|
||||
EXPECT_FALSE(service_certificate_->has_certificate());
|
||||
service_certificate_.Init(kTestSessionId1);
|
||||
EXPECT_FALSE(service_certificate_.has_certificate());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitPrivacyModeRequired) {
|
||||
@@ -122,9 +101,8 @@ TEST_F(ServiceCertificateTest, InitPrivacyModeRequired) {
|
||||
Properties::Init();
|
||||
Properties::AddSessionPropertySet(kTestSessionId1, &property_set);
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1);
|
||||
EXPECT_FALSE(service_certificate_->has_certificate());
|
||||
service_certificate_.Init(kTestSessionId1);
|
||||
EXPECT_FALSE(service_certificate_.has_certificate());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitServiceCertificatePresent) {
|
||||
@@ -136,13 +114,12 @@ TEST_F(ServiceCertificateTest, InitServiceCertificatePresent) {
|
||||
Properties::Init();
|
||||
Properties::AddSessionPropertySet(kTestSessionId1, &property_set);
|
||||
|
||||
CreateServiceCertificate();
|
||||
std::string service_certificate;
|
||||
std::string raw_service_certificate;
|
||||
EXPECT_TRUE(Properties::GetServiceCertificate(kTestSessionId1,
|
||||
&service_certificate));
|
||||
&raw_service_certificate));
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
service_certificate_->Init(service_certificate));
|
||||
EXPECT_TRUE(service_certificate_->has_certificate());
|
||||
service_certificate_.Init(raw_service_certificate));
|
||||
EXPECT_TRUE(service_certificate_.has_certificate());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, SetServiceCertificate) {
|
||||
@@ -153,9 +130,8 @@ TEST_F(ServiceCertificateTest, SetServiceCertificate) {
|
||||
Properties::Init();
|
||||
Properties::AddSessionPropertySet(kTestSessionId1, &property_set);
|
||||
|
||||
CreateServiceCertificate();
|
||||
EXPECT_EQ(NO_ERROR, service_certificate_->Init(kTestSignedCertificate));
|
||||
EXPECT_TRUE(service_certificate_->has_certificate());
|
||||
EXPECT_EQ(NO_ERROR, service_certificate_.Init(kTestSignedCertificate));
|
||||
EXPECT_TRUE(service_certificate_.has_certificate());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ TEST_F(UsageTableHeaderTest, UpdateEntry) {
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) {
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector);
|
||||
uint32_t usage_entry_number = kUsageEntryInfoVector.size();
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_NE(NO_ERROR, usage_table_header_->DeleteEntry(
|
||||
usage_entry_number, device_files_, &metrics));
|
||||
@@ -426,7 +426,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) {
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -462,7 +462,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) {
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -507,7 +507,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) {
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop2
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -558,7 +558,7 @@ TEST_F(UsageTableHeaderTest,
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
device_files_->DeleteAllLicenses();
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
@@ -608,7 +608,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) {
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -671,7 +671,7 @@ TEST_F(UsageTableHeaderTest,
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[usage_entry_info_vector.size() - 1].key_set_id,
|
||||
@@ -739,7 +739,7 @@ TEST_F(UsageTableHeaderTest,
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
uint32_t usage_entry_number_after_deleted_entry =
|
||||
usage_entry_number_to_be_deleted + 1;
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -812,7 +812,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) {
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
|
||||
uint32_t usage_entry_number_to_be_deleted =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(
|
||||
@@ -867,7 +867,7 @@ TEST_F(UsageTableHeaderTest,
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_usage_entry_number].key_set_id,
|
||||
@@ -933,7 +933,7 @@ TEST_F(UsageTableHeaderTest,
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
@@ -1007,7 +1007,7 @@ TEST_F(UsageTableHeaderTest,
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
|
||||
@@ -1085,7 +1085,7 @@ TEST_F(UsageTableHeaderTest,
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
|
||||
.Times(2)
|
||||
@@ -1157,7 +1157,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) {
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_usage_entry_number].key_set_id,
|
||||
@@ -1271,7 +1271,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) {
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
|
||||
uint32_t last_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
|
||||
.Times(2)
|
||||
@@ -1371,7 +1371,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) {
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_TRUE(device_files_->StoreLicense(
|
||||
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
|
||||
@@ -1490,7 +1490,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) {
|
||||
usage_entry_info_vector.size() - 5; // kUsageEntryInfoSecureStop1
|
||||
uint32_t last_valid_usage_entry_number =
|
||||
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop3
|
||||
metrics::MetricsGroup metrics;
|
||||
metrics::CryptoMetrics metrics;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
|
||||
.Times(2)
|
||||
|
||||
Reference in New Issue
Block a user