Merges to android Pi release (part 4)
These are a set of CLs merged from the wv cdm repo to the android repo. * Correct RELEASE_ALL_USAGE_INFO_ERRORs Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/28742 ] RELEASE_ALL_USAGE_INFO_ERROR_4 and 5 were introduced and made use of in http://go/wvgerrit/24022 (branch: oc-dev). The error code definitions were merged over in http://go/wvgerrit/24602. When http://go/wvgerrit/24622 from cdm_partners_3.2 was merged to master (http://go/wvgerrit/27723) there was conflict in error codes. The error codes were adjusted to RELEASE_ALL_USAGE_INFO_ERROR_3 and 4 and were made use of. To avoid renaming the errors between oc-dev and master, new errors RELEASE_ALL_USAGE_INFO_ERROR_6 and 7 have been added to handle the scenarios noted in the merge from cdm_partner_3.2. The other errors have been reverted back to RELEASE_ALL_USAGE_INFO_ERROR_4 and 5. They will be used when http://go/wvgerrit/24602 is merged. * Address compilation issues Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/28740 ] These changes enable compilation of most of the cdm code on android expect for OEMCrypto unit tests (b/62739406) on wv master. * Add property for binary/base64 provisioning msgs. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/28074 ] Property is "provisioning_messages_are_binary". Its default setting is false in the CE CDM, but it can be overridden by integrators. Added section to integration guide that discusses Provisioning Server message formats and the new property. Link: https://docs.google.com/document/d/1cBVbhgrajLpDe2W3_vzLzUqzpdDt73chvm4_sZlZlS8/edit#heading=h.hgxw53ddw7jo BUG: 71650075 Test: Not currently passing. Will be addressed in a subsequent commit in the chain. Change-Id: I9168193819974d1ff65d9a94dbd762e45ecc43ca
This commit is contained in:
@@ -35,6 +35,7 @@ LOCAL_SRC_FILES := \
|
||||
$(CORE_SRC_DIR)/policy_engine.cpp \
|
||||
$(CORE_SRC_DIR)/privacy_crypto_openssl.cpp \
|
||||
$(CORE_SRC_DIR)/service_certificate.cpp \
|
||||
$(CORE_SRC_DIR)/usage_table_header.cpp \
|
||||
$(SRC_DIR)/wv_content_decryption_module.cpp \
|
||||
$(METRICS_SRC_DIR)/distribution.cpp \
|
||||
$(METRICS_SRC_DIR)/event_metric.cpp \
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace wvcdm {
|
||||
class CdmClientPropertySet;
|
||||
class ServiceCertificate;
|
||||
class WvCdmEventListener;
|
||||
class UsageTableHeader;
|
||||
|
||||
class CdmSession {
|
||||
public:
|
||||
@@ -42,7 +43,7 @@ class CdmSession {
|
||||
virtual CdmResponseType RestoreOfflineSession(
|
||||
const CdmKeySetId& key_set_id, const CdmLicenseType license_type);
|
||||
virtual CdmResponseType RestoreUsageSession(
|
||||
const CdmKeyMessage& key_request, const CdmKeyResponse& key_response);
|
||||
const DeviceFiles::CdmUsageData& usage_data);
|
||||
|
||||
virtual const CdmSessionId& session_id() { return session_id_; }
|
||||
virtual const CdmKeySetId& key_set_id() { return key_set_id_; }
|
||||
@@ -86,6 +87,9 @@ class CdmSession {
|
||||
// ReleaseKey() - Accept response and release key.
|
||||
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
|
||||
|
||||
virtual CdmResponseType DeleteUsageEntry(
|
||||
const DeviceFiles::CdmUsageData& usage_data);
|
||||
|
||||
virtual bool IsKeyLoaded(const KeyId& key_id);
|
||||
virtual int64_t GetDurationRemaining();
|
||||
|
||||
@@ -104,7 +108,8 @@ class CdmSession {
|
||||
// Delete usage information for the list of tokens, |provider_session_tokens|.
|
||||
virtual CdmResponseType DeleteMultipleUsageInformation(
|
||||
const std::vector<std::string>& provider_session_tokens);
|
||||
virtual CdmResponseType UpdateUsageInformation();
|
||||
virtual CdmResponseType UpdateUsageTableInformation();
|
||||
virtual CdmResponseType UpdateUsageEntryInformation();
|
||||
|
||||
virtual bool is_initial_usage_update() { return is_initial_usage_update_; }
|
||||
virtual bool is_usage_update_needed() { return is_usage_update_needed_; }
|
||||
@@ -118,6 +123,9 @@ class CdmSession {
|
||||
virtual bool is_temporary() { return is_temporary_; }
|
||||
virtual bool license_received() { return license_received_; }
|
||||
|
||||
virtual CdmUsageSupportType get_usage_support_type()
|
||||
{ return usage_support_type_; }
|
||||
|
||||
// ReleaseCrypto() - Closes the underlying crypto session but leaves this
|
||||
// object alive. It is invalid to call any method that requires a crypto
|
||||
// session after calling this. Since calling this renders this object mostly
|
||||
@@ -170,6 +178,8 @@ class CdmSession {
|
||||
CdmResponseType StoreLicense();
|
||||
bool StoreLicense(DeviceFiles::LicenseState state);
|
||||
|
||||
bool UpdateUsageInfo();
|
||||
|
||||
// These setters are for testing only. Takes ownership of the pointers.
|
||||
void set_license_parser(CdmLicense* license_parser);
|
||||
void set_crypto_session(CryptoSession* crypto_session);
|
||||
@@ -203,11 +213,18 @@ class CdmSession {
|
||||
SecurityLevel requested_security_level_;
|
||||
CdmAppParameterMap app_parameters_;
|
||||
|
||||
// decryption and usage flags
|
||||
// decryption flags
|
||||
bool is_initial_decryption_;
|
||||
bool has_decrypted_since_last_report_; // ... last report to policy engine.
|
||||
|
||||
// Usage related flags and data
|
||||
bool is_initial_usage_update_;
|
||||
bool is_usage_update_needed_;
|
||||
CdmUsageSupportType usage_support_type_;
|
||||
UsageTableHeader* usage_table_header_;
|
||||
uint32_t usage_entry_number_;
|
||||
CdmUsageEntry usage_entry_;
|
||||
std::string usage_provider_session_token_;
|
||||
|
||||
// information useful for offline and usage scenarios
|
||||
CdmKeyMessage key_request_;
|
||||
|
||||
@@ -93,7 +93,7 @@ class CryptoSession {
|
||||
|
||||
// Usage related methods
|
||||
virtual bool UsageInformationSupport(bool* has_support);
|
||||
virtual CdmResponseType UpdateUsageInformation();
|
||||
virtual CdmResponseType UpdateUsageInformation(); // only for OEMCrypto v9-12
|
||||
virtual CdmResponseType DeactivateUsageInformation(
|
||||
const std::string& provider_session_token);
|
||||
virtual CdmResponseType GenerateUsageReport(
|
||||
|
||||
@@ -154,9 +154,15 @@ class DeviceFiles {
|
||||
virtual bool ListUsageInfoFiles(std::vector<std::string>* usage_file_names);
|
||||
virtual bool RetrieveUsageInfo(const std::string& usage_info_file_name,
|
||||
std::vector<CdmUsageData>* usage_data);
|
||||
virtual bool RetrieveUsageInfo(const std::string& usage_info_file_name,
|
||||
const std::string& provider_session_token,
|
||||
CdmUsageData* usage_data);
|
||||
// This method overwrites rather than appends data to the usage file
|
||||
virtual bool StoreUsageInfo(const std::string& usage_info_file_name,
|
||||
const std::vector<CdmUsageData>& usage_data);
|
||||
virtual bool UpdateUsageInfo(const std::string& usage_info_file_name,
|
||||
const std::string& provider_session_token,
|
||||
const CdmUsageData& usage_data);
|
||||
|
||||
virtual bool StoreHlsAttributes(const std::string& key_set_id,
|
||||
const CdmHlsMethod method,
|
||||
|
||||
@@ -62,6 +62,10 @@ class CdmLicense {
|
||||
return is_offline_;
|
||||
}
|
||||
|
||||
static bool ExtractProviderSessionToken(
|
||||
const CdmKeyResponse& license_response,
|
||||
std::string* provider_session_token);
|
||||
|
||||
private:
|
||||
|
||||
CdmResponseType HandleKeyErrorResponse(
|
||||
|
||||
@@ -40,6 +40,12 @@ class Properties {
|
||||
static inline bool use_certificates_as_identification() {
|
||||
return use_certificates_as_identification_;
|
||||
}
|
||||
static inline bool provisioning_messages_are_binary() {
|
||||
return provisioning_messages_are_binary_;
|
||||
}
|
||||
static void set_provisioning_messages_are_binary(bool flag) {
|
||||
provisioning_messages_are_binary_ = flag;
|
||||
}
|
||||
static inline bool security_level_path_backward_compatibility_support() {
|
||||
return security_level_path_backward_compatibility_support_;
|
||||
}
|
||||
@@ -111,6 +117,7 @@ class Properties {
|
||||
static bool oem_crypto_use_userspace_buffers_;
|
||||
static bool use_certificates_as_identification_;
|
||||
static bool security_level_path_backward_compatibility_support_;
|
||||
static bool provisioning_messages_are_binary_;
|
||||
static scoped_ptr<CdmClientPropertySetMap> session_property_set_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(Properties);
|
||||
|
||||
@@ -7,48 +7,36 @@
|
||||
#include <vector>
|
||||
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "lock.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "metrics_group.h"
|
||||
#include "scoped_ptr.h"
|
||||
#include "timer_metric.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
class FileSystem;
|
||||
class CryptoSession;
|
||||
|
||||
// Offline licenses/secure stops may be securely tracked using usage
|
||||
// tables (OEMCrypto v9-12) or usage table headers+usage entries
|
||||
// (OEMCrypto v13+). This class assists with the latter, synchronizing
|
||||
// access to usage table header and associated data-structures and controlling
|
||||
// when they are read in or written out to non-secure persistent storage.
|
||||
//
|
||||
// Each OEMCrypto (for each security level) will maintain its own usage table
|
||||
// header. Each license will have an associated usage entry that is also
|
||||
// stored in persistent memory and is noted in the usage table header.
|
||||
// Usage entry information will be verified when licenses are loaded.
|
||||
//
|
||||
// OEMCrypto for each security level have their own usage table
|
||||
// headers. They are loaded on initialization and written out periodically.
|
||||
// The lifecycle of this class is tied to when OEMCrypto is
|
||||
// initialized/terminated.
|
||||
//
|
||||
// Sessions and licenses are however handled by CdmSession and so most
|
||||
// calls to maniplate the usage table header related to usage entries
|
||||
// are by CdmSession.
|
||||
//
|
||||
// The UsageTableHeader class is a singleton that CDM sessions will share.
|
||||
// A separate object will be created for each security level.
|
||||
// The class synchronizes access to usage table header and associated
|
||||
// data-structures and controls when they are read in or written out to
|
||||
// non-secure persistent storage.
|
||||
// Upgrades from a fixed size usage table (supported by previous
|
||||
// versions of the OEMCrypto API v9-12) are handled by this class.
|
||||
// |usage_entry| and |usage_entry_number|s need to be saved in the license
|
||||
// |usage_entry| and |usage_entry_number| need to be saved in the license
|
||||
// and usage info records by the caller.
|
||||
class UsageTableHeader {
|
||||
public:
|
||||
UsageTableHeader();
|
||||
virtual ~UsageTableHeader() {}
|
||||
|
||||
// This methods instantiates or retrieves a usage table header singleton of
|
||||
// appropriate security level as specified by the |crypto_session|
|
||||
// object.
|
||||
// |crypto_session| is used to create or load a usage master table and
|
||||
// not cached beyound this call.
|
||||
bool Init(CdmSecurityLevel security_level, CryptoSession* crypto_session);
|
||||
static UsageTableHeader* GetInstance(FileSystem* file_system,
|
||||
CryptoSession* crypto_session_);
|
||||
virtual ~UsageTableHeader() {}
|
||||
|
||||
// |persistent_license| false indicates usage info record
|
||||
CdmResponseType AddEntry(CryptoSession* crypto_session,
|
||||
@@ -65,69 +53,56 @@ class UsageTableHeader {
|
||||
// The licenses or usage info records specified by |usage_entry_number|
|
||||
// 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::CryptoMetrics* metrics);
|
||||
CdmResponseType DeleteEntry(uint32_t usage_entry_number);
|
||||
CdmResponseType MoveEntry(uint32_t from_usage_entry_number,
|
||||
const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to_usage_entry_number);
|
||||
|
||||
private:
|
||||
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
|
||||
const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to /* usage entry number */,
|
||||
DeviceFiles* handle,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
UsageTableHeader(FileSystem* file_system, CryptoSession* crypto_session,
|
||||
CdmSecurityLevel security_level);
|
||||
|
||||
CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
CdmResponseType GetEntry(uint32_t usage_entry_number,
|
||||
CdmUsageEntry* usage_entry);
|
||||
CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle,
|
||||
CdmResponseType StoreEntry(uint32_t usage_entry_number,
|
||||
const CdmUsageEntry& usage_entry);
|
||||
|
||||
CdmResponseType Shrink(metrics::CryptoMetrics* metrics,
|
||||
uint32_t number_of_usage_entries_to_delete);
|
||||
bool DeleteLastEntry();
|
||||
|
||||
CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
bool UpgradeLicensesFromUsageTable(DeviceFiles* handle,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle,
|
||||
metrics::CryptoMetrics* metrics);
|
||||
CdmResponseType UpgradeFromUsageTable();
|
||||
|
||||
// Indicates whether one of more license/usage records failed to be upgraded.
|
||||
bool UpgradeLicensesFromUsageTable();
|
||||
bool UpgradeUsageInfoFromUsageTable();
|
||||
|
||||
virtual bool is_inited() { return is_inited_; }
|
||||
|
||||
virtual bool CreateDummyOldUsageEntry(CryptoSession* crypto_session);
|
||||
SecurityLevel GetSecurityLevel() {
|
||||
return security_level_ == kSecurityLevelL3 ? kLevel3 : kLevelDefault;
|
||||
}
|
||||
|
||||
static UsageTableHeader* usage_table_header_l1_;
|
||||
static UsageTableHeader* usage_table_header_l3_;
|
||||
|
||||
// This handle and file system is only to be used when accessing
|
||||
// usage_table_header. Usage entries should use the file system provided
|
||||
// by CdmSession.
|
||||
scoped_ptr<DeviceFiles> file_handle_;
|
||||
scoped_ptr<FileSystem> file_system_;
|
||||
CdmSecurityLevel security_level_;
|
||||
SecurityLevel requested_security_level_;
|
||||
|
||||
CdmUsageTableHeader usage_table_header_;
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_;
|
||||
|
||||
metrics::MetricsGroup metrics_;
|
||||
metrics::TimerMetric life_span_;
|
||||
|
||||
// Lock to ensure that a single object is created for each security level
|
||||
// and data member to represent whether an object has been correctly
|
||||
// initialized.
|
||||
bool is_inited_;
|
||||
static Lock initialization_lock_;
|
||||
|
||||
// Synchonizes access to the Usage Table Header and bookkeeping
|
||||
// data-structures
|
||||
Lock usage_table_header_lock_;
|
||||
|
||||
// Test related declarations
|
||||
friend class UsageTableHeaderTest;
|
||||
|
||||
// These setters are for testing only. Takes ownership of the pointers.
|
||||
void SetDeviceFiles(DeviceFiles* device_files) {
|
||||
file_handle_.reset(device_files);
|
||||
}
|
||||
void SetCryptoSession(CryptoSession* crypto_session) {
|
||||
test_crypto_session_.reset(crypto_session);
|
||||
}
|
||||
|
||||
// Test related data members
|
||||
scoped_ptr<CryptoSession> test_crypto_session_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(UsageTableHeader);
|
||||
};
|
||||
|
||||
|
||||
@@ -285,15 +285,15 @@ enum CdmResponseType {
|
||||
INVALID_USAGE_ENTRY_NUMBER_MODIFICATION, /* 240 */
|
||||
USAGE_INVALID_NEW_ENTRY,
|
||||
USAGE_INVALID_PARAMETERS_1,
|
||||
USAGE_RETRIEVE_LICENSE_FAILED,
|
||||
USAGE_RETRIEVE_USAGE_INFO_FAILED,
|
||||
USAGE_RETRIEVE_INVALID_STORAGE_TYPE, /* 245 */
|
||||
USAGE_GET_ENTRY_RETRIEVE_LICENSE_FAILED,
|
||||
USAGE_GET_ENTRY_RETRIEVE_USAGE_INFO_FAILED,
|
||||
USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE, /* 245 */
|
||||
USAGE_ENTRY_NUMBER_MISMATCH,
|
||||
USAGE_STORE_LICENSE_FAILED,
|
||||
USAGE_STORE_USAGE_INFO_FAILED,
|
||||
USAGE_INVALID_LOAD_ENTRY,
|
||||
RELEASE_ALL_USAGE_INFO_ERROR_3, /* 250 */
|
||||
RELEASE_ALL_USAGE_INFO_ERROR_4,
|
||||
RELEASE_ALL_USAGE_INFO_ERROR_4, /* 250 */
|
||||
RELEASE_ALL_USAGE_INFO_ERROR_5,
|
||||
RELEASE_USAGE_INFO_FAILED,
|
||||
INCORRECT_USAGE_SUPPORT_TYPE_1,
|
||||
INCORRECT_USAGE_SUPPORT_TYPE_2,
|
||||
@@ -314,6 +314,11 @@ enum CdmResponseType {
|
||||
PARSE_RESPONSE_ERROR_2,
|
||||
PARSE_RESPONSE_ERROR_3, /* 270 */
|
||||
PARSE_RESPONSE_ERROR_4,
|
||||
USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED,
|
||||
USAGE_STORE_ENTRY_RETRIEVE_USAGE_INFO_FAILED,
|
||||
USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE,
|
||||
RELEASE_ALL_USAGE_INFO_ERROR_6, /* 275 */
|
||||
RELEASE_ALL_USAGE_INFO_ERROR_7,
|
||||
};
|
||||
|
||||
enum CdmKeyStatus {
|
||||
|
||||
@@ -1055,7 +1055,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
CdmResponseType status = usage_session_->Init(usage_property_set_.get());
|
||||
if (NO_ERROR != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error");
|
||||
LOGE("CdmEngine::GetUsageInfo: session init error: %d", status);
|
||||
return status;
|
||||
}
|
||||
DeviceFiles handle(file_system_);
|
||||
@@ -1067,11 +1067,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
CdmKeyMessage license_request;
|
||||
CdmKeyResponse license_response;
|
||||
std::string usage_entry;
|
||||
uint32_t usage_entry_number = 0;
|
||||
DeviceFiles::CdmUsageData usage_data;
|
||||
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
ssid, &license_request,
|
||||
&license_response, &usage_entry,
|
||||
&usage_entry_number)) {
|
||||
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_));
|
||||
@@ -1085,16 +1083,14 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
return GET_USAGE_INFO_ERROR_2;
|
||||
}
|
||||
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
ssid, &license_request,
|
||||
&license_response, &usage_entry,
|
||||
&usage_entry_number)) {
|
||||
ssid, &usage_data)) {
|
||||
// No entry found for that ssid.
|
||||
return USAGE_INFO_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
status =
|
||||
usage_session_->RestoreUsageSession(license_request,license_response);
|
||||
usage_session_->RestoreUsageSession(usage_data);
|
||||
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: restore usage session error %d", status);
|
||||
@@ -1167,9 +1163,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
return GET_USAGE_INFO_ERROR_3;
|
||||
}
|
||||
|
||||
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&license_info)) {
|
||||
&usage_data)) {
|
||||
LOGE("CdmEngine::GetUsageInfo: unable to read usage information");
|
||||
return GET_USAGE_INFO_ERROR_4;
|
||||
}
|
||||
@@ -1178,16 +1174,15 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
|
||||
return INVALID_PARAMETERS_ENG_10;
|
||||
}
|
||||
if (0 == license_info.size()) {
|
||||
if (0 == usage_data.size()) {
|
||||
usage_info->resize(0);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
usage_info->resize(kUsageReportsPerRequest);
|
||||
|
||||
uint32_t index = rand() % license_info.size();
|
||||
status = usage_session_->RestoreUsageSession(license_info[index].first,
|
||||
license_info[index].second);
|
||||
uint32_t index = rand() % usage_data.size();
|
||||
status = usage_session_->RestoreUsageSession(usage_data[index]);
|
||||
if (KEY_ADDED != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: restore usage session (%d) error %ld", index,
|
||||
status);
|
||||
@@ -1222,12 +1217,12 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: unable to initialize device files");
|
||||
return RELEASE_ALL_USAGE_INFO_ERROR_3;
|
||||
return RELEASE_ALL_USAGE_INFO_ERROR_6;
|
||||
}
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(app_id, &provider_session_tokens)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete usage records");
|
||||
return RELEASE_ALL_USAGE_INFO_ERROR_4;
|
||||
return RELEASE_ALL_USAGE_INFO_ERROR_7;
|
||||
}
|
||||
|
||||
if (provider_session_tokens.size() == 0UL) {
|
||||
@@ -1258,25 +1253,49 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) {
|
||||
DeviceFiles handle(file_system_);
|
||||
if (handle.Init(static_cast<CdmSecurityLevel>(j))) {
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure"
|
||||
"stops", j);
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
|
||||
} else {
|
||||
SecurityLevel security_level =
|
||||
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
usage_property_set_->set_security_level(security_level);
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
usage_session_->Init(usage_property_set_.get());
|
||||
CdmResponseType status2 = usage_session_->
|
||||
DeleteMultipleUsageInformation(provider_session_tokens);
|
||||
if (status2 != NO_ERROR) {
|
||||
status = status2;
|
||||
SecurityLevel security_level =
|
||||
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
usage_property_set_->set_security_level(security_level);
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
usage_session_->Init(usage_property_set_.get());
|
||||
|
||||
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
if (!handle.RetrieveUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&usage_data)) {
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_4;
|
||||
} else {
|
||||
for (size_t k = 0; k < usage_data.size(); ++k) {
|
||||
CdmResponseType status2 =
|
||||
usage_session_->DeleteUsageEntry(usage_data[k]);
|
||||
if (status == NO_ERROR && status2 != NO_ERROR)
|
||||
status = status2;
|
||||
}
|
||||
}
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_5;
|
||||
}
|
||||
} else if (usage_session_->get_usage_support_type()
|
||||
== kUsageTableSupport) {
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&provider_session_tokens)) {
|
||||
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure"
|
||||
"stops", j);
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
|
||||
} else {
|
||||
CdmResponseType status2 = usage_session_->
|
||||
DeleteMultipleUsageInformation(provider_session_tokens);
|
||||
if (status2 != NO_ERROR) {
|
||||
status = status2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1337,24 +1356,20 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
std::string app_id;
|
||||
session->GetApplicationId(&app_id);
|
||||
|
||||
std::string provider_session_token;
|
||||
CdmKeyMessage key_message;
|
||||
CdmKeyResponse key_response;
|
||||
std::string usage_entry;
|
||||
uint32_t usage_entry_number = 0;
|
||||
DeviceFiles::CdmUsageData usage_data;
|
||||
if (!handle.RetrieveUsageInfoByKeySetId(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), key_set_id,
|
||||
&provider_session_token, &key_message, &key_response,
|
||||
&usage_entry, &usage_entry_number)) {
|
||||
&(usage_data.provider_session_token),
|
||||
&(usage_data.license_request),
|
||||
&(usage_data.license), &(usage_data.usage_entry),
|
||||
&(usage_data.usage_entry_number))) {
|
||||
LOGE("CdmEngine::LoadUsageSession: unable to find usage information");
|
||||
return LOAD_USAGE_INFO_MISSING;
|
||||
}
|
||||
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = session->RestoreUsageSession(
|
||||
key_message,
|
||||
key_response),
|
||||
status = session->RestoreUsageSession(usage_data),
|
||||
session->GetMetrics(),
|
||||
cdm_session_restore_usage_session_,
|
||||
status);
|
||||
@@ -1596,14 +1611,24 @@ void CdmEngine::OnTimerEvent() {
|
||||
for (CdmSessionList::iterator iter = sessions.begin();
|
||||
iter != sessions.end(); ++iter) {
|
||||
(*iter)->reset_usage_flags();
|
||||
if ((*iter)->get_usage_support_type() == kUsageEntrySupport)
|
||||
(*iter)->UpdateUsageEntryInformation();
|
||||
|
||||
if (!has_usage_been_updated) {
|
||||
// usage is updated for all sessions so this needs to be
|
||||
// called only once per update usage information period
|
||||
CdmResponseType status = (*iter)->UpdateUsageInformation();
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
if ((*iter)->get_usage_support_type() == kUsageTableSupport) {
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = (*iter)->UpdateUsageTableInformation(),
|
||||
(*iter)->GetMetrics(),
|
||||
crypto_session_update_usage_information_,
|
||||
status);
|
||||
if (NO_ERROR != status) {
|
||||
LOGW("Update usage information failed: %d", status);
|
||||
} else {
|
||||
has_usage_been_updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_event_listener.h"
|
||||
#include "usage_table_header.h"
|
||||
|
||||
namespace {
|
||||
const size_t kKeySetIdLength = 14;
|
||||
@@ -39,8 +40,20 @@ CdmSession::CdmSession(FileSystem* file_system) :
|
||||
has_decrypted_since_last_report_(false),
|
||||
is_initial_usage_update_(true),
|
||||
is_usage_update_needed_(false),
|
||||
usage_support_type_(kNonSecureUsageSupport),
|
||||
usage_table_header_(NULL),
|
||||
usage_entry_number_(0),
|
||||
mock_license_parser_in_use_(false),
|
||||
mock_policy_engine_in_use_(false) {
|
||||
CdmResponseType sts =
|
||||
crypto_session_->GetUsageSupportType(&usage_support_type_);
|
||||
|
||||
if (sts != NO_ERROR) {
|
||||
LOGW("CdmSession::CdmSession: Failed to get usage support type");
|
||||
}
|
||||
if (usage_support_type_ == kUsageEntrySupport)
|
||||
usage_table_header_ = UsageTableHeader::GetInstance(file_system,
|
||||
crypto_session_.get());
|
||||
life_span_.Start();
|
||||
}
|
||||
|
||||
@@ -188,28 +201,37 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
int64_t playback_start_time;
|
||||
int64_t last_playback_time;
|
||||
int64_t grace_period_end_time;
|
||||
std::string usage_entry;
|
||||
uint32_t usage_entry_number = 0;
|
||||
|
||||
if (!file_handle_->RetrieveLicense(
|
||||
key_set_id, &license_state, &offline_init_data_, &key_request_,
|
||||
&key_response_, &offline_key_renewal_request_,
|
||||
&offline_key_renewal_response_, &offline_release_server_url_,
|
||||
&playback_start_time, &last_playback_time, &grace_period_end_time,
|
||||
&app_parameters_, &usage_entry, &usage_entry_number)) {
|
||||
LOGE("CdmSession::Init failed to retrieve license. key set id = %s",
|
||||
key_set_id.c_str());
|
||||
&app_parameters_, &usage_entry_, &usage_entry_number_)) {
|
||||
LOGE("CdmSession::RestoreOfflineSession: failed to retrieve license. "
|
||||
"key set id = %s", key_set_id.c_str());
|
||||
return GET_LICENSE_ERROR;
|
||||
}
|
||||
|
||||
// Do not restore a released offline license, unless a release retry
|
||||
if (!(license_type == kLicenseTypeRelease ||
|
||||
license_state == DeviceFiles::kLicenseStateActive)) {
|
||||
LOGE("CdmSession::Init invalid offline license state = %d, type = %d",
|
||||
license_state, license_type);
|
||||
LOGE("CdmSession::RestoreOfflineSession: invalid offline license state = "
|
||||
"%d, type = %d", license_state, license_type);
|
||||
return GET_RELEASED_LICENSE_ERROR;
|
||||
}
|
||||
|
||||
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_type == kLicenseTypeRelease) {
|
||||
if (!license_parser_->RestoreLicenseForRelease(key_request_,
|
||||
key_response_)) {
|
||||
@@ -223,6 +245,20 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
}
|
||||
}
|
||||
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
CdmResponseType sts =
|
||||
usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("CdmSession::RestoreOfflineSession failed to update usage entry = "
|
||||
"%d", sts);
|
||||
return sts;
|
||||
}
|
||||
if (!StoreLicense(license_state)) {
|
||||
LOGW("CdmSession::RestoreUsageSession: unable to save updated usage "
|
||||
"info");
|
||||
}
|
||||
}
|
||||
|
||||
license_received_ = true;
|
||||
is_offline_ = true;
|
||||
is_release_ = license_type == kLicenseTypeRelease;
|
||||
@@ -230,14 +266,45 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::RestoreUsageSession(
|
||||
const CdmKeyMessage& key_request, const CdmKeyResponse& key_response) {
|
||||
key_request_ = key_request;
|
||||
key_response_ = key_response;
|
||||
const DeviceFiles::CdmUsageData& usage_data) {
|
||||
if (!key_set_id_.empty()) {
|
||||
file_handle_->UnreserveLicenseId(key_set_id_);
|
||||
}
|
||||
key_set_id_ = usage_data.key_set_id;
|
||||
key_request_ = usage_data.license_request;
|
||||
key_response_ = usage_data.license;
|
||||
usage_entry_ = usage_data.usage_entry;
|
||||
usage_entry_number_ = usage_data.usage_entry_number;
|
||||
usage_provider_session_token_ = usage_data.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::RestoreUsageSession: failed to load usage entry = %d",
|
||||
sts);
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
|
||||
if (!license_parser_->RestoreLicenseForRelease(key_request_, key_response_)) {
|
||||
return RELEASE_LICENSE_ERROR_2;
|
||||
}
|
||||
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
CdmResponseType sts =
|
||||
usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("CdmSession::RestoreUsageSession: failed to update usage entry: %d",
|
||||
sts);
|
||||
return sts;
|
||||
}
|
||||
if (!UpdateUsageInfo()) {
|
||||
LOGW("CdmSession::RestoreUsageSession: unable to save updated usage "
|
||||
"info");
|
||||
}
|
||||
}
|
||||
|
||||
license_received_ = true;
|
||||
is_offline_ = false;
|
||||
is_release_ = true;
|
||||
@@ -339,7 +406,36 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
} else if (license_received_) { // renewal
|
||||
return RenewKey(key_response);
|
||||
} else {
|
||||
CdmResponseType sts = license_parser_->HandleKeyResponse(key_response);
|
||||
// If usage table header+entries are supported, preprocess the license
|
||||
// to see if it has a provider session token. If so a new entry needs
|
||||
// to be created.
|
||||
CdmResponseType sts;
|
||||
std::string provider_session_token;
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
if (license_parser_->ExtractProviderSessionToken(
|
||||
key_response, &provider_session_token) &&
|
||||
!provider_session_token.empty()) {
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
sts = usage_table_header_->AddEntry(
|
||||
crypto_session_.get(), is_offline_, key_set_id_,
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), &usage_entry_number_);
|
||||
if (sts != NO_ERROR) return sts;
|
||||
}
|
||||
}
|
||||
sts = license_parser_->HandleKeyResponse(key_response);
|
||||
|
||||
// Update or delete entry if usage table header+entries are supported
|
||||
if (usage_support_type_ == kUsageEntrySupport &&
|
||||
!provider_session_token.empty()) {
|
||||
if (sts != KEY_ADDED) {
|
||||
CdmResponseType sts =
|
||||
usage_table_header_->DeleteEntry(usage_entry_number_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? ADD_KEY_ERROR : sts;
|
||||
|
||||
@@ -351,6 +447,13 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
license_parser_->provider_session_token().c_str());
|
||||
|
||||
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
|
||||
if (usage_support_type_ == kUsageEntrySupport)
|
||||
usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_);
|
||||
|
||||
if (!is_offline_)
|
||||
usage_provider_session_token_ =
|
||||
license_parser_->provider_session_token();
|
||||
|
||||
sts = StoreLicense();
|
||||
if (sts != NO_ERROR) return sts;
|
||||
}
|
||||
@@ -510,9 +613,24 @@ CdmResponseType CdmSession::GenerateReleaseRequest(
|
||||
|
||||
if (KEY_MESSAGE != status) return status;
|
||||
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
status = usage_table_header_->UpdateEntry(crypto_session_.get(),
|
||||
&usage_entry_);
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("CdmSession::GenerateReleaseRequest: Update usage entry failed = "
|
||||
"%d", status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_offline_) { // Mark license as being released
|
||||
if (!StoreLicense(DeviceFiles::kLicenseStateReleasing))
|
||||
return RELEASE_KEY_REQUEST_ERROR;
|
||||
} else if (!usage_provider_session_token_.empty()) {
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
if (!UpdateUsageInfo())
|
||||
return RELEASE_USAGE_INFO_FAILED;
|
||||
}
|
||||
}
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
@@ -525,10 +643,38 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
|
||||
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
|
||||
DeleteLicense();
|
||||
|
||||
// Deletion of usage entry cannot occur while in use by a crypto session.
|
||||
// So close and reopen after deletion.
|
||||
if (usage_support_type_ == kUsageEntrySupport) {
|
||||
crypto_session_->Close();
|
||||
|
||||
CdmResponseType sts = usage_table_header_->DeleteEntry(usage_entry_number_);
|
||||
if (sts != NO_ERROR) return sts;
|
||||
|
||||
M_TIME(
|
||||
sts = crypto_session_->Open(requested_security_level_),
|
||||
&metrics_,
|
||||
crypto_session_open_,
|
||||
sts,
|
||||
requested_security_level_);
|
||||
if (NO_ERROR != sts) return sts;
|
||||
}
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::DeleteUsageEntry(
|
||||
const DeviceFiles::CdmUsageData& usage_data) {
|
||||
if (usage_support_type_ != kUsageEntrySupport) {
|
||||
LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d",
|
||||
usage_support_type_);
|
||||
return INCORRECT_USAGE_SUPPORT_TYPE_1;
|
||||
}
|
||||
|
||||
return usage_table_header_->DeleteEntry(usage_data.usage_entry_number);
|
||||
}
|
||||
|
||||
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
|
||||
return license_parser_->IsKeyLoaded(key_id);
|
||||
}
|
||||
@@ -602,13 +748,11 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
std::string usage_entry;
|
||||
uint32_t usage_entry_number = 0;
|
||||
if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_,
|
||||
key_response_,
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
key_set_id_, usage_entry,
|
||||
usage_entry_number)) {
|
||||
key_set_id_, usage_entry_,
|
||||
usage_entry_number_)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to store usage info");
|
||||
return STORE_USAGE_INFO_ERROR;
|
||||
}
|
||||
@@ -616,15 +760,13 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
}
|
||||
|
||||
bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) {
|
||||
std::string usage_entry;
|
||||
uint32_t usage_entry_number = 0;
|
||||
return file_handle_->StoreLicense(
|
||||
key_set_id_, state, offline_init_data_, key_request_, key_response_,
|
||||
offline_key_renewal_request_, offline_key_renewal_response_,
|
||||
offline_release_server_url_, policy_engine_->GetPlaybackStartTime(),
|
||||
policy_engine_->GetLastPlaybackTime(),
|
||||
policy_engine_->GetGracePeriodEndTime(), app_parameters_, usage_entry,
|
||||
usage_entry_number);
|
||||
policy_engine_->GetGracePeriodEndTime(), app_parameters_, usage_entry_,
|
||||
usage_entry_number_);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::ReleaseCrypto() {
|
||||
@@ -686,14 +828,43 @@ CdmResponseType CdmSession::DeleteMultipleUsageInformation(
|
||||
return sts;
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::UpdateUsageInformation() {
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
sts = crypto_session_->UpdateUsageInformation(),
|
||||
&metrics_,
|
||||
crypto_session_update_usage_information_,
|
||||
sts);
|
||||
return sts;
|
||||
CdmResponseType CdmSession::UpdateUsageTableInformation() {
|
||||
CdmUsageSupportType usage_support_type;
|
||||
CdmResponseType sts =
|
||||
crypto_session_->GetUsageSupportType(&usage_support_type);
|
||||
|
||||
if (sts == NO_ERROR && usage_support_type == kUsageTableSupport) {
|
||||
M_TIME(
|
||||
sts = crypto_session_->UpdateUsageInformation(),
|
||||
&metrics_,
|
||||
crypto_session_update_usage_information_,
|
||||
sts);
|
||||
return sts;
|
||||
}
|
||||
|
||||
return NO_ERROR; // Ignore
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::UpdateUsageEntryInformation() {
|
||||
if (usage_support_type_ != kUsageEntrySupport) {
|
||||
LOGE("CdmSession::UpdateUsageEntryInformation: Unexpected usage type "
|
||||
"supported: %d", usage_support_type_);
|
||||
return INCORRECT_USAGE_SUPPORT_TYPE_2;
|
||||
}
|
||||
|
||||
CdmResponseType sts = usage_table_header_->UpdateEntry(crypto_session_.get(),
|
||||
&usage_entry_);
|
||||
|
||||
if (sts != NO_ERROR) return sts;
|
||||
|
||||
if (is_offline_)
|
||||
StoreLicense(is_release_
|
||||
? DeviceFiles::kLicenseStateReleasing
|
||||
: DeviceFiles::kLicenseStateActive);
|
||||
else if (!usage_provider_session_token_.empty())
|
||||
UpdateUsageInfo();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer,
|
||||
@@ -788,6 +959,24 @@ CdmResponseType CdmSession::GenericVerify(const std::string& message,
|
||||
return sts;
|
||||
}
|
||||
|
||||
bool CdmSession::UpdateUsageInfo() {
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
|
||||
DeviceFiles::CdmUsageData usage_data;
|
||||
usage_data.provider_session_token = usage_provider_session_token_;
|
||||
usage_data.license_request = key_request_;
|
||||
usage_data.license = key_response_;
|
||||
usage_data.key_set_id = key_set_id_;
|
||||
usage_data.usage_entry = usage_entry_;
|
||||
usage_data.usage_entry_number = usage_entry_number_;
|
||||
|
||||
return file_handle_->UpdateUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
usage_provider_session_token_,
|
||||
usage_data);
|
||||
}
|
||||
|
||||
// For testing only - takes ownership of pointers
|
||||
|
||||
void CdmSession::set_license_parser(CdmLicense* license_parser) {
|
||||
|
||||
@@ -261,10 +261,14 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
std::string serialized_request;
|
||||
signed_provisioning_msg.SerializeToString(&serialized_request);
|
||||
|
||||
// Return request as web-safe base64 string
|
||||
std::vector<uint8_t> request_vector(serialized_request.begin(),
|
||||
serialized_request.end());
|
||||
request->assign(Base64SafeEncodeNoPad(request_vector));
|
||||
if (!wvcdm::Properties::provisioning_messages_are_binary()) {
|
||||
// Return request as web-safe base64 string
|
||||
std::vector<uint8_t> request_vector(serialized_request.begin(),
|
||||
serialized_request.end());
|
||||
request->assign(Base64SafeEncodeNoPad(request_vector));
|
||||
} else {
|
||||
request->swap(serialized_request);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -279,10 +283,14 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
||||
FileSystem* file_system, const CdmProvisioningResponse& response,
|
||||
std::string* cert, std::string* wrapped_key) {
|
||||
|
||||
// The response is base64 encoded in a JSON wrapper.
|
||||
// Extract it and decode it. If errors, return an empty string.
|
||||
std::string raw_string;
|
||||
ExtractAndDecodeSignedMessage(response, &raw_string);
|
||||
if (!wvcdm::Properties::provisioning_messages_are_binary()) {
|
||||
// The response is base64 encoded in a JSON wrapper.
|
||||
// Extract it and decode it. If errors, return an empty string.
|
||||
ExtractAndDecodeSignedMessage(response, &raw_string);
|
||||
} else {
|
||||
raw_string.assign(response);
|
||||
}
|
||||
|
||||
if (raw_string.empty()) {
|
||||
LOGE("HandleProvisioningResponse: response message is empty or "
|
||||
|
||||
@@ -470,34 +470,34 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
||||
random_sts,
|
||||
metrics::Pow2Bucket(sizeof(request_id_base_)));
|
||||
++request_id_index_;
|
||||
CdmUsageSupportType usage_support_type;
|
||||
GetUsageSupportType(&usage_support_type);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void CryptoSession::Close() {
|
||||
LOGV("CloseSession: id=%ld open=%s", (uint32_t)oec_session_id_,
|
||||
open_ ? "true" : "false");
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!open_) return;
|
||||
|
||||
OEMCryptoResult close_sts;
|
||||
M_TIME(
|
||||
close_sts = OEMCrypto_CloseSession(
|
||||
oec_session_id_),
|
||||
metrics_,
|
||||
oemcrypto_close_session_,
|
||||
close_sts);
|
||||
if (OEMCrypto_SUCCESS == close_sts) {
|
||||
open_ = false;
|
||||
if (update_usage_table_after_close_session_) {
|
||||
OEMCryptoResult update_sts;
|
||||
M_TIME(
|
||||
update_sts = OEMCrypto_UpdateUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_update_usage_table_,
|
||||
update_sts);
|
||||
if ( update_sts != OEMCrypto_SUCCESS)
|
||||
LOGW("CryptoSession::Close: OEMCrypto_UpdateUsageTable error=%ld", update_sts);
|
||||
}
|
||||
bool update_usage_table = false;
|
||||
{
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!open_) return;
|
||||
|
||||
M_TIME(
|
||||
close_sts = OEMCrypto_CloseSession(
|
||||
oec_session_id_),
|
||||
metrics_,
|
||||
oemcrypto_close_session_,
|
||||
close_sts);
|
||||
if (OEMCrypto_SUCCESS == close_sts)
|
||||
open_ = false;
|
||||
update_usage_table = update_usage_table_after_close_session_;
|
||||
}
|
||||
if (close_sts == OEMCrypto_SUCCESS && update_usage_table &&
|
||||
usage_support_type_ == kUsageTableSupport) {
|
||||
UpdateUsageInformation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,27 +669,27 @@ CdmResponseType CryptoSession::LoadKeys(
|
||||
metrics_,
|
||||
oemcrypto_load_keys_,
|
||||
sts);
|
||||
CdmResponseType result = KEY_ADDED;
|
||||
if (OEMCrypto_SUCCESS == sts) {
|
||||
if (!provider_session_token.empty()) {
|
||||
if (!provider_session_token.empty())
|
||||
update_usage_table_after_close_session_ = true;
|
||||
M_TIME(
|
||||
sts = OEMCrypto_UpdateUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_update_usage_table_,
|
||||
sts);
|
||||
if (sts != OEMCrypto_SUCCESS) {
|
||||
LOGW("CryptoSession::LoadKeys: OEMCrypto_UpdateUsageTable error=%ld",
|
||||
sts);
|
||||
}
|
||||
}
|
||||
return KEY_ADDED;
|
||||
result = KEY_ADDED;
|
||||
} else if (OEMCrypto_ERROR_TOO_MANY_KEYS == sts) {
|
||||
LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts);
|
||||
return INSUFFICIENT_CRYPTO_RESOURCES;
|
||||
result = INSUFFICIENT_CRYPTO_RESOURCES;
|
||||
} else {
|
||||
LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts);
|
||||
return LOAD_KEY_ERROR;
|
||||
result = LOAD_KEY_ERROR;
|
||||
}
|
||||
|
||||
// Leaving critical section
|
||||
crypto_lock_.Release();
|
||||
|
||||
if (!provider_session_token.empty() &&
|
||||
usage_support_type_ == kUsageTableSupport) {
|
||||
UpdateUsageInformation();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) {
|
||||
@@ -1104,7 +1104,7 @@ bool CryptoSession::UsageInformationSupport(bool* has_support) {
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::UpdateUsageInformation() {
|
||||
LOGV("UpdateUsageInformation: id=%ld", (uint32_t)oec_session_id_);
|
||||
LOGV("CryptoSession::UpdateUsageInformation: id=%ld", (uint32_t)oec_session_id_);
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!initialized_) return UNKNOWN_ERROR;
|
||||
|
||||
@@ -1115,7 +1115,7 @@ CdmResponseType CryptoSession::UpdateUsageInformation() {
|
||||
oemcrypto_update_usage_table_,
|
||||
status);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
LOGE("CryptoSession::UsageUsageInformation: error=%ld", status);
|
||||
LOGE("CryptoSession::UpdateUsageInformation: error=%ld", status);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
return NO_ERROR;
|
||||
@@ -1262,40 +1262,35 @@ CdmResponseType CryptoSession::ReleaseUsageInformation(
|
||||
const std::string& message, const std::string& signature,
|
||||
const std::string& provider_session_token) {
|
||||
LOGV("ReleaseUsageInformation: id=%ld", (uint32_t)oec_session_id_);
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
||||
const uint8_t* sig = reinterpret_cast<const uint8_t*>(signature.data());
|
||||
const uint8_t* pst = msg + GetOffset(message, provider_session_token);
|
||||
{
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
||||
const uint8_t* sig = reinterpret_cast<const uint8_t*>(signature.data());
|
||||
const uint8_t* pst = msg + GetOffset(message, provider_session_token);
|
||||
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_DeleteUsageEntry(
|
||||
oec_session_id_,
|
||||
pst,
|
||||
provider_session_token.length(),
|
||||
msg,
|
||||
message.length(),
|
||||
sig,
|
||||
signature.length()),
|
||||
metrics_,
|
||||
oemcrypto_delete_usage_entry_,
|
||||
status);
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_DeleteUsageEntry(
|
||||
oec_session_id_,
|
||||
pst,
|
||||
provider_session_token.length(),
|
||||
msg,
|
||||
message.length(),
|
||||
sig,
|
||||
signature.length()),
|
||||
metrics_,
|
||||
oemcrypto_delete_usage_entry_,
|
||||
status);
|
||||
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGE("CryptoSession::ReleaseUsageInformation: Report Usage error=%ld",
|
||||
status);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
M_TIME(
|
||||
status = OEMCrypto_UpdateUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_update_usage_table_,
|
||||
status);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
LOGW("CryptoSession::ReleaseUsageInformation: update table error=%ld",
|
||||
status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGE("CryptoSession::ReleaseUsageInformation: Report Usage error=%ld",
|
||||
status);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (usage_support_type_ == kUsageTableSupport)
|
||||
UpdateUsageInformation();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -1304,28 +1299,23 @@ CdmResponseType CryptoSession::DeleteUsageInformation(
|
||||
CdmResponseType response = NO_ERROR;
|
||||
LOGV("CryptoSession::DeleteUsageInformation");
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_ForceDeleteUsageEntry(
|
||||
reinterpret_cast<const uint8_t*>(provider_session_token.c_str()),
|
||||
provider_session_token.length()),
|
||||
metrics_,
|
||||
oemcrypto_force_delete_usage_entry_,
|
||||
status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGE("CryptoSession::DeleteUsageInformation: Delete Usage Table error =%ld",
|
||||
status);
|
||||
response = UNKNOWN_ERROR;
|
||||
}
|
||||
M_TIME(
|
||||
status = OEMCrypto_UpdateUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_update_usage_table_,
|
||||
status);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
LOGE("CryptoSession::DeleteUsageInformation: update table error=%ld",
|
||||
status);
|
||||
response = UNKNOWN_ERROR;
|
||||
{
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
M_TIME(
|
||||
status = OEMCrypto_ForceDeleteUsageEntry(
|
||||
reinterpret_cast<const uint8_t*>(provider_session_token.c_str()),
|
||||
provider_session_token.length()),
|
||||
metrics_,
|
||||
oemcrypto_force_delete_usage_entry_,
|
||||
status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGE("CryptoSession::DeleteUsageInformation: Delete Usage Table error "
|
||||
"= %ld", status);
|
||||
response = UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
if (usage_support_type_ == kUsageTableSupport)
|
||||
UpdateUsageInformation();
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -1333,58 +1323,48 @@ CdmResponseType CryptoSession::DeleteMultipleUsageInformation(
|
||||
const std::vector<std::string>& provider_session_tokens) {
|
||||
LOGV("CryptoSession::DeleteMultipleUsageInformation");
|
||||
CdmResponseType response = NO_ERROR;
|
||||
for (size_t i=0; i < provider_session_tokens.size(); ++i) {
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_ForceDeleteUsageEntry(
|
||||
reinterpret_cast<const uint8_t*>(provider_session_tokens[i].c_str()),
|
||||
provider_session_tokens[i].length()),
|
||||
metrics_,
|
||||
oemcrypto_force_delete_usage_entry_,
|
||||
status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGW("CryptoSession::DeleteMultipleUsageInformation: "
|
||||
"Delete Usage Table error =%ld", status);
|
||||
response = UNKNOWN_ERROR;
|
||||
{
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
for (size_t i=0; i < provider_session_tokens.size(); ++i) {
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_ForceDeleteUsageEntry(
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
provider_session_tokens[i].c_str()),
|
||||
provider_session_tokens[i].length()),
|
||||
metrics_,
|
||||
oemcrypto_force_delete_usage_entry_,
|
||||
status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGW("CryptoSession::DeleteMultipleUsageInformation: "
|
||||
"Delete Usage Table error =%ld", status);
|
||||
response = UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_UpdateUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_update_usage_table_,
|
||||
status);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
LOGE("CryptoSession::DeleteMultipleUsageInformation: update table error=%ld",
|
||||
status);
|
||||
response = UNKNOWN_ERROR;
|
||||
}
|
||||
if (usage_support_type_ == kUsageTableSupport)
|
||||
UpdateUsageInformation();
|
||||
return response;
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::DeleteAllUsageReports() {
|
||||
LOGV("DeleteAllUsageReports");
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_DeleteOldUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_delete_usage_table_,
|
||||
status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGE("CryptoSession::DeleteAllUsageReports: Delete Usage Table error =%ld",
|
||||
status);
|
||||
{
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
M_TIME(
|
||||
status = OEMCrypto_DeleteOldUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_delete_usage_table_,
|
||||
status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGE("CryptoSession::DeleteAllUsageReports: Delete Usage Table error "
|
||||
"=%ld", status);
|
||||
}
|
||||
}
|
||||
|
||||
M_TIME(
|
||||
status = OEMCrypto_UpdateUsageTable(),
|
||||
metrics_,
|
||||
oemcrypto_update_usage_table_,
|
||||
status);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
LOGE("CryptoSession::DeletaAllUsageReports: update table error=%ld",
|
||||
status);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
if (usage_support_type_ == kUsageTableSupport)
|
||||
UpdateUsageInformation();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -2015,7 +1995,7 @@ CdmResponseType CryptoSession::CreateUsageTableHeader(
|
||||
}
|
||||
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
LOGE("CreateUsageTableHeader; usage table header creation failed: %d",
|
||||
LOGE("CreateUsageTableHeader: usage table header creation failed: %d",
|
||||
result);
|
||||
return CREATE_USAGE_TABLE_ERROR;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const char kUsageInfoFileNamePrefix[] = "usage";
|
||||
const char kUsageInfoFileNameExt[] = ".bin";
|
||||
const char kLicenseFileNameExt[] = ".lic";
|
||||
const char kEmptyFileName[] = "";
|
||||
const char kUsageTableFileName[] = "usagetable.bin";
|
||||
const char kUsageTableFileName[] = "usgtable.bin";
|
||||
const char kWildcard[] = "*";
|
||||
|
||||
bool Hash(const std::string& data, std::string* hash) {
|
||||
@@ -734,14 +734,65 @@ bool DeviceFiles::StoreUsageInfo(const std::string& usage_info_file_name,
|
||||
return StoreFileWithHash(usage_info_file_name, serialized_file);
|
||||
}
|
||||
|
||||
bool DeviceFiles::UpdateUsageInfo(const std::string& usage_info_file_name,
|
||||
const std::string& provider_session_token,
|
||||
const CdmUsageData& usage_data) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::UpdateUsageInfo: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!FileExists(usage_info_file_name)) {
|
||||
LOGW("DeviceFiles::UpdateUsageInfo: Usage file does not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
|
||||
LOGW("DeviceFiles::UpdateUsageInfo: Unable to parse file");
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (; index < file.usage_info().sessions_size(); ++index) {
|
||||
if (file.usage_info().sessions(index).token() == provider_session_token) {
|
||||
UsageInfo* usage_info = file.mutable_usage_info();
|
||||
UsageInfo_ProviderSession* provider_session =
|
||||
usage_info->mutable_sessions(index);
|
||||
provider_session->set_license_request(usage_data.license_request);
|
||||
provider_session->set_license(usage_data.license);
|
||||
provider_session->set_key_set_id(usage_data.key_set_id);
|
||||
provider_session->set_usage_entry(usage_data.usage_entry);
|
||||
provider_session->set_usage_entry_number(usage_data.usage_entry_number);
|
||||
|
||||
std::string serialized_file;
|
||||
file.SerializeToString(&serialized_file);
|
||||
return StoreFileWithHash(usage_info_file_name, serialized_file);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveUsageInfo(const std::string& usage_info_file_name,
|
||||
std::vector<CdmUsageData>* usage_data) {
|
||||
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usage_data == NULL) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: usage_data not provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FileExists(usage_info_file_name) ||
|
||||
GetFileSize(usage_info_file_name) == 0) {
|
||||
usage_data->resize(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
|
||||
return false;
|
||||
@@ -760,6 +811,43 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& usage_info_file_name,
|
||||
file.usage_info().sessions(i).usage_entry_number();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveUsageInfo(const std::string& usage_info_file_name,
|
||||
const std::string& provider_session_token,
|
||||
CdmUsageData* usage_data) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usage_data == NULL) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: usage_data not provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (; index < file.usage_info().sessions_size(); ++index) {
|
||||
if (file.usage_info().sessions(index).token() == provider_session_token) {
|
||||
usage_data->provider_session_token =
|
||||
file.usage_info().sessions(index).token();
|
||||
usage_data->license_request =
|
||||
file.usage_info().sessions(index).license_request();
|
||||
usage_data->license = file.usage_info().sessions(index).license();
|
||||
usage_data->key_set_id = file.usage_info().sessions(index).key_set_id();
|
||||
usage_data->usage_entry = file.usage_info().sessions(index).usage_entry();
|
||||
usage_data->usage_entry_number =
|
||||
file.usage_info().sessions(index).usage_entry_number();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -766,6 +766,43 @@ bool CdmLicense::IsKeyLoaded(const KeyId& key_id) {
|
||||
return loaded_keys_.find(key_id) != loaded_keys_.end();
|
||||
}
|
||||
|
||||
bool CdmLicense::ExtractProviderSessionToken(
|
||||
const CdmKeyResponse& license_response,
|
||||
std::string* provider_session_token) {
|
||||
if (license_response.empty()) {
|
||||
LOGE("CdmLicense::ExtractProviderSessionToken: empty license response");
|
||||
return false;
|
||||
}
|
||||
|
||||
SignedMessage signed_response;
|
||||
if (!signed_response.ParseFromString(license_response)) {
|
||||
LOGE(
|
||||
"CdmLicense::ExtractProviderSessionToken: unable to parse signed "
|
||||
"license response");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (signed_response.type() != SignedMessage::LICENSE) {
|
||||
LOGE("CdmLicense::ExtractProviderSessionToken: unrecognized signed message "
|
||||
"type: %d", signed_response.type());
|
||||
return false;
|
||||
}
|
||||
|
||||
License license;
|
||||
if (!license.ParseFromString(signed_response.msg())) {
|
||||
LOGE("CdmLicense::ExtractProviderSessionToken: unable to parse license "
|
||||
"response");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (license.id().has_provider_session_token()) {
|
||||
*provider_session_token = license.id().provider_session_token();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::HandleKeyErrorResponse(
|
||||
const SignedMessage& signed_message) {
|
||||
LicenseError license_error;
|
||||
|
||||
@@ -13,6 +13,7 @@ bool Properties::oem_crypto_use_secure_buffers_;
|
||||
bool Properties::oem_crypto_use_fifo_;
|
||||
bool Properties::oem_crypto_use_userspace_buffers_;
|
||||
bool Properties::use_certificates_as_identification_;
|
||||
bool Properties::provisioning_messages_are_binary_;
|
||||
bool Properties::security_level_path_backward_compatibility_support_;
|
||||
scoped_ptr<CdmClientPropertySetMap> Properties::session_property_set_;
|
||||
|
||||
|
||||
@@ -5,94 +5,85 @@
|
||||
#include "crypto_session.h"
|
||||
#include "license.h"
|
||||
#include "log.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace {
|
||||
std::string kEmptyString;
|
||||
uint64_t kOldUsageEntryTimeSinceLicenseReceived = 0;
|
||||
uint64_t kOldUsageEntryTimeSinceFirstDecrypt = 0;
|
||||
uint64_t kOldUsageEntryTimeSinceLastDecrypt = 0;
|
||||
std::string kOldUsageEntryServerMacKey(wvcdm::MAC_KEY_SIZE, 0);
|
||||
std::string kOldUsageEntryClientMacKey(wvcdm::MAC_KEY_SIZE, 0);
|
||||
std::string kOldUsageEntryPoviderSessionToken =
|
||||
"nahZ6achSheiqua3TohQuei0ahwohv";
|
||||
}
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
UsageTableHeader::UsageTableHeader()
|
||||
: security_level_(kSecurityLevelUninitialized),
|
||||
requested_security_level_(kLevelDefault),
|
||||
is_inited_(false) {
|
||||
file_system_.reset(new FileSystem());
|
||||
file_handle_.reset(new DeviceFiles(file_system_.get()));
|
||||
}
|
||||
UsageTableHeader* UsageTableHeader::usage_table_header_l1_ = NULL;
|
||||
UsageTableHeader* UsageTableHeader::usage_table_header_l3_ = NULL;
|
||||
|
||||
bool UsageTableHeader::Init(CdmSecurityLevel security_level,
|
||||
CryptoSession* crypto_session) {
|
||||
LOGV("UsageTableHeader::Init: security level: %d", security_level);
|
||||
if (crypto_session == NULL) {
|
||||
LOGE("UsageTableHeader::Init: no crypto session provided");
|
||||
return false;
|
||||
}
|
||||
Lock UsageTableHeader::initialization_lock_;
|
||||
|
||||
UsageTableHeader* UsageTableHeader::GetInstance(FileSystem* file_system,
|
||||
CryptoSession* crypto_session) {
|
||||
LOGV("UsageTableHeader::GetInstance");
|
||||
AutoLock auto_lock(initialization_lock_);
|
||||
CdmSecurityLevel security_level = crypto_session->GetSecurityLevel();
|
||||
switch (security_level) {
|
||||
case kSecurityLevelL1:
|
||||
if (usage_table_header_l1_ != NULL)
|
||||
return usage_table_header_l1_;
|
||||
break;
|
||||
case kSecurityLevelL3:
|
||||
if (usage_table_header_l3_ != NULL)
|
||||
return usage_table_header_l3_;
|
||||
break;
|
||||
default:
|
||||
LOGE("UsageTableHeader::Init: invalid security level provided: %d",
|
||||
LOGE("UsageTableHeader::GetInstance: unsupported security level: %d",
|
||||
security_level);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
security_level_ = security_level;
|
||||
requested_security_level_ =
|
||||
security_level_ == kSecurityLevelL3 ? kLevel3 : kLevelDefault;
|
||||
|
||||
if (!file_handle_->Init(security_level)) {
|
||||
LOGE("UsageTableHeader::Init: device files initialization failed");
|
||||
return false;
|
||||
UsageTableHeader* header =
|
||||
new UsageTableHeader(file_system, crypto_session, security_level);
|
||||
if (!header->is_inited()) {
|
||||
delete header;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CdmResponseType status = USAGE_INFO_NOT_FOUND;
|
||||
if (file_handle_->RetrieveUsageTableInfo(&usage_table_header_,
|
||||
if (security_level == kSecurityLevelL1)
|
||||
usage_table_header_l1_ = header;
|
||||
else
|
||||
usage_table_header_l3_ = header;
|
||||
return header;
|
||||
}
|
||||
|
||||
UsageTableHeader::UsageTableHeader(FileSystem* file_system,
|
||||
CryptoSession* crypto_session,
|
||||
CdmSecurityLevel security_level)
|
||||
: file_handle_(new DeviceFiles(file_system)),
|
||||
security_level_(security_level),
|
||||
is_inited_(false) {
|
||||
LOGV("UsageTableHeader::UsageTablerHeader: security level: %d",
|
||||
security_level);
|
||||
|
||||
if (!file_handle_->RetrieveUsageTableInfo(&usage_table_header_,
|
||||
&usage_entry_info_)) {
|
||||
status = crypto_session->LoadUsageTableHeader(usage_table_header_);
|
||||
CdmResponseType status =
|
||||
crypto_session->CreateUsageTableHeader(&usage_table_header_);
|
||||
if (status != NO_ERROR) return;
|
||||
} else {
|
||||
CdmResponseType status =
|
||||
crypto_session->LoadUsageTableHeader(usage_table_header_);
|
||||
if (status != NO_ERROR) {
|
||||
LOGE(
|
||||
"UsageTableHeader::Init: load usage table failed, security level: %d",
|
||||
"UsageTableHeader::UsageTablerHeader: load usage table failed, "
|
||||
"security level: %d",
|
||||
security_level);
|
||||
file_handle_->DeleteAllLicenses();
|
||||
usage_entry_info_.clear();
|
||||
usage_table_header_.clear();
|
||||
status = crypto_session->CreateUsageTableHeader(&usage_table_header_);
|
||||
if (status != NO_ERROR) return false;
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
status = crypto_session->CreateUsageTableHeader(&usage_table_header_);
|
||||
if (status != NO_ERROR) return false;
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
|
||||
|
||||
metrics::CryptoMetrics alternate_metrics;
|
||||
metrics::CryptoMetrics* metrics =
|
||||
crypto_session->GetCryptoMetrics() != NULL ?
|
||||
crypto_session->GetCryptoMetrics() : &alternate_metrics;
|
||||
|
||||
UpgradeFromUsageTable(file_handle_.get(), metrics);
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
|
||||
}
|
||||
|
||||
is_inited_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::AddEntry(
|
||||
CryptoSession* crypto_session, bool persistent_license,
|
||||
const CdmKeySetId& key_set_id, const std::string& usage_info_file_name,
|
||||
uint32_t* usage_entry_number) {
|
||||
LOGV("UsageTableHeader::AddEntry: Lock");
|
||||
LOGV("UsageTableHeader::AddEntry");
|
||||
AutoLock auto_lock(usage_table_header_lock_);
|
||||
CdmResponseType status = crypto_session->CreateUsageEntry(usage_entry_number);
|
||||
|
||||
@@ -110,7 +101,7 @@ CdmResponseType UsageTableHeader::AddEntry(
|
||||
size_t number_of_entries = usage_entry_info_.size();
|
||||
usage_entry_info_.resize(*usage_entry_number + 1);
|
||||
for (size_t i = number_of_entries; i < usage_entry_info_.size() - 1; ++i) {
|
||||
usage_entry_info_[i].storage_type = kStorageTypeUnknown;
|
||||
usage_entry_info_[i].storage_type = kStorageUnknown;
|
||||
usage_entry_info_[i].key_set_id.clear();
|
||||
usage_entry_info_[i].usage_info_file_name.clear();
|
||||
}
|
||||
@@ -129,17 +120,15 @@ CdmResponseType UsageTableHeader::AddEntry(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::LoadEntry(CryptoSession* crypto_session,
|
||||
const CdmUsageEntry& usage_entry,
|
||||
uint32_t usage_entry_number) {
|
||||
LOGV("UsageTableHeader::LoadEntry: Lock");
|
||||
CdmResponseType UsageTableHeader::LoadEntry(
|
||||
CryptoSession* crypto_session, const CdmUsageEntry& usage_entry,
|
||||
uint32_t usage_entry_number) {
|
||||
LOGV("UsageTableHeader::LoadEntry");
|
||||
AutoLock auto_lock(usage_table_header_lock_);
|
||||
|
||||
if (usage_entry_number >= usage_entry_info_.size()) {
|
||||
LOGE(
|
||||
"UsageTableHeader::LoadEntry: usage entry number %d larger than table "
|
||||
"size: %d",
|
||||
usage_entry_number, usage_entry_info_.size());
|
||||
LOGE("UsageTableHeader::LoadEntry: usage entry number %d larger than table size: %d",
|
||||
usage_entry_number, usage_entry_info_.size());
|
||||
return USAGE_INVALID_LOAD_ENTRY;
|
||||
}
|
||||
return crypto_session->LoadUsageEntry(usage_entry_number, usage_entry);
|
||||
@@ -147,93 +136,73 @@ CdmResponseType UsageTableHeader::LoadEntry(CryptoSession* crypto_session,
|
||||
|
||||
CdmResponseType UsageTableHeader::UpdateEntry(CryptoSession* crypto_session,
|
||||
CdmUsageEntry* usage_entry) {
|
||||
LOGV("UsageTableHeader::UpdateEntryL: Lock");
|
||||
LOGV("UsageTableHeader::UpdateEntry");
|
||||
AutoLock auto_lock(usage_table_header_lock_);
|
||||
CdmUsageTableHeader usage_table_header;
|
||||
CdmResponseType status =
|
||||
crypto_session->UpdateUsageEntry(&usage_table_header_, usage_entry);
|
||||
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header, usage_entry_info_);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number,
|
||||
DeviceFiles* handle,
|
||||
metrics::CryptoMetrics* metrics) {
|
||||
LOGV("UsageTableHeader::DeleteEntry: Lock");
|
||||
CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number) {
|
||||
LOGV("UsageTableHeader::DeleteEntry");
|
||||
AutoLock auto_lock(usage_table_header_lock_);
|
||||
if (usage_entry_number >= usage_entry_info_.size()) {
|
||||
LOGE("UsageTableHeader::DeleteEntry: usage entry number %d larger than "
|
||||
"usage entry size %d", usage_entry_number, usage_entry_info_.size());
|
||||
if (usage_entry_number >= usage_entry_info_.size())
|
||||
return USAGE_INVALID_PARAMETERS_1;
|
||||
}
|
||||
|
||||
// Find the last valid entry number, in order to swap
|
||||
size_t swap_entry_number = usage_entry_info_.size() - 1;
|
||||
CdmUsageEntry swap_usage_entry;
|
||||
bool swap_usage_entry_valid = false;
|
||||
|
||||
while (!swap_usage_entry_valid && swap_entry_number > usage_entry_number) {
|
||||
for (; !swap_usage_entry_valid && swap_entry_number > usage_entry_number;
|
||||
--swap_entry_number) {
|
||||
switch (usage_entry_info_[swap_entry_number].storage_type) {
|
||||
case kStorageLicense:
|
||||
case kStorageUsageInfo: {
|
||||
CdmResponseType status =
|
||||
GetEntry(swap_entry_number, handle, &swap_usage_entry);
|
||||
CdmResponseType status = GetEntry(swap_entry_number, &swap_usage_entry);
|
||||
if (status == NO_ERROR) swap_usage_entry_valid = true;
|
||||
break;
|
||||
}
|
||||
case kStorageTypeUnknown:
|
||||
case kStorageUnknown:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!swap_usage_entry_valid) --swap_entry_number;
|
||||
}
|
||||
|
||||
uint32_t number_of_entries_to_be_deleted =
|
||||
usage_entry_info_.size() - usage_entry_number;
|
||||
uint32_t new_usage_table_size = 0;
|
||||
|
||||
if (swap_usage_entry_valid) {
|
||||
CdmResponseType status = MoveEntry(swap_entry_number, swap_usage_entry,
|
||||
usage_entry_number, handle, metrics);
|
||||
// If unable to move entry, unset storage type of entry to be deleted and
|
||||
// resize |usage_entry_info_| so that swap usage entry is the last entry.
|
||||
if (status != NO_ERROR) {
|
||||
usage_entry_info_[usage_entry_number].storage_type = kStorageTypeUnknown;
|
||||
usage_entry_info_[usage_entry_number].key_set_id.clear();
|
||||
if (usage_entry_info_.size() - 1 == swap_entry_number) {
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_,
|
||||
usage_entry_info_);
|
||||
} else {
|
||||
Shrink(metrics, usage_entry_info_.size() - swap_entry_number - 1);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
number_of_entries_to_be_deleted =
|
||||
usage_entry_info_.size() - swap_entry_number;
|
||||
MoveEntry(swap_entry_number, swap_usage_entry, usage_entry_number);
|
||||
new_usage_table_size = swap_entry_number;
|
||||
} else {
|
||||
// No valid usage entries before entry to be deleted
|
||||
new_usage_table_size = usage_entry_number;
|
||||
}
|
||||
return Shrink(metrics, number_of_entries_to_be_deleted);
|
||||
usage_entry_info_.resize(new_usage_table_size);
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
crypto_session.Open(GetSecurityLevel());
|
||||
crypto_session.ShrinkUsageTableHeader(new_usage_table_size,
|
||||
&usage_table_header_);
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::MoveEntry(
|
||||
uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry,
|
||||
uint32_t to_usage_entry_number, DeviceFiles* handle,
|
||||
metrics::CryptoMetrics* metrics) {
|
||||
uint32_t to_usage_entry_number) {
|
||||
LOGV("UsageTableHeader::MoveEntry");
|
||||
AutoLock auto_lock(usage_table_header_lock_);
|
||||
|
||||
// crypto_session points to an object whose scope is this method or a test
|
||||
// object whose scope is the lifetime of this class
|
||||
scoped_ptr<CryptoSession> scoped_crypto_session;
|
||||
CryptoSession* crypto_session = test_crypto_session_.get();
|
||||
if (crypto_session == NULL) {
|
||||
scoped_crypto_session.reset((new CryptoSession(metrics)));
|
||||
crypto_session = scoped_crypto_session.get();
|
||||
}
|
||||
|
||||
crypto_session->Open(requested_security_level_);
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
crypto_session.Open(GetSecurityLevel());
|
||||
|
||||
CdmResponseType status =
|
||||
crypto_session->LoadUsageEntry(from_usage_entry_number, from_usage_entry);
|
||||
crypto_session.LoadUsageEntry(from_usage_entry_number, from_usage_entry);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("UsageTableHeader::MoveEntry: Failed to load usage entry: %d",
|
||||
@@ -241,7 +210,7 @@ CdmResponseType UsageTableHeader::MoveEntry(
|
||||
return status;
|
||||
}
|
||||
|
||||
status = crypto_session->MoveUsageEntry(to_usage_entry_number);
|
||||
status = crypto_session.MoveUsageEntry(to_usage_entry_number);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("UsageTableHeader::MoveEntry: Failed to move usage entry: %d->%d",
|
||||
@@ -253,7 +222,7 @@ CdmResponseType UsageTableHeader::MoveEntry(
|
||||
usage_entry_info_[from_usage_entry_number];
|
||||
|
||||
CdmUsageEntry usage_entry;
|
||||
status = crypto_session->UpdateUsageEntry(&usage_table_header_, &usage_entry);
|
||||
status = crypto_session.UpdateUsageEntry(&usage_table_header_, &usage_entry);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("UsageTableHeader::MoveEntry: Failed to update usage entry: %d",
|
||||
@@ -263,13 +232,12 @@ CdmResponseType UsageTableHeader::MoveEntry(
|
||||
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
|
||||
|
||||
StoreEntry(to_usage_entry_number, handle, usage_entry);
|
||||
StoreEntry(to_usage_entry_number, usage_entry);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
|
||||
DeviceFiles* handle,
|
||||
CdmUsageEntry* usage_entry) {
|
||||
uint32_t entry_number;
|
||||
switch (usage_entry_info_[usage_entry_number].storage_type) {
|
||||
@@ -279,7 +247,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
|
||||
std::string key_renewal_response, release_server_url;
|
||||
int64_t playback_start_time, last_playback_time, grace_period_end_time;
|
||||
CdmAppParameterMap app_parameters;
|
||||
if (!handle->RetrieveLicense(
|
||||
if (!file_handle_->RetrieveLicense(
|
||||
usage_entry_info_[usage_entry_number].key_set_id, &license_state,
|
||||
&init_data, &key_request, &key_response, &key_renewal_request,
|
||||
&key_renewal_response, &release_server_url, &playback_start_time,
|
||||
@@ -295,7 +263,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
|
||||
CdmKeyMessage license_request;
|
||||
CdmKeyResponse license_response;
|
||||
|
||||
if (!handle->RetrieveUsageInfoByKeySetId(
|
||||
if (!file_handle_->RetrieveUsageInfoByKeySetId(
|
||||
usage_entry_info_[usage_entry_number].usage_info_file_name,
|
||||
usage_entry_info_[usage_entry_number].key_set_id,
|
||||
&provider_session_token, &license_request, &license_response,
|
||||
@@ -306,7 +274,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kStorageTypeUnknown:
|
||||
case kStorageUnknown:
|
||||
default:
|
||||
LOGE(
|
||||
"UsageTableHeader::GetEntry: Attempting to retrieve usage "
|
||||
@@ -325,7 +293,6 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
DeviceFiles* handle,
|
||||
const CdmUsageEntry& usage_entry) {
|
||||
uint32_t entry_number;
|
||||
switch (usage_entry_info_[usage_entry_number].storage_type) {
|
||||
@@ -336,7 +303,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
int64_t playback_start_time, last_playback_time, grace_period_end_time;
|
||||
CdmAppParameterMap app_parameters;
|
||||
CdmUsageEntry entry;
|
||||
if (!handle->RetrieveLicense(
|
||||
if (!file_handle_->RetrieveLicense(
|
||||
usage_entry_info_[usage_entry_number].key_set_id, &license_state,
|
||||
&init_data, &key_request, &key_response, &key_renewal_request,
|
||||
&key_renewal_response, &release_server_url, &playback_start_time,
|
||||
@@ -345,7 +312,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
LOGE("UsageTableHeader::StoreEntry: Failed to retrieve license");
|
||||
return USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED;
|
||||
}
|
||||
if (!handle->StoreLicense(
|
||||
if (!file_handle_->StoreLicense(
|
||||
usage_entry_info_[usage_entry_number].key_set_id, license_state,
|
||||
init_data, key_request, key_response, key_renewal_request,
|
||||
key_renewal_response, release_server_url, playback_start_time,
|
||||
@@ -360,7 +327,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
CdmUsageEntry entry;
|
||||
std::string provider_session_token, init_data, key_request, key_response,
|
||||
key_renewal_request;
|
||||
if (!handle->RetrieveUsageInfoByKeySetId(
|
||||
if (!file_handle_->RetrieveUsageInfoByKeySetId(
|
||||
usage_entry_info_[usage_entry_number].usage_info_file_name,
|
||||
usage_entry_info_[usage_entry_number].key_set_id,
|
||||
&provider_session_token, &key_request, &key_response, &entry,
|
||||
@@ -370,10 +337,10 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
"information");
|
||||
return USAGE_STORE_ENTRY_RETRIEVE_USAGE_INFO_FAILED;
|
||||
}
|
||||
handle->DeleteUsageInfo(
|
||||
file_handle_->DeleteUsageInfo(
|
||||
usage_entry_info_[usage_entry_number].usage_info_file_name,
|
||||
provider_session_token);
|
||||
if (!handle->StoreUsageInfo(
|
||||
if (!file_handle_->StoreUsageInfo(
|
||||
provider_session_token, key_request, key_response,
|
||||
usage_entry_info_[usage_entry_number].usage_info_file_name,
|
||||
usage_entry_info_[usage_entry_number].key_set_id, usage_entry,
|
||||
@@ -383,7 +350,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kStorageTypeUnknown:
|
||||
case kStorageUnknown:
|
||||
default:
|
||||
LOGE(
|
||||
"UsageTableHeader::GetUsageEntry: Attempting to retrieve usage "
|
||||
@@ -394,56 +361,41 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::Shrink(
|
||||
metrics::CryptoMetrics* metrics,
|
||||
uint32_t number_of_usage_entries_to_delete) {
|
||||
bool UsageTableHeader::DeleteLastEntry() {
|
||||
if (usage_entry_info_.empty()) {
|
||||
LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty");
|
||||
return NO_USAGE_ENTRIES;
|
||||
}
|
||||
|
||||
if (usage_entry_info_.size() < number_of_usage_entries_to_delete) {
|
||||
LOGW(
|
||||
"UsageTableHeader::Shrink: cannot delete %d entries when usage entry "
|
||||
"table size is %d", number_of_usage_entries_to_delete,
|
||||
usage_entry_info_.size());
|
||||
return NO_ERROR;
|
||||
"UsageTableHeader::DeleteLastEntry: usage entry info table "
|
||||
"unexpectedly empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (number_of_usage_entries_to_delete == 0) return NO_ERROR;
|
||||
|
||||
usage_entry_info_.resize(usage_entry_info_.size() -
|
||||
number_of_usage_entries_to_delete);
|
||||
|
||||
// crypto_session points to an object whose scope is this method or a test
|
||||
// object whose scope is the lifetime of this class
|
||||
scoped_ptr<CryptoSession> scoped_crypto_session;
|
||||
CryptoSession* crypto_session = test_crypto_session_.get();
|
||||
if (crypto_session == NULL) {
|
||||
scoped_crypto_session.reset((new CryptoSession(metrics)));
|
||||
crypto_session = scoped_crypto_session.get();
|
||||
}
|
||||
|
||||
CdmResponseType status = crypto_session->Open(requested_security_level_);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
status = crypto_session->ShrinkUsageTableHeader(usage_entry_info_.size(),
|
||||
&usage_table_header_);
|
||||
if (status != NO_ERROR) return status;
|
||||
usage_entry_info_.resize(usage_entry_info_.size() - 1);
|
||||
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
crypto_session.Open(GetSecurityLevel());
|
||||
crypto_session.ShrinkUsageTableHeader(usage_entry_info_.size(),
|
||||
&usage_table_header_);
|
||||
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
|
||||
return true;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::UpgradeFromUsageTable() {
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
|
||||
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
status = crypto_session.CreateUsageTableHeader(&usage_table_header_);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
crypto_session.Close();
|
||||
|
||||
UpgradeLicensesFromUsageTable();
|
||||
UpgradeUsageInfoFromUsageTable();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType UsageTableHeader::UpgradeFromUsageTable(
|
||||
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
|
||||
UpgradeLicensesFromUsageTable(handle, metrics);
|
||||
UpgradeUsageInfoFromUsageTable(handle, metrics);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
|
||||
bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
|
||||
// Fetch the key set IDs for each offline license. For each license
|
||||
// * retrieve the provider session token,
|
||||
// * create a new usage entry
|
||||
@@ -451,14 +403,18 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
// * update the usage header table and entry numbers
|
||||
// * save the usage table header and store the usage entry number and
|
||||
// usage entry along with the license to persistent memory
|
||||
// On errors, continue to the next license, but indicate on return that not
|
||||
// all licenses may have been upgraded.
|
||||
std::vector<std::string> key_set_ids;
|
||||
if (!handle->ListLicenses(&key_set_ids)) {
|
||||
LOGW(
|
||||
if (file_handle_->ListLicenses(&key_set_ids)) {
|
||||
LOGE(
|
||||
"UpgradeUsageTableHeader::UpgradeLicensesFromUsageTable: unable to "
|
||||
"retrieve list of licenses");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
for (size_t i = 0; i < key_set_ids.size(); ++i) {
|
||||
DeviceFiles::LicenseState license_state;
|
||||
std::string init_data, key_request, key_response, key_renewal_request;
|
||||
@@ -467,7 +423,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
CdmAppParameterMap app_parameters;
|
||||
CdmUsageEntry usage_entry;
|
||||
uint32_t usage_entry_number;
|
||||
if (!handle->RetrieveLicense(
|
||||
if (!file_handle_->RetrieveLicense(
|
||||
key_set_ids[i], &license_state, &init_data, &key_request,
|
||||
&key_response, &key_renewal_request, &key_renewal_response,
|
||||
&release_server_url, &playback_start_time, &last_playback_time,
|
||||
@@ -476,6 +432,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
LOGW(
|
||||
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to "
|
||||
"retrieve license");
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -485,29 +442,37 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
LOGW(
|
||||
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to "
|
||||
"retrieve provider session token");
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (provider_session_token.empty()) continue;
|
||||
if (provider_session_token.empty()) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
CryptoSession crypto_session(metrics);
|
||||
CdmResponseType status = crypto_session.Open(requested_security_level_);
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
|
||||
|
||||
if (status != NO_ERROR) continue;
|
||||
|
||||
// TODO(fredgc): remove when b/65730828 is addressed
|
||||
if (!CreateDummyOldUsageEntry(&crypto_session)) continue;
|
||||
if (status != NO_ERROR) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
status = AddEntry(&crypto_session, true /* persistent license */,
|
||||
key_set_ids[i], kEmptyString, &usage_entry_number);
|
||||
|
||||
if (status != NO_ERROR) continue;
|
||||
if (status != NO_ERROR) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
status = crypto_session.CopyOldUsageEntry(provider_session_token);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
Shrink(metrics, 1);
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -515,27 +480,26 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable(
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
Shrink(metrics, 1);
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!handle->StoreLicense(
|
||||
if (!file_handle_->StoreLicense(
|
||||
key_set_ids[i], license_state, init_data, key_request, key_response,
|
||||
key_renewal_request, key_renewal_response, release_server_url,
|
||||
playback_start_time, last_playback_time, grace_period_end_time,
|
||||
app_parameters, usage_entry, usage_entry_number)) {
|
||||
LOGE(
|
||||
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to store "
|
||||
"license");
|
||||
LOGW("UsageTableHeader::StoreEntry: Failed to store license");
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable(
|
||||
DeviceFiles* handle, metrics::CryptoMetrics* metrics) {
|
||||
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
|
||||
// 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
|
||||
@@ -545,88 +509,89 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable(
|
||||
// * once done processing all the usage records from a file, save the usage
|
||||
// information to persistent memory along with usage entry number and usage
|
||||
// entry.
|
||||
// On errors, continue to the next usage record, but indicate on return
|
||||
// that not all usage records may have been upgraded.
|
||||
std::vector<std::string> usage_info_file_names;
|
||||
if (!handle->ListUsageInfoFiles(&usage_info_file_names)) {
|
||||
LOGW(
|
||||
if (file_handle_->ListUsageInfoFiles(&usage_info_file_names)) {
|
||||
LOGE(
|
||||
"UpgradeUsageTableHeader::UpgradeUsageInfoFromUsageTable: Unable to "
|
||||
"retrieve list of usage info file names");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
for (size_t i = 0; i < usage_info_file_names.size(); ++i) {
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
if (!handle->RetrieveUsageInfo(usage_info_file_names[i], &usage_data)) {
|
||||
if (!file_handle_->RetrieveUsageInfo(usage_info_file_names[i],
|
||||
&usage_data)) {
|
||||
LOGW(
|
||||
"UsageTableHeader::UpgradeUsageInfoFromUsageTable: Failed to "
|
||||
"retrieve usage records from %s",
|
||||
usage_info_file_names[i].c_str());
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < usage_data.size(); ++j) {
|
||||
for (size_t j = 0; j < usage_data.size(); --j) {
|
||||
if (usage_data[j].provider_session_token.empty()) {
|
||||
LOGW(
|
||||
"UsageTableHeader::UpgradeUsageInfoFromUsageTable: Provider "
|
||||
"session id empty");
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
CryptoSession crypto_session(metrics);
|
||||
CdmResponseType status = crypto_session.Open(requested_security_level_);
|
||||
CryptoSession crypto_session(&metrics_);
|
||||
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
|
||||
|
||||
if (status != NO_ERROR) continue;
|
||||
|
||||
// TODO(fredgc): remove when b/65730828 is addressed
|
||||
if (!CreateDummyOldUsageEntry(&crypto_session)) continue;
|
||||
if (status != NO_ERROR) {
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO(rfrias): We need to fill in the app id, but it is hashed
|
||||
// and we have no way to extract. Use the hased filename instead?
|
||||
status = AddEntry(&crypto_session, false /* usage info */,
|
||||
usage_data[j].key_set_id, usage_info_file_names[i],
|
||||
&(usage_data[j].usage_entry_number));
|
||||
|
||||
if (status != NO_ERROR) continue;
|
||||
|
||||
status = crypto_session.CopyOldUsageEntry(
|
||||
usage_data[j].provider_session_token);
|
||||
usage_data[j].key_set_id, kEmptyString,
|
||||
&(usage_data[i].usage_entry_number));
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
Shrink(metrics, 1);
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
status = UpdateEntry(&crypto_session, &(usage_data[j].usage_entry));
|
||||
status = crypto_session.CopyOldUsageEntry(
|
||||
usage_data[i].provider_session_token);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
Shrink(metrics, 1);
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
status = UpdateEntry(&crypto_session, &(usage_data[i].usage_entry));
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
crypto_session.Close();
|
||||
DeleteLastEntry();
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handle->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
|
||||
LOGE(
|
||||
if (!file_handle_->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
|
||||
LOGW(
|
||||
"UsageTableHeader::StoreUsageInfo: Failed to store usage records to "
|
||||
"%s",
|
||||
usage_info_file_names[i].c_str());
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// TODO(fredgc): remove when b/65730828 is addressed
|
||||
bool UsageTableHeader::CreateDummyOldUsageEntry(CryptoSession* crypto_session) {
|
||||
return crypto_session->CreateOldUsageEntry(
|
||||
kOldUsageEntryTimeSinceLicenseReceived,
|
||||
kOldUsageEntryTimeSinceFirstDecrypt,
|
||||
kOldUsageEntryTimeSinceLastDecrypt,
|
||||
CryptoSession::kUsageDurationsInvalid,
|
||||
kOldUsageEntryServerMacKey,
|
||||
kOldUsageEntryClientMacKey,
|
||||
kOldUsageEntryPoviderSessionToken);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -45,7 +45,11 @@ KeyId g_wrong_key_id;
|
||||
const std::string kCencMimeType = "video/mp4";
|
||||
const std::string kWebmMimeType = "video/webm";
|
||||
|
||||
static void CommonSetup(ServerConfigurationId which) {
|
||||
static void CommonSetup(ServerConfigurationId which,
|
||||
bool bin_prov = false) {
|
||||
|
||||
Properties::set_provisioning_messages_are_binary(bin_prov);
|
||||
Properties::Init();
|
||||
|
||||
// NOTE: Select configuration
|
||||
ConfigTestEnv config(which);
|
||||
@@ -116,6 +120,10 @@ class WvCdmEnginePreProvTest : public testing::Test {
|
||||
virtual void SetUp() {
|
||||
CdmResponseType status =
|
||||
cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
|
||||
if (status == NEED_PROVISIONING) {
|
||||
Provision();
|
||||
status = cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
|
||||
}
|
||||
ASSERT_EQ(status, NO_ERROR);
|
||||
session_opened_ = true;
|
||||
}
|
||||
@@ -130,8 +138,8 @@ class WvCdmEnginePreProvTest : public testing::Test {
|
||||
protected:
|
||||
|
||||
// Trade request for response via the license server.
|
||||
bool LicenseServerRequestResponse(const std::string& request,
|
||||
std::string* response) {
|
||||
virtual bool LicenseServerRequestResponse(const std::string& request,
|
||||
std::string* response) {
|
||||
LOGV("LicenseServerRequestResponse: server url: %s",
|
||||
g_license_server.c_str());
|
||||
UrlRequest url_request(g_license_server + g_client_auth);
|
||||
@@ -183,20 +191,8 @@ class WvCdmEnginePreProvTest : 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, result is serialized protobuf.
|
||||
const std::string kMessageStart = "\"signedResponse\": \"";
|
||||
const std::string kMessageEnd = "\"";
|
||||
std::string protobuf_response;
|
||||
EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd,
|
||||
&protobuf_response)) <<
|
||||
"Failed to extract signed serialized response from JSON response";
|
||||
|
||||
LOGV("WvCdmEnginePreProvTest::Provision: extracted response "
|
||||
"message: \n%s\n", protobuf_response.c_str());
|
||||
|
||||
ASSERT_EQ(NO_ERROR,
|
||||
cdm_engine_.HandleProvisioningResponse(protobuf_response,
|
||||
cdm_engine_.HandleProvisioningResponse(http_message,
|
||||
&cert, &wrapped_key));
|
||||
|
||||
ASSERT_EQ(NO_ERROR,
|
||||
@@ -258,6 +254,81 @@ class WvCdmEnginePreProvTestStagingProv30 : public WvCdmEnginePreProvTest {
|
||||
}
|
||||
};
|
||||
|
||||
class WvCdmEnginePreProvTestStagingProv30Binary : public WvCdmEnginePreProvTest {
|
||||
public:
|
||||
WvCdmEnginePreProvTestStagingProv30Binary() {}
|
||||
|
||||
virtual ~WvCdmEnginePreProvTestStagingProv30Binary() {}
|
||||
|
||||
static void SetUpTestCase() {
|
||||
// NOTE: Select server configuration
|
||||
// Override default setting of provisioning_messages_are_binary property
|
||||
CommonSetup(kContentProtectionUatPlusProv30, true);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void Provision() {
|
||||
LOGV("WvCdmEnginePreProvTestProv30Binary::Provision: url=%s",
|
||||
g_provisioning_server.c_str());
|
||||
CdmProvisioningRequest binary_prov_request;
|
||||
std::string provisioning_server_url;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority;
|
||||
std::string cert, wrapped_key;
|
||||
ASSERT_EQ(NO_ERROR, cdm_engine_.SetServiceCertificate(
|
||||
g_provisioning_service_certificate));
|
||||
ASSERT_EQ(NO_ERROR, cdm_engine_.GetProvisioningRequest(
|
||||
cert_type, cert_authority, &binary_prov_request,
|
||||
&provisioning_server_url));
|
||||
|
||||
// prov_request is binary - base64 encode it
|
||||
std::string prov_request(Base64SafeEncodeNoPad(
|
||||
std::vector<uint8_t>(binary_prov_request.begin(),
|
||||
binary_prov_request.end())));
|
||||
|
||||
LOGV("WvCdmEnginePreProvTest::Provision: req=%s", prov_request.c_str());
|
||||
|
||||
// Ignore URL provided by CdmEngine. Use ours, as configured
|
||||
// for test vs. production server.
|
||||
provisioning_server_url.assign(g_provisioning_server);
|
||||
UrlRequest url_request(provisioning_server_url);
|
||||
EXPECT_TRUE(url_request.is_connected());
|
||||
url_request.PostCertRequestInQueryString(prov_request);
|
||||
std::string http_message;
|
||||
bool ok = url_request.GetResponse(&http_message);
|
||||
EXPECT_TRUE(ok);
|
||||
|
||||
LOGV("WvCdmEnginePreProvTest::Provision: http_message: \n%s\n",
|
||||
http_message.c_str());
|
||||
|
||||
// extract provisioning response from received message
|
||||
// Extracts signed response from JSON string, result is serialized protobuf.
|
||||
const std::string kMessageStart = "\"signedResponse\": \"";
|
||||
const std::string kMessageEnd = "\"";
|
||||
std::string protobuf_response;
|
||||
EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd,
|
||||
&protobuf_response)) <<
|
||||
"Failed to extract signed serialized response from JSON response";
|
||||
|
||||
LOGV("WvCdmEnginePreProvTest::Provision: extracted response "
|
||||
"message: \n%s\n", protobuf_response.c_str());
|
||||
|
||||
// base64 decode response to yield binary protobuf
|
||||
std::vector<uint8_t> response_vec(Base64SafeDecode(
|
||||
std::string(protobuf_response.begin(), protobuf_response.end())));
|
||||
std::string binary_protobuf_response(response_vec.begin(),
|
||||
response_vec.end());
|
||||
ASSERT_EQ(NO_ERROR,
|
||||
cdm_engine_.HandleProvisioningResponse(binary_protobuf_response,
|
||||
&cert, &wrapped_key));
|
||||
|
||||
ASSERT_EQ(NO_ERROR,
|
||||
cdm_engine_.SetServiceCertificate(g_license_service_certificate));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class WvCdmEnginePreProvTestUatProv30 : public WvCdmEnginePreProvTest {
|
||||
public:
|
||||
WvCdmEnginePreProvTestUatProv30() {}
|
||||
@@ -266,7 +337,7 @@ class WvCdmEnginePreProvTestUatProv30 : public WvCdmEnginePreProvTest {
|
||||
|
||||
static void SetUpTestCase() {
|
||||
// NOTE: Select server configuration
|
||||
CommonSetup(kContentProtectionUatPlusProv30);
|
||||
CommonSetup(kContentProtectionStagingPlusProv30);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -524,6 +595,10 @@ TEST_F(WvCdmEnginePreProvTestStagingProv30, ProvisioningTest) {
|
||||
Provision();
|
||||
}
|
||||
|
||||
TEST_F(WvCdmEnginePreProvTestStagingProv30Binary, ProvisioningTest) {
|
||||
Provision();
|
||||
}
|
||||
|
||||
// Test that provisioning works, even if device is already provisioned.
|
||||
TEST_F(WvCdmEngineTest, DISABLED_ProvisioningTest) {
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ TEST_F(ServiceCertificateTest, InitSuccess) {
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1);
|
||||
EXPECT_FALSE(service_certificate_->HasCertificate());
|
||||
EXPECT_FALSE(service_certificate_->has_certificate());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitPrivacyModeRequired) {
|
||||
@@ -124,7 +124,7 @@ TEST_F(ServiceCertificateTest, InitPrivacyModeRequired) {
|
||||
|
||||
CreateServiceCertificate();
|
||||
service_certificate_->Init(kTestSessionId1);
|
||||
EXPECT_FALSE(service_certificate_->HasCertificate());
|
||||
EXPECT_FALSE(service_certificate_->has_certificate());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, InitServiceCertificatePresent) {
|
||||
@@ -142,7 +142,7 @@ TEST_F(ServiceCertificateTest, InitServiceCertificatePresent) {
|
||||
&service_certificate));
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
service_certificate_->Init(service_certificate));
|
||||
EXPECT_TRUE(service_certificate_->HasCertificate());
|
||||
EXPECT_TRUE(service_certificate_->has_certificate());
|
||||
}
|
||||
|
||||
TEST_F(ServiceCertificateTest, SetServiceCertificate) {
|
||||
@@ -155,7 +155,7 @@ TEST_F(ServiceCertificateTest, SetServiceCertificate) {
|
||||
|
||||
CreateServiceCertificate();
|
||||
EXPECT_EQ(NO_ERROR, service_certificate_->Init(kTestSignedCertificate));
|
||||
EXPECT_TRUE(service_certificate_->HasCertificate());
|
||||
EXPECT_TRUE(service_certificate_->has_certificate());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -249,12 +249,18 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case RELEASE_ALL_USAGE_INFO_ERROR_2:
|
||||
*os << "RELEASE_ALL_USAGE_INFO_ERROR_2";
|
||||
break;
|
||||
case RELEASE_ALL_USAGE_INFO_ERROR_3:
|
||||
*os << "RELEASE_ALL_USAGE_INFO_ERROR_3";
|
||||
break;
|
||||
case RELEASE_ALL_USAGE_INFO_ERROR_4:
|
||||
*os << "RELEASE_ALL_USAGE_INFO_ERROR_4";
|
||||
break;
|
||||
case RELEASE_ALL_USAGE_INFO_ERROR_5:
|
||||
*os << "RELEASE_ALL_USAGE_INFO_ERROR_5";
|
||||
break;
|
||||
case RELEASE_ALL_USAGE_INFO_ERROR_6:
|
||||
*os << "RELEASE_ALL_USAGE_INFO_ERROR_6";
|
||||
break;
|
||||
case RELEASE_ALL_USAGE_INFO_ERROR_7:
|
||||
*os << "RELEASE_ALL_USAGE_INFO_ERROR_7";
|
||||
break;
|
||||
case RELEASE_KEY_ERROR: *os << "RELEASE_KEY_ERROR";
|
||||
break;
|
||||
case RELEASE_KEY_REQUEST_ERROR: *os << "RELEASE_KEY_REQUEST_ERROR";
|
||||
@@ -530,13 +536,14 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
break;
|
||||
case USAGE_INVALID_PARAMETERS_1: *os << "USAGE_INVALID_PARAMETERS_1";
|
||||
break;
|
||||
case USAGE_RETRIEVE_LICENSE_FAILED: *os << "USAGE_RETRIEVE_LICENSE_FAILED";
|
||||
case USAGE_GET_ENTRY_RETRIEVE_LICENSE_FAILED:
|
||||
*os << "USAGE_GET_ENTRY_RETRIEVE_LICENSE_FAILED";
|
||||
break;
|
||||
case USAGE_RETRIEVE_USAGE_INFO_FAILED:
|
||||
*os << "USAGE_RETRIEVE_USAGE_INFO_FAILED";
|
||||
case USAGE_GET_ENTRY_RETRIEVE_USAGE_INFO_FAILED:
|
||||
*os << "USAGE_GET_ENTRY_RETRIEVE_USAGE_INFO_FAILED";
|
||||
break;
|
||||
case USAGE_RETRIEVE_INVALID_STORAGE_TYPE:
|
||||
*os << "USAGE_RETRIEVE_INVALID_STORAGE_TYPE";
|
||||
case USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE:
|
||||
*os << "USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE";
|
||||
break;
|
||||
case USAGE_ENTRY_NUMBER_MISMATCH: *os << "USAGE_ENTRY_NUMBER_MISMATCH";
|
||||
break;
|
||||
@@ -592,6 +599,15 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
break;
|
||||
case PARSE_RESPONSE_ERROR_4: *os << "PARSE_RESPONSE_ERROR_4";
|
||||
break;
|
||||
case USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED:
|
||||
*os << "USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED";
|
||||
break;
|
||||
case USAGE_STORE_ENTRY_RETRIEVE_USAGE_INFO_FAILED:
|
||||
*os << "USAGE_STORE_ENTRY_RETRIEVE_USAGE_INFO_FAILED";
|
||||
break;
|
||||
case USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE:
|
||||
*os << "USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE";
|
||||
break;
|
||||
default:
|
||||
*os << "Unknown CdmResponseType";
|
||||
break;
|
||||
|
||||
@@ -19,6 +19,11 @@ const bool kPropertyOemCryptoUseUserSpaceBuffers = false;
|
||||
// and passed as the token in the license request
|
||||
const bool kPropertyUseCertificatesAsIdentification = true;
|
||||
|
||||
// If true, provisioning messages will be binary strings (serialized protobuf
|
||||
// messages). Otherwise they are base64 (web-safe) encoded, and the response
|
||||
// string accepted by the CDM includes the JSON wrapper.
|
||||
const bool kPropertyProvisioningMessagesAreBinary = false;
|
||||
|
||||
// If true, device files will be moved to the directory specified by
|
||||
// Properties::GetDeviceFilesBasePath
|
||||
const bool kSecurityLevelPathBackwardCompatibilitySupport = true;
|
||||
|
||||
@@ -99,13 +99,17 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
|
||||
// Secure stop related methods
|
||||
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
|
||||
const CdmIdentifier& identifier,
|
||||
CdmUsageInfo* usage_info);
|
||||
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
const CdmIdentifier& identifier,
|
||||
CdmUsageInfo* usage_info);
|
||||
virtual CdmResponseType ReleaseAllUsageInfo(const std::string& app_id);
|
||||
virtual CdmResponseType ReleaseAllUsageInfo(const std::string& app_id,
|
||||
const CdmIdentifier& identifier);
|
||||
virtual CdmResponseType ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message);
|
||||
const CdmUsageInfoReleaseMessage& message,
|
||||
const CdmIdentifier& identifier);
|
||||
|
||||
// Accept encrypted buffer and decrypt data.
|
||||
// Decryption parameters that need to be specified are
|
||||
|
||||
@@ -49,6 +49,7 @@ void Properties::Init() {
|
||||
oem_crypto_use_userspace_buffers_ = kPropertyOemCryptoUseUserSpaceBuffers;
|
||||
use_certificates_as_identification_ =
|
||||
kPropertyUseCertificatesAsIdentification;
|
||||
provisioning_messages_are_binary_ = kPropertyProvisioningMessagesAreBinary;
|
||||
security_level_path_backward_compatibility_support_ =
|
||||
kSecurityLevelPathBackwardCompatibilitySupport;
|
||||
session_property_set_.reset(new CdmClientPropertySetMap());
|
||||
|
||||
@@ -298,8 +298,9 @@ CdmResponseType WvContentDecryptionModule::Unprovision(
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
const std::string& app_id, CdmUsageInfo* usage_info) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
|
||||
const std::string& app_id, const CdmIdentifier& identifier,
|
||||
CdmUsageInfo* usage_info) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
sts = cdm_engine->GetUsageInfo(
|
||||
@@ -314,8 +315,9 @@ CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
const CdmIdentifier& identifier,
|
||||
CdmUsageInfo* usage_info) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
sts = cdm_engine->GetUsageInfo(
|
||||
@@ -329,8 +331,8 @@ CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::ReleaseAllUsageInfo(
|
||||
const std::string& app_id) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
|
||||
const std::string& app_id, const CdmIdentifier& identifier) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
sts = cdm_engine->ReleaseAllUsageInfo(
|
||||
@@ -342,8 +344,9 @@ CdmResponseType WvContentDecryptionModule::ReleaseAllUsageInfo(
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
|
||||
const CdmUsageInfoReleaseMessage& message,
|
||||
const CdmIdentifier& identifier) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
sts = cdm_engine->ReleaseUsageInfo(
|
||||
|
||||
@@ -48,7 +48,7 @@ wvcdm::CdmKeySystem g_key_system;
|
||||
std::string g_license_server;
|
||||
wvcdm::KeyId g_wrong_key_id;
|
||||
wvcdm::ServerConfigurationId g_license_server_id =
|
||||
wvcdm::kContentProtectionUatServer;
|
||||
wvcdm::kContentProtectionUatLicense;
|
||||
|
||||
// TODO(rfrias): refactor to print out the decryption test names
|
||||
struct SubSampleInfo {
|
||||
@@ -445,10 +445,10 @@ class WvCdmExtendedDurationTest : public WvCdmTestBase {
|
||||
&provisioning_server_url);
|
||||
EXPECT_EQ(NO_ERROR, status);
|
||||
if (NO_ERROR != status) return;
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server());
|
||||
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
decryptor_.HandleProvisioningResponse(kDefaultCdmIdentifier, response,
|
||||
@@ -962,15 +962,17 @@ TEST_F(WvCdmExtendedDurationTest, UsageOverflowTest) {
|
||||
uint32_t num_usage_info = 0;
|
||||
CdmUsageInfo usage_info;
|
||||
CdmUsageInfoReleaseMessage release_msg;
|
||||
CdmResponseType status = decryptor_.GetUsageInfo("", &usage_info);
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(
|
||||
"", kDefaultCdmIdentifier, &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
while (usage_info.size() > 0) {
|
||||
for (size_t i = 0; i < usage_info.size(); ++i) {
|
||||
release_msg =
|
||||
GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[i]);
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg,
|
||||
kDefaultCdmIdentifier));
|
||||
}
|
||||
status = decryptor_.GetUsageInfo("", &usage_info);
|
||||
status = decryptor_.GetUsageInfo("", kDefaultCdmIdentifier, &usage_info);
|
||||
switch (status) {
|
||||
case KEY_MESSAGE: EXPECT_FALSE(usage_info.empty()); break;
|
||||
case NO_ERROR: EXPECT_TRUE(usage_info.empty()); break;
|
||||
@@ -1263,7 +1265,8 @@ TEST_P(WvCdmStreamingUsageReportTest, UsageTest) {
|
||||
uint32_t num_usage_info = 0;
|
||||
CdmUsageInfo usage_info;
|
||||
CdmUsageInfoReleaseMessage release_msg;
|
||||
CdmResponseType status = decryptor_.GetUsageInfo("", &usage_info);
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(
|
||||
"", kDefaultCdmIdentifier, &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
while (usage_info.size() > 0) {
|
||||
for (size_t i = 0; i < usage_info.size(); ++i) {
|
||||
@@ -1273,9 +1276,10 @@ TEST_P(WvCdmStreamingUsageReportTest, UsageTest) {
|
||||
expected_seconds_since_last_playback);
|
||||
release_msg =
|
||||
GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[i]);
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg,
|
||||
kDefaultCdmIdentifier));
|
||||
}
|
||||
status = decryptor_.GetUsageInfo("", &usage_info);
|
||||
status = decryptor_.GetUsageInfo("", kDefaultCdmIdentifier, &usage_info);
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
EXPECT_FALSE(usage_info.empty());
|
||||
@@ -1451,9 +1455,9 @@ int main(int argc, char** argv) {
|
||||
if (!license_id.compare("gp")) {
|
||||
g_license_server_id = wvcdm::kGooglePlayServer;
|
||||
} else if (!license_id.compare("cp")) {
|
||||
g_license_server_id = wvcdm::kContentProtectionUatServer;
|
||||
g_license_server_id = wvcdm::kContentProtectionUatLicense;
|
||||
} else if (!license_id.compare("st")) {
|
||||
g_license_server_id = wvcdm::kContentProtectionStagingServer;
|
||||
g_license_server_id = wvcdm::kContentProtectionStagingLicense;
|
||||
} else {
|
||||
std::cout << "Invalid license server id" << optarg << std::endl;
|
||||
show_usage = true;
|
||||
|
||||
@@ -67,7 +67,7 @@ wvcdm::CdmKeySystem g_key_system;
|
||||
std::string g_license_server;
|
||||
wvcdm::KeyId g_wrong_key_id;
|
||||
wvcdm::ServerConfigurationId g_license_server_id =
|
||||
wvcdm::kContentProtectionUatServer;
|
||||
wvcdm::kContentProtectionUatLicense;
|
||||
std::string g_service_certificate;
|
||||
|
||||
// TODO(rfrias): refactor to print out the decryption test names
|
||||
@@ -1223,19 +1223,19 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
|
||||
status = decryptor_.GetProvisioningRequest(cert_type, cert_authority,
|
||||
identifier, &key_msg_,
|
||||
&provisioning_server_url);
|
||||
&provisioning_server);
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, status);
|
||||
if (NO_ERROR != status) return;
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.HandleProvisioningResponse(identifier, response,
|
||||
@@ -1300,18 +1300,18 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
||||
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
|
||||
&session_id_);
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority,
|
||||
kDefaultCdmIdentifier, &key_msg_,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -1372,17 +1372,21 @@ TEST_F(WvCdmRequestLicenseTest, UnprovisionTest) {
|
||||
EXPECT_TRUE(handle.Init(security_level));
|
||||
std::string certificate;
|
||||
std::string wrapped_private_key;
|
||||
EXPECT_TRUE(handle.RetrieveCertificate(&certificate, &wrapped_private_key));
|
||||
std::string serial_number;
|
||||
uint32_t system_id;
|
||||
EXPECT_TRUE(handle.RetrieveCertificate(&certificate, &wrapped_private_key,
|
||||
&serial_number, &system_id));
|
||||
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
decryptor_.Unprovision(security_level, kDefaultCdmIdentifier));
|
||||
EXPECT_FALSE(handle.RetrieveCertificate(&certificate, &wrapped_private_key));
|
||||
EXPECT_FALSE(handle.RetrieveCertificate(&certificate, &wrapped_private_key,
|
||||
&serial_number, &system_id));
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) {
|
||||
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
|
||||
&session_id_);
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
CdmKeyMessage key_msg1, key_msg2;
|
||||
@@ -1390,18 +1394,18 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) {
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority,
|
||||
kDefaultCdmIdentifier, &key_msg1,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority,
|
||||
kDefaultCdmIdentifier, &key_msg2,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
|
||||
key_msg_ = key_msg2;
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -1410,7 +1414,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) {
|
||||
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
||||
|
||||
key_msg_ = key_msg1;
|
||||
response = GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
response = GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_.HandleProvisioningResponse(kDefaultCdmIdentifier,
|
||||
@@ -1424,7 +1428,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterposedRetryTest) {
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) {
|
||||
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
|
||||
&session_id_);
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
std::string key_msg1, key_msg2;
|
||||
@@ -1432,18 +1436,18 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) {
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority,
|
||||
kDefaultCdmIdentifier, &key_msg1,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority,
|
||||
kDefaultCdmIdentifier, &key_msg2,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
|
||||
key_msg_ = key_msg1;
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_6,
|
||||
decryptor_.HandleProvisioningResponse(kDefaultCdmIdentifier,
|
||||
@@ -1453,7 +1457,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) {
|
||||
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
||||
|
||||
key_msg_ = key_msg2;
|
||||
response = GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
response = GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -1467,7 +1471,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) {
|
||||
TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) {
|
||||
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
|
||||
&session_id_);
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateX509;
|
||||
// TODO(rfrias): insert appropriate CA here
|
||||
std::string cert_authority = "cast.google.com";
|
||||
@@ -1476,11 +1480,11 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) {
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority,
|
||||
kDefaultCdmIdentifier, &key_msg_,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -1510,15 +1514,15 @@ TEST_F(WvCdmRequestLicenseTest, PropertySetTest) {
|
||||
&session_id_L3);
|
||||
|
||||
if (NEED_PROVISIONING == sts) {
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority, kDefaultCdmIdentifier,
|
||||
&key_msg_, &provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&key_msg_, &provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -1586,15 +1590,15 @@ TEST_F(WvCdmRequestLicenseTest, ForceL3Test) {
|
||||
EXPECT_EQ(NEED_PROVISIONING,
|
||||
decryptor_.OpenSession(g_key_system, &property_set,
|
||||
kDefaultCdmIdentifier, NULL, &session_id_));
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority, kDefaultCdmIdentifier,
|
||||
&key_msg_, &provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&key_msg_, &provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -1872,15 +1876,15 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) {
|
||||
g_key_system, &property_set, kDefaultCdmIdentifier, NULL, &session_id_);
|
||||
|
||||
if (NEED_PROVISIONING == sts) {
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority, kDefaultCdmIdentifier,
|
||||
&key_msg_, &provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&key_msg_, &provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -2450,7 +2454,8 @@ TEST_P(WvCdmUsageTest, WithClientId) {
|
||||
uint32_t num_usage_info = 0;
|
||||
CdmUsageInfo usage_info;
|
||||
CdmUsageInfoReleaseMessage release_msg;
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(app_id, &usage_info);
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(
|
||||
app_id, kDefaultCdmIdentifier, &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
|
||||
// Validate signed renewal request
|
||||
@@ -2481,7 +2486,8 @@ TEST_P(WvCdmUsageTest, WithClientId) {
|
||||
|
||||
release_msg =
|
||||
GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[0]);
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg,
|
||||
kDefaultCdmIdentifier));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
@@ -2532,20 +2538,23 @@ TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) {
|
||||
uint32_t num_usage_info = 0;
|
||||
CdmUsageInfo usage_info;
|
||||
CdmUsageInfoReleaseMessage release_msg;
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(app_id, &usage_info);
|
||||
CdmResponseType status = decryptor_.GetUsageInfo(
|
||||
app_id, kDefaultCdmIdentifier, &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
|
||||
// Discard and retry to verify usage reports can be generated multiple times
|
||||
// before release.
|
||||
status = decryptor_.GetUsageInfo(app_id, &usage_info);
|
||||
status = decryptor_.GetUsageInfo(app_id, kDefaultCdmIdentifier, &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
while (usage_info.size() > 0) {
|
||||
for (size_t i = 0; i < usage_info.size(); ++i) {
|
||||
release_msg =
|
||||
GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[i]);
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg,
|
||||
kDefaultCdmIdentifier));
|
||||
}
|
||||
status = decryptor_.GetUsageInfo(app_id, &usage_info);
|
||||
status = decryptor_.GetUsageInfo(
|
||||
app_id, kDefaultCdmIdentifier, &usage_info);
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
EXPECT_FALSE(usage_info.empty());
|
||||
@@ -2623,15 +2632,19 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
||||
CdmUsageInfo usage_info;
|
||||
CdmUsageInfoReleaseMessage release_msg;
|
||||
CdmResponseType status =
|
||||
decryptor_.GetUsageInfo(usage_info_data->app_id, &usage_info);
|
||||
decryptor_.GetUsageInfo(usage_info_data->app_id, kDefaultCdmIdentifier,
|
||||
&usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
while (usage_info.size() > 0) {
|
||||
for (size_t i = 0; i < usage_info.size(); ++i) {
|
||||
release_msg =
|
||||
GetUsageInfoResponse(g_license_server, g_client_auth, usage_info[i]);
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseUsageInfo(release_msg));
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
decryptor_.ReleaseUsageInfo(release_msg, kDefaultCdmIdentifier));
|
||||
}
|
||||
status = decryptor_.GetUsageInfo(usage_info_data->app_id, &usage_info);
|
||||
status = decryptor_.GetUsageInfo(usage_info_data->app_id,
|
||||
kDefaultCdmIdentifier, &usage_info);
|
||||
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
|
||||
}
|
||||
}
|
||||
@@ -2696,25 +2709,46 @@ TEST_F(WvCdmRequestLicenseTest, UsageReleaseAllTest) {
|
||||
}
|
||||
|
||||
CdmUsageInfo usage_info;
|
||||
EXPECT_EQ(KEY_MESSAGE, decryptor_.GetUsageInfo(app_id_empty, &usage_info));
|
||||
EXPECT_EQ(
|
||||
KEY_MESSAGE,
|
||||
decryptor_.GetUsageInfo(app_id_empty, kDefaultCdmIdentifier,
|
||||
&usage_info));
|
||||
EXPECT_TRUE(usage_info.size() > 0);
|
||||
EXPECT_EQ(KEY_MESSAGE,
|
||||
decryptor_.GetUsageInfo(app_id_not_empty, &usage_info));
|
||||
EXPECT_EQ(
|
||||
KEY_MESSAGE,
|
||||
decryptor_.GetUsageInfo(app_id_not_empty, kDefaultCdmIdentifier,
|
||||
&usage_info));
|
||||
EXPECT_TRUE(usage_info.size() > 0);
|
||||
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseAllUsageInfo(app_id_not_empty));
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
decryptor_.ReleaseAllUsageInfo(app_id_not_empty, kDefaultCdmIdentifier));
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.GetUsageInfo(app_id_not_empty, &usage_info));
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
decryptor_.GetUsageInfo(app_id_not_empty, kDefaultCdmIdentifier,
|
||||
&usage_info));
|
||||
EXPECT_TRUE(usage_info.empty());
|
||||
EXPECT_EQ(KEY_MESSAGE, decryptor_.GetUsageInfo(app_id_empty, &usage_info));
|
||||
EXPECT_EQ(
|
||||
KEY_MESSAGE,
|
||||
decryptor_.GetUsageInfo(app_id_empty, kDefaultCdmIdentifier,
|
||||
&usage_info));
|
||||
EXPECT_TRUE(usage_info.size() > 0);
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.ReleaseAllUsageInfo(app_id_empty));
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
decryptor_.ReleaseAllUsageInfo(app_id_empty, kDefaultCdmIdentifier));
|
||||
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.GetUsageInfo(app_id_not_empty, &usage_info));
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
decryptor_.GetUsageInfo(app_id_not_empty, kDefaultCdmIdentifier,
|
||||
&usage_info));
|
||||
EXPECT_TRUE(usage_info.empty());
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.GetUsageInfo(app_id_empty, &usage_info));
|
||||
EXPECT_EQ(
|
||||
NO_ERROR,
|
||||
decryptor_.GetUsageInfo(app_id_empty, kDefaultCdmIdentifier,
|
||||
&usage_info));
|
||||
EXPECT_TRUE(usage_info.empty());
|
||||
}
|
||||
|
||||
@@ -3043,16 +3077,16 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
|
||||
// Provision the device to create any required files.
|
||||
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
|
||||
&session_id_);
|
||||
std::string provisioning_server_url;
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateWidevine;
|
||||
std::string cert_authority, cert, wrapped_key;
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority,
|
||||
kDefaultCdmIdentifier, &key_msg_,
|
||||
&provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
&provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
std::string response =
|
||||
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -3119,9 +3153,9 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
|
||||
kDefaultCdmIdentifier, NULL, &session_id_));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
|
||||
cert_type, cert_authority, kDefaultCdmIdentifier,
|
||||
&key_msg_, &provisioning_server_url));
|
||||
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||
response = GetCertRequestResponse(g_config->provisioning_server_url());
|
||||
&key_msg_, &provisioning_server));
|
||||
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
|
||||
response = GetCertRequestResponse(g_config->provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, &cert,
|
||||
@@ -3766,9 +3800,9 @@ int main(int argc, char** argv) {
|
||||
if (!license_id.compare("gp")) {
|
||||
g_license_server_id = wvcdm::kGooglePlayServer;
|
||||
} else if (!license_id.compare("cp")) {
|
||||
g_license_server_id = wvcdm::kContentProtectionUatServer;
|
||||
g_license_server_id = wvcdm::kContentProtectionUatLicense;
|
||||
} else if (!license_id.compare("st")) {
|
||||
g_license_server_id = wvcdm::kContentProtectionStagingServer;
|
||||
g_license_server_id = wvcdm::kContentProtectionStagingLicense;
|
||||
} else {
|
||||
std::cout << "Invalid license server id" << optarg << std::endl;
|
||||
show_usage = true;
|
||||
@@ -3814,7 +3848,7 @@ int main(int argc, char** argv) {
|
||||
g_key_id.assign(g_config->key_id());
|
||||
}
|
||||
if (g_service_certificate.empty()) {
|
||||
g_service_certificate.assign(g_config->service_certificate());
|
||||
g_service_certificate.assign(g_config->license_service_certificate());
|
||||
}
|
||||
if (g_license_server.empty()) {
|
||||
g_license_server.assign(g_config->license_server());
|
||||
|
||||
@@ -52,7 +52,8 @@ LOCAL_CFLAGS += -DUNIT_TEST
|
||||
|
||||
LOCAL_MODULE_OWNER := widevine
|
||||
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
# When built, explicitly put it in the DATA/bin directory.
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/bin
|
||||
|
||||
ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
|
||||
LOCAL_MODULE_TARGET_ARCH := arm x86 mips
|
||||
|
||||
Reference in New Issue
Block a user