Merges to android Pi release (part 5)

These are a set of CLs merged from the wv cdm repo to the android repo.

* Change build options for make protobuf host tools

  Author: Gene Morgan <gmorgan@google.com>

  [ Merge of http://go/wvgerrit/30381 ]

  Also revert local change to protobuf/extension_set.cc
  This builds after adding -Wno-return-type and -Wno-unused flags.

* OEMCrypto v13 stub

  Author: Rintaro Kuroiwa <rkuroiwa@google.com>

  [ Merge of http://go/wvgerrit/30004 ]

* Remove merge conflict tags

  Author: Edwin Wong <edwinwong@google.com>

  [ Merge of http://go/wvgerrit/30120 ]

  Remove merge conflict tags for http://go/wvgerrit/29880

* Added Android Things ARM provisioning key to L3

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/29701 ]

  BUG: 63443584

BUG: 71650075
Test: Not currently passing. Will be addressed in a subsequent
      commit in the chain.

Change-Id: Ifd867b491dfda5d67d2e225695535b5af9e18260
This commit is contained in:
Rahul Frias
2018-01-09 18:03:56 -08:00
parent 169d0b6cb6
commit b7c9ad57c9
24 changed files with 1852 additions and 1129 deletions

View File

@@ -104,7 +104,26 @@ class CdmEngine {
const CdmSessionId& session_id, const CdmKeySetId& key_set_id,
const InitializationData& init_data, const CdmLicenseType license_type,
CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
// Accept license response and extract key info.
// This API may
// (a) accept license response, extract key info and load keys.
// (b) accept a renewal response and update license policy information.
// (c) accept a release response and release an offline license or secure
// stop.
// (d) accept a service certificate and cache that information for the
// the lifetime of the session.
//
// |session_id| identifies the session that generated the request and can
// process the response. Should be empty if a release response.
// |key_data| is the license, renewal, release response or service
// certificate response.
// |key_set_id| should be non-null and specified if license release.
// If offline license or streaming license associated with
// a secure stop, |key_set_id| should be non-null and will
// be filled in on return. Use the |key_set_id| with
// RestoreKeys (to reload offline session) or
// GenerateKeyRequest (to release offline session/secure stop).
// |key_set_id| will be cleared if release or streaming
// (not associated with a secure stop).
virtual CdmResponseType AddKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data,
CdmKeySetId* key_set_id);

View File

@@ -87,8 +87,7 @@ class CdmSession {
// ReleaseKey() - Accept response and release key.
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
virtual CdmResponseType DeleteUsageEntry(
const DeviceFiles::CdmUsageData& usage_data);
virtual CdmResponseType DeleteUsageEntry(uint32_t usage_entry_number);
virtual bool IsKeyLoaded(const KeyId& key_id);
virtual int64_t GetDurationRemaining();
@@ -122,6 +121,10 @@ class CdmSession {
virtual bool is_offline() { return is_offline_; }
virtual bool is_temporary() { return is_temporary_; }
virtual bool license_received() { return license_received_; }
virtual bool has_provider_session_token() {
return (license_parser_.get() != NULL &&
license_parser_->provider_session_token().size() > 0);
}
virtual CdmUsageSupportType get_usage_support_type()
{ return usage_support_type_; }

View File

@@ -17,6 +17,8 @@
namespace wvcdm {
class CryptoKey;
class UsageTableHeader;
typedef std::map<CryptoKeyId, CryptoKey*> CryptoKeyMap;
class CryptoSession {
@@ -145,6 +147,9 @@ class CryptoSession {
const std::string& signature);
// Usage table header and usage entry related methods
virtual UsageTableHeader* GetUsageTableHeader() {
return usage_table_header_;
}
virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type);
virtual CdmResponseType CreateUsageTableHeader(
CdmUsageTableHeader* usage_table_header);
@@ -230,7 +235,11 @@ class CryptoSession {
KeyId cached_key_id_;
bool is_usage_support_type_valid_;
CdmUsageSupportType usage_support_type_;
UsageTableHeader* usage_table_header_;
static UsageTableHeader* usage_table_header_l1_;
static UsageTableHeader* usage_table_header_l3_;
uint64_t request_id_base_;
static uint64_t request_id_index_;

View File

@@ -21,6 +21,7 @@ class Clock;
class CryptoSession;
class PolicyEngine;
class ServiceCertificate;
class CdmSession;
class CdmLicense {
public:
@@ -38,7 +39,8 @@ class CdmLicense {
std::string* server_url);
virtual CdmResponseType PrepareKeyUpdateRequest(
bool is_renewal, const CdmAppParameterMap& app_parameters,
CdmKeyMessage* signed_request, std::string* server_url);
CdmSession* cdm_session, CdmKeyMessage* signed_request,
std::string* server_url);
virtual CdmResponseType HandleKeyResponse(
const CdmKeyResponse& license_response);
virtual CdmResponseType HandleKeyUpdateResponse(

View File

@@ -7,6 +7,7 @@
#include <vector>
#include "device_files.h"
#include "file_store.h"
#include "lock.h"
#include "metrics_group.h"
#include "scoped_ptr.h"
@@ -15,28 +16,40 @@
namespace wvcdm {
class FileSystem;
class CryptoSession;
// 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.
// 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.
//
// 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| need to be saved in the license
// |usage_entry| and |usage_entry_number|s need to be saved in the license
// and usage info records by the caller.
class UsageTableHeader {
public:
// This methods instantiates or retrieves a usage table header singleton of
// appropriate security level as specified by the |crypto_session|
// object.
UsageTableHeader();
virtual ~UsageTableHeader() {}
// |crypto_session| is used to create or load a usage master table and
// not cached beyound this call.
static UsageTableHeader* GetInstance(FileSystem* file_system,
CryptoSession* crypto_session_);
virtual ~UsageTableHeader() {}
bool Init(CdmSecurityLevel security_level, CryptoSession* crypto_session);
// |persistent_license| false indicates usage info record
CdmResponseType AddEntry(CryptoSession* crypto_session,
@@ -53,56 +66,67 @@ 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);
CdmResponseType MoveEntry(uint32_t from_usage_entry_number,
const CdmUsageEntry& from_usage_entry,
uint32_t to_usage_entry_number);
CdmResponseType DeleteEntry(uint32_t usage_entry_number, DeviceFiles* handle,
metrics::MetricsGroup* metrics);
private:
UsageTableHeader(FileSystem* file_system, CryptoSession* crypto_session,
CdmSecurityLevel security_level);
CdmResponseType MoveEntry(uint32_t from /* usage entry number */,
const CdmUsageEntry& from_usage_entry,
uint32_t to /* usage entry number */,
DeviceFiles* handle,
metrics::MetricsGroup* metrics);
CdmResponseType GetEntry(uint32_t usage_entry_number,
CdmResponseType GetEntry(uint32_t usage_entry_number, DeviceFiles* handle,
CdmUsageEntry* usage_entry);
CdmResponseType StoreEntry(uint32_t usage_entry_number,
CdmResponseType StoreEntry(uint32_t usage_entry_number, DeviceFiles* handle,
const CdmUsageEntry& usage_entry);
bool DeleteLastEntry();
CdmResponseType Shrink(metrics::MetricsGroup* metrics,
uint32_t number_of_usage_entries_to_delete);
CdmResponseType UpgradeFromUsageTable();
// Indicates whether one of more license/usage records failed to be upgraded.
bool UpgradeLicensesFromUsageTable();
bool UpgradeUsageInfoFromUsageTable();
CdmResponseType UpgradeFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
bool UpgradeLicensesFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
bool UpgradeUsageInfoFromUsageTable(DeviceFiles* handle,
metrics::MetricsGroup* metrics);
virtual bool is_inited() { return is_inited_; }
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);
};

View File

@@ -64,6 +64,10 @@ static const std::string QUERY_KEY_MAX_NUMBER_OF_SESSIONS =
"MaxNumberOfSessions";
static const std::string QUERY_KEY_OEMCRYPTO_API_VERSION =
"OemCryptoApiVersion";
static const std::string QUERY_KEY_CURRENT_SRM_VERSION = "CurrentSRMVersion";
static const std::string QUERY_KEY_SRM_UPDATE_SUPPORT = "SRMUpdateSupport";
// whether OEM supports SRM update
static const std::string QUERY_KEY_WVCDM_VERSION = "WidevineCdmVersion";
static const std::string QUERY_VALUE_TRUE = "True";
static const std::string QUERY_VALUE_FALSE = "False";

View File

@@ -407,13 +407,19 @@ enum CdmUsageSupportType {
enum CdmUsageEntryStorageType {
kStorageLicense,
kStorageUsageInfo,
kStorageUnknown,
kStorageTypeUnknown,
};
struct CdmUsageEntryInfo {
CdmUsageEntryStorageType storage_type;
CdmKeySetId key_set_id;
std::string usage_info_file_name;
bool operator==(const CdmUsageEntryInfo& other) const {
return storage_type == other.storage_type &&
key_set_id == other.key_set_id &&
(storage_type != kStorageUsageInfo ||
usage_info_file_name == other.usage_info_file_name);
}
};
class CdmKeyAllowedUsage {

View File

@@ -409,7 +409,12 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
CdmResponseType sts = session->AddKey(key_data);
if (key_set_id) {
*key_set_id = session->key_set_id();
if ((session->is_offline() ||
session->has_provider_session_token()) && !license_type_release) {
*key_set_id = session->key_set_id();
} else {
key_set_id->clear();
}
}
switch (sts) {
@@ -681,6 +686,28 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
std::ostringstream api_version_stream;
api_version_stream << api_version;
*query_response = api_version_stream.str();
} else if (query_token == QUERY_KEY_CURRENT_SRM_VERSION) {
uint16_t current_srm_version;
if (!crypto_session.GetSrmVersion(&current_srm_version)) {
LOGW("CdmEngine::QueryStatus: GetCurrentSRMVersion failed");
return UNKNOWN_ERROR;
}
std::ostringstream current_srm_version_stream;
current_srm_version_stream << current_srm_version;
*query_response = current_srm_version_stream.str();
} else if (query_token == QUERY_KEY_SRM_UPDATE_SUPPORT) {
bool is_srm_update_supported = crypto_session.IsSrmUpdateSupported();
*query_response =
is_srm_update_supported ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
} else if (query_token == QUERY_KEY_WVCDM_VERSION) {
std::string cdm_version;
if (!Properties::GetWVCdmVersion(&cdm_version)) {
LOGW("CdmEngine::QueryStatus: GetWVCdmVersion failed");
return UNKNOWN_ERROR;
}
*query_response = cdm_version;
} else {
LOGW("CdmEngine::QueryStatus: Unknown status requested, token = %s",
query_token.c_str());
@@ -1261,42 +1288,47 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
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;
switch (usage_session_->get_usage_support_type()) {
case 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].usage_entry_number);
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;
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
status = RELEASE_ALL_USAGE_INFO_ERROR_5;
}
break;
}
case kUsageTableSupport: {
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete %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;
}
break;
}
default:
// Ignore
break;
}
} else {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to initialize L%d device"
@@ -1611,25 +1643,25 @@ 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
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;
switch ((*iter)->get_usage_support_type()) {
case kUsageEntrySupport:
(*iter)->UpdateUsageEntryInformation();
break;
case kUsageTableSupport:
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)->UpdateUsageTableInformation();
if (NO_ERROR != status) {
LOGW("Update usage information failed: %d", status);
} else {
has_usage_been_updated = true;
}
}
}
break;
default:
// Ignore
break;
}
}
}

View File

@@ -45,15 +45,6 @@ CdmSession::CdmSession(FileSystem* file_system) :
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();
}
@@ -106,6 +97,13 @@ CdmResponseType CdmSession::Init(
return SESSION_FILE_HANDLE_INIT_ERROR;
}
if (crypto_session_->GetUsageSupportType(&usage_support_type_) == NO_ERROR) {
if (usage_support_type_ == kUsageEntrySupport)
usage_table_header_ = crypto_session_->GetUsageTableHeader();
} else {
usage_support_type_ = kNonSecureUsageSupport;
}
// Device Provisioning state is not yet known.
// If not using certificates, then Keybox is client token for license
// requests.
@@ -195,6 +193,9 @@ CdmResponseType CdmSession::Init(
CdmResponseType CdmSession::RestoreOfflineSession(
const CdmKeySetId& key_set_id, const CdmLicenseType license_type) {
if (!key_set_id_.empty()) {
file_handle_->UnreserveLicenseId(key_set_id_);
}
key_set_id_ = key_set_id;
DeviceFiles::LicenseState license_state;
@@ -430,7 +431,8 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
!provider_session_token.empty()) {
if (sts != KEY_ADDED) {
CdmResponseType sts =
usage_table_header_->DeleteEntry(usage_entry_number_);
usage_table_header_->DeleteEntry(usage_entry_number_,
file_handle_.get(), &metrics_);
if (sts != NO_ERROR) {
LOGW("CdmSession::AddKey: Delete usage entry failed = %d", sts);
}
@@ -446,7 +448,7 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
license_parser_->provider_session_token().size(),
license_parser_->provider_session_token().c_str());
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
if (is_offline_ || has_provider_session_token()) {
if (usage_support_type_ == kUsageEntrySupport)
usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_);
@@ -556,8 +558,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
}
has_decrypted_since_last_report_ = true;
if (!is_usage_update_needed_) {
is_usage_update_needed_ =
!license_parser_->provider_session_token().empty();
is_usage_update_needed_ = has_provider_session_token();
}
} else {
Clock clock;
@@ -576,7 +577,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
CdmResponseType CdmSession::GenerateRenewalRequest(
CdmKeyRequest* key_request) {
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
true, app_parameters_, &key_request->message, &key_request->url);
true, app_parameters_, NULL, &key_request->message, &key_request->url);
key_request->type = kKeyRequestTypeRenewal;
@@ -606,8 +607,8 @@ CdmResponseType CdmSession::GenerateReleaseRequest(
CdmKeyRequest* key_request) {
is_release_ = true;
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
false, app_parameters_, &key_request->message,
&key_request->url);
false, app_parameters_, usage_table_header_ == NULL ? NULL : this,
&key_request->message, &key_request->url);
key_request->type = kKeyRequestTypeRelease;
@@ -641,38 +642,53 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
license_parser_->HandleKeyUpdateResponse(false, key_response);
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RELEASE_KEY_ERROR : sts;
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
if (is_offline_ || has_provider_session_token()) {
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_);
sts = DeleteUsageEntry(usage_entry_number_);
if (NO_ERROR != sts) return sts;
}
}
return NO_ERROR;
}
CdmResponseType CdmSession::DeleteUsageEntry(
const DeviceFiles::CdmUsageData& usage_data) {
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
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);
// The usage entry cannot be deleted if it has a crypto session handling
// it, so close and reopen session.
CdmResponseType sts;
crypto_session_->Close();
crypto_session_.reset(new CryptoSession(&metrics_));
M_TIME(
sts = crypto_session_->Open(requested_security_level_),
&metrics_,
crypto_session_open_,
sts,
requested_security_level_);
if (sts != NO_ERROR) return sts;
usage_table_header_ = NULL;
if (crypto_session_->GetUsageSupportType(&usage_support_type_) == NO_ERROR) {
if (usage_support_type_ == kUsageEntrySupport)
usage_table_header_ = crypto_session_->GetUsageTableHeader();
} else {
usage_support_type_ = kNonSecureUsageSupport;
}
if (usage_table_header_ == NULL) {
LOGE("CdmSession::DeleteUsageEntry: Usage table header unavailable");
return INCORRECT_USAGE_SUPPORT_TYPE_1;
}
return usage_table_header_->DeleteEntry(usage_entry_number,
file_handle_.get(),
&metrics_);
}
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
@@ -775,7 +791,7 @@ CdmResponseType CdmSession::ReleaseCrypto() {
}
bool CdmSession::DeleteLicense() {
if (!is_offline_ && license_parser_->provider_session_token().empty())
if (!is_offline_ && !has_provider_session_token())
return false;
if (is_offline_) {

View File

@@ -17,6 +17,7 @@
#include "properties.h"
#include "pst_report.h"
#include "string_conversions.h"
#include "usage_table_header.h"
#include "wv_cdm_constants.h"
namespace {
@@ -41,6 +42,8 @@ Lock CryptoSession::crypto_lock_;
bool CryptoSession::initialized_ = false;
int CryptoSession::session_count_ = 0;
uint64_t CryptoSession::request_id_index_ = 0;
UsageTableHeader* CryptoSession::usage_table_header_l1_ = NULL;
UsageTableHeader* CryptoSession::usage_table_header_l3_ = NULL;
CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
: metrics_(metrics),
@@ -48,7 +51,9 @@ CryptoSession::CryptoSession(metrics::MetricsGroup* metrics)
update_usage_table_after_close_session_(false),
is_destination_buffer_type_valid_(false),
requested_security_level_(kLevelDefault),
usage_support_type_(kUnknownUsageSupport),
is_usage_support_type_valid_(false),
usage_support_type_(kNonSecureUsageSupport),
usage_table_header_(NULL),
request_id_base_(0),
cipher_mode_(kCipherModeCtr) {
Init();
@@ -121,6 +126,16 @@ void CryptoSession::Terminate() {
if (OEMCrypto_SUCCESS != sts) {
LOGE("OEMCrypto_Terminate failed: %d", sts);
}
if (usage_table_header_l1_ != NULL) {
delete usage_table_header_l1_;
usage_table_header_l1_ = NULL;
}
if (usage_table_header_l3_ != NULL) {
delete usage_table_header_l3_;
usage_table_header_l3_ = NULL;
}
initialized_ = false;
}
@@ -217,8 +232,7 @@ bool CryptoSession::GetProvisioningToken(std::string* token) {
}
CdmSecurityLevel CryptoSession::GetSecurityLevel() {
LOGV("CryptoSession::GetSecurityLevel: Lock");
AutoLock auto_lock(crypto_lock_);
LOGV("CryptoSession::GetSecurityLevel");
if (!initialized_) {
return kSecurityLevelUninitialized;
}
@@ -430,7 +444,8 @@ uint8_t CryptoSession::GetSecurityPatchLevel() {
}
CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
LOGV("CryptoSession::Open: Lock");
LOGV("CryptoSession::Open: Lock: requested_security_level: %d",
requested_security_level);
AutoLock auto_lock(crypto_lock_);
if (!initialized_) return UNKNOWN_ERROR;
if (open_) return NO_ERROR;
@@ -470,8 +485,35 @@ 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);
if (GetUsageSupportType(&usage_support_type) == NO_ERROR) {
if (usage_support_type == kUsageEntrySupport) {
CdmSecurityLevel security_level = GetSecurityLevel();
if (security_level == kSecurityLevelL1 ||
security_level == kSecurityLevelL3) {
UsageTableHeader* header = security_level == kSecurityLevelL1 ?
usage_table_header_l1_ : usage_table_header_l3_;
if (header == NULL) {
header = new UsageTableHeader();
// Ignore errors since we do not know when a session is opened,
// if it is intended to be used for offline/usage session related
// or otherwise.
if (!header->Init(security_level, this)) {
delete header;
usage_table_header_ = NULL;
return NO_ERROR;
}
if (security_level == kSecurityLevelL1)
usage_table_header_l1_ = header;
else
usage_table_header_l3_ = header;
}
usage_table_header_ = header;
}
}
}
return NO_ERROR;
}
@@ -1108,6 +1150,11 @@ CdmResponseType CryptoSession::UpdateUsageInformation() {
AutoLock auto_lock(crypto_lock_);
if (!initialized_) return UNKNOWN_ERROR;
if (usage_table_header_ != NULL) {
LOGV("UpdateUsageInformation: deprecated for OEMCrypto v13+");
return NO_ERROR;
}
OEMCryptoResult status;
M_TIME(
status = OEMCrypto_UpdateUsageTable(),
@@ -1264,6 +1311,11 @@ CdmResponseType CryptoSession::ReleaseUsageInformation(
LOGV("ReleaseUsageInformation: id=%ld", (uint32_t)oec_session_id_);
{
AutoLock auto_lock(crypto_lock_);
if (usage_table_header_ != NULL) {
LOGW("ReleaseUsageInformation: deprecated for OEMCrypto v13+");
return NO_ERROR;
}
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);

View File

@@ -858,6 +858,11 @@ bool DeviceFiles::ListUsageInfoFiles(
return false;
}
if (usage_info_file_names == NULL) {
LOGW("DeviceFiles::ListUsageInfoFiles: usage_info_file_names not provided");
return false;
}
// Get list of filenames
std::vector<std::string> filenames;
if (!ListFiles(&filenames)) {
@@ -982,7 +987,7 @@ bool DeviceFiles::StoreUsageTableInfo(
const CdmUsageTableHeader& usage_table_header,
const std::vector<CdmUsageEntryInfo>& usage_entry_info) {
if (!initialized_) {
LOGW("DeviceFiles::StoreUsageTableHeader: not initialized");
LOGW("DeviceFiles::StoreUsageTableInfo: not initialized");
return false;
}
@@ -1009,7 +1014,7 @@ bool DeviceFiles::StoreUsageTableInfo(
info->set_usage_info_file_name(
usage_entry_info[i].usage_info_file_name);
break;
case kStorageUnknown:
case kStorageTypeUnknown:
default:
info->set_storage(
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN);
@@ -1081,7 +1086,7 @@ bool DeviceFiles::RetrieveUsageTableInfo(
break;
case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN:
default:
(*usage_entry_info)[i].storage_type = kStorageUnknown;
(*usage_entry_info)[i].storage_type = kStorageTypeUnknown;
break;
}
}

View File

@@ -7,6 +7,7 @@
#include <vector>
#include "clock.h"
#include "cdm_session.h"
#include "crypto_key.h"
#include "crypto_session.h"
#include "device_files.h"
@@ -274,7 +275,8 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
bool is_renewal, const CdmAppParameterMap& app_parameters,
CdmKeyMessage* signed_request, std::string* server_url) {
CdmSession* cdm_session, CdmKeyMessage* signed_request,
std::string* server_url) {
if (!initialized_) {
LOGE("CdmLicense::PrepareKeyUpdateRequest: not initialized");
return LICENSE_PARSER_NOT_INITIALIZED_1;
@@ -330,6 +332,12 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
if (NO_ERROR != status) return status;
}
// TODO(rfrias): Refactor to avoid needing to call CdmSession
if (cdm_session) {
CdmResponseType status = cdm_session->UpdateUsageEntryInformation();
if (NO_ERROR != status) return status;
}
std::string usage_report;
CdmResponseType status = crypto_session_->GenerateUsageReport(
provider_session_token_, &usage_report, &usage_duration_status,

View File

@@ -29,14 +29,15 @@ RSA* GetKey(const std::string& serialized_key) {
return NULL;
}
RSA* key = d2i_RSAPublicKey_bio(bio, NULL);
BIO_free(bio);
if (key == NULL) {
LOGE("GetKey: RSA key deserialization failure: %s",
ERR_error_string(ERR_get_error(), NULL));
BIO_free(bio);
return NULL;
}
BIO_free(bio);
return key;
}

View File

@@ -5,6 +5,7 @@
#include "crypto_session.h"
#include "license.h"
#include "log.h"
#include "metrics_group.h"
namespace {
std::string kEmptyString;
@@ -12,78 +13,65 @@ std::string kEmptyString;
namespace wvcdm {
UsageTableHeader* UsageTableHeader::usage_table_header_l1_ = NULL;
UsageTableHeader* UsageTableHeader::usage_table_header_l3_ = NULL;
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::GetInstance: unsupported security level: %d",
security_level);
return NULL;
}
UsageTableHeader* header =
new UsageTableHeader(file_system, crypto_session, security_level);
if (!header->is_inited()) {
delete header;
return NULL;
}
if (security_level == kSecurityLevelL1)
usage_table_header_l1_ = header;
else
usage_table_header_l3_ = header;
return header;
UsageTableHeader::UsageTableHeader()
: security_level_(kSecurityLevelUninitialized),
requested_security_level_(kLevelDefault),
is_inited_(false) {
file_handle_.reset(new DeviceFiles(file_system_.get()));
}
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);
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;
}
switch (security_level) {
case kSecurityLevelL1:
case kSecurityLevelL3:
break;
default:
LOGE("UsageTableHeader::Init: invalid security level provided: %d",
security_level);
return false;
}
security_level_ = security_level;
if (!file_handle_->Init(security_level)) {
LOGE("UsageTableHeader::Init: device files initialization failed");
return false;
}
if (!file_handle_->RetrieveUsageTableInfo(&usage_table_header_,
&usage_entry_info_)) {
CdmResponseType status =
crypto_session->CreateUsageTableHeader(&usage_table_header_);
if (status != NO_ERROR) return;
if (status != NO_ERROR) return false;
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
} else {
CdmResponseType status =
crypto_session->LoadUsageTableHeader(usage_table_header_);
if (status != NO_ERROR) {
LOGE(
"UsageTableHeader::UsageTablerHeader: load usage table failed, "
"security level: %d",
"UsageTableHeader::Init: load usage table failed, security level: %d",
security_level);
return;
return false;
}
}
requested_security_level_ =
security_level_ == kSecurityLevelL3 ? kLevel3 : kLevelDefault;
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");
LOGV("UsageTableHeader::AddEntry: Lock");
AutoLock auto_lock(usage_table_header_lock_);
CdmResponseType status = crypto_session->CreateUsageEntry(usage_entry_number);
@@ -101,7 +89,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 = kStorageUnknown;
usage_entry_info_[i].storage_type = kStorageTypeUnknown;
usage_entry_info_[i].key_set_id.clear();
usage_entry_info_[i].usage_info_file_name.clear();
}
@@ -120,15 +108,17 @@ CdmResponseType UsageTableHeader::AddEntry(
return NO_ERROR;
}
CdmResponseType UsageTableHeader::LoadEntry(
CryptoSession* crypto_session, const CdmUsageEntry& usage_entry,
uint32_t usage_entry_number) {
LOGV("UsageTableHeader::LoadEntry");
CdmResponseType UsageTableHeader::LoadEntry(CryptoSession* crypto_session,
const CdmUsageEntry& usage_entry,
uint32_t usage_entry_number) {
LOGV("UsageTableHeader::LoadEntry: Lock");
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);
@@ -136,20 +126,21 @@ CdmResponseType UsageTableHeader::LoadEntry(
CdmResponseType UsageTableHeader::UpdateEntry(CryptoSession* crypto_session,
CdmUsageEntry* usage_entry) {
LOGV("UsageTableHeader::UpdateEntry");
LOGV("UsageTableHeader::UpdateEntryL: Lock");
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) {
LOGV("UsageTableHeader::DeleteEntry");
CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number,
DeviceFiles* handle,
metrics::MetricsGroup* metrics) {
LOGV("UsageTableHeader::DeleteEntry: Lock");
AutoLock auto_lock(usage_table_header_lock_);
if (usage_entry_number >= usage_entry_info_.size())
return USAGE_INVALID_PARAMETERS_1;
@@ -159,50 +150,67 @@ CdmResponseType UsageTableHeader::DeleteEntry(uint32_t usage_entry_number) {
CdmUsageEntry swap_usage_entry;
bool swap_usage_entry_valid = false;
for (; !swap_usage_entry_valid && swap_entry_number > usage_entry_number;
--swap_entry_number) {
while (!swap_usage_entry_valid && swap_entry_number > usage_entry_number) {
switch (usage_entry_info_[swap_entry_number].storage_type) {
case kStorageLicense:
case kStorageUsageInfo: {
CdmResponseType status = GetEntry(swap_entry_number, &swap_usage_entry);
CdmResponseType status =
GetEntry(swap_entry_number, handle, &swap_usage_entry);
if (status == NO_ERROR) swap_usage_entry_valid = true;
break;
}
case kStorageUnknown:
case kStorageTypeUnknown:
default:
break;
}
if (!swap_usage_entry_valid) --swap_entry_number;
}
uint32_t new_usage_table_size = 0;
uint32_t number_of_entries_to_be_deleted =
usage_entry_info_.size() - usage_entry_number;
if (swap_usage_entry_valid) {
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;
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;
}
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;
return Shrink(metrics, number_of_entries_to_be_deleted);
}
CdmResponseType UsageTableHeader::MoveEntry(
uint32_t from_usage_entry_number, const CdmUsageEntry& from_usage_entry,
uint32_t to_usage_entry_number) {
uint32_t to_usage_entry_number, DeviceFiles* handle,
metrics::MetricsGroup* metrics) {
LOGV("UsageTableHeader::MoveEntry");
AutoLock auto_lock(usage_table_header_lock_);
CryptoSession crypto_session(&metrics_);
crypto_session.Open(GetSecurityLevel());
// 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_);
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",
@@ -210,7 +218,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",
@@ -222,7 +230,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",
@@ -232,12 +240,13 @@ CdmResponseType UsageTableHeader::MoveEntry(
file_handle_->StoreUsageTableInfo(usage_table_header_, usage_entry_info_);
StoreEntry(to_usage_entry_number, usage_entry);
StoreEntry(to_usage_entry_number, handle, 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) {
@@ -247,7 +256,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 (!file_handle_->RetrieveLicense(
if (!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,
@@ -263,7 +272,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
CdmKeyMessage license_request;
CdmKeyResponse license_response;
if (!file_handle_->RetrieveUsageInfoByKeySetId(
if (!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,
@@ -274,7 +283,7 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
}
break;
}
case kStorageUnknown:
case kStorageTypeUnknown:
default:
LOGE(
"UsageTableHeader::GetEntry: Attempting to retrieve usage "
@@ -293,6 +302,7 @@ 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) {
@@ -303,7 +313,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 (!file_handle_->RetrieveLicense(
if (!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,
@@ -312,7 +322,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
LOGE("UsageTableHeader::StoreEntry: Failed to retrieve license");
return USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED;
}
if (!file_handle_->StoreLicense(
if (!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,
@@ -327,7 +337,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 (!file_handle_->RetrieveUsageInfoByKeySetId(
if (!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,
@@ -337,10 +347,10 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
"information");
return USAGE_STORE_ENTRY_RETRIEVE_USAGE_INFO_FAILED;
}
file_handle_->DeleteUsageInfo(
handle->DeleteUsageInfo(
usage_entry_info_[usage_entry_number].usage_info_file_name,
provider_session_token);
if (!file_handle_->StoreUsageInfo(
if (!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,
@@ -350,7 +360,7 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
}
break;
}
case kStorageUnknown:
case kStorageTypeUnknown:
default:
LOGE(
"UsageTableHeader::GetUsageEntry: Attempting to retrieve usage "
@@ -361,41 +371,56 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
return NO_ERROR;
}
bool UsageTableHeader::DeleteLastEntry() {
CdmResponseType UsageTableHeader::Shrink(
metrics::MetricsGroup* metrics,
uint32_t number_of_usage_entries_to_delete) {
if (usage_entry_info_.empty()) {
LOGW(
"UsageTableHeader::DeleteLastEntry: usage entry info table "
"unexpectedly empty");
return false;
LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty");
return NO_USAGE_ENTRIES;
}
usage_entry_info_.resize(usage_entry_info_.size() - 1);
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;
}
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;
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;
}
bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
CdmResponseType UsageTableHeader::UpgradeFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
UpgradeLicensesFromUsageTable(handle, metrics);
UpgradeUsageInfoFromUsageTable(handle, metrics);
return NO_ERROR;
}
bool UsageTableHeader::UpgradeLicensesFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
// Fetch the key set IDs for each offline license. For each license
// * retrieve the provider session token,
// * create a new usage entry
@@ -403,18 +428,14 @@ 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 (file_handle_->ListLicenses(&key_set_ids)) {
LOGE(
if (handle->ListLicenses(&key_set_ids)) {
LOGW(
"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;
@@ -423,7 +444,7 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
CdmAppParameterMap app_parameters;
CdmUsageEntry usage_entry;
uint32_t usage_entry_number;
if (!file_handle_->RetrieveLicense(
if (!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,
@@ -432,7 +453,6 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
LOGW(
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to "
"retrieve license");
result = false;
continue;
}
@@ -442,37 +462,26 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
LOGW(
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to "
"retrieve provider session token");
result = false;
continue;
}
if (provider_session_token.empty()) {
result = false;
continue;
}
if (provider_session_token.empty()) continue;
CryptoSession crypto_session(&metrics_);
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
CryptoSession crypto_session(metrics);
CdmResponseType status = crypto_session.Open(requested_security_level_);
if (status != NO_ERROR) {
result = false;
continue;
}
if (status != NO_ERROR) continue;
status = AddEntry(&crypto_session, true /* persistent license */,
key_set_ids[i], kEmptyString, &usage_entry_number);
if (status != NO_ERROR) {
result = false;
continue;
}
if (status != NO_ERROR) continue;
status = crypto_session.CopyOldUsageEntry(provider_session_token);
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
result = false;
Shrink(metrics, 1);
continue;
}
@@ -480,26 +489,27 @@ bool UsageTableHeader::UpgradeLicensesFromUsageTable() {
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
result = false;
Shrink(metrics, 1);
continue;
}
if (!file_handle_->StoreLicense(
if (!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)) {
LOGW("UsageTableHeader::StoreEntry: Failed to store license");
result = false;
LOGE(
"UsageTableHeader::UpgradeLicensesFromUsageTable: Failed to store "
"license");
continue;
}
}
return result;
return NO_ERROR;
}
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
bool UsageTableHeader::UpgradeUsageInfoFromUsageTable(
DeviceFiles* handle, metrics::MetricsGroup* metrics) {
// Fetch all usage files. For each file retrieve all the usage info records
// within the file. For each piece of usage information
// * create a new usage entry
@@ -509,27 +519,21 @@ 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 (file_handle_->ListUsageInfoFiles(&usage_info_file_names)) {
LOGE(
if (handle->ListUsageInfoFiles(&usage_info_file_names)) {
LOGW(
"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 (!file_handle_->RetrieveUsageInfo(usage_info_file_names[i],
&usage_data)) {
if (!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;
}
@@ -538,17 +542,13 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
LOGW(
"UsageTableHeader::UpgradeUsageInfoFromUsageTable: Provider "
"session id empty");
result = false;
continue;
}
CryptoSession crypto_session(&metrics_);
CdmResponseType status = crypto_session.Open(GetSecurityLevel());
CryptoSession crypto_session(metrics);
CdmResponseType status = crypto_session.Open(requested_security_level_);
if (status != NO_ERROR) {
result = false;
continue;
}
if (status != NO_ERROR) 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?
@@ -556,18 +556,14 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
usage_data[j].key_set_id, kEmptyString,
&(usage_data[i].usage_entry_number));
if (status != NO_ERROR) {
result = false;
continue;
}
if (status != NO_ERROR) continue;
status = crypto_session.CopyOldUsageEntry(
usage_data[i].provider_session_token);
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
result = false;
Shrink(metrics, 1);
continue;
}
@@ -575,23 +571,21 @@ bool UsageTableHeader::UpgradeUsageInfoFromUsageTable() {
if (status != NO_ERROR) {
crypto_session.Close();
DeleteLastEntry();
result = false;
Shrink(metrics, 1);
continue;
}
}
if (!file_handle_->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
LOGW(
if (!handle->StoreUsageInfo(usage_info_file_names[i], usage_data)) {
LOGE(
"UsageTableHeader::StoreUsageInfo: Failed to store usage records to "
"%s",
usage_info_file_names[i].c_str());
result = false;
continue;
}
}
return result;
return NO_ERROR;
}
} // namespace wvcdm

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,9 @@
// Copyright 2017 Google Inc. All Rights Reserved.
#include "usage_table_header.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string>
#include "crypto_session.h"
#include "device_files.h"
#include "file_store.h"
@@ -52,58 +50,10 @@ const CdmUsageEntryInfo kUsageEntryInfoStorageTypeUnknown = {
.storage_type = kStorageTypeUnknown,
.key_set_id = "",
.usage_info_file_name = ""};
const std::vector<std::string> kEmptyLicenseList;
const std::string kLicenseArray[] = {
kUsageEntryInfoOfflineLicense1.key_set_id,
kUsageEntryInfoOfflineLicense2.key_set_id,
kUsageEntryInfoOfflineLicense3.key_set_id,
};
const size_t kLicenseArraySize = sizeof(kLicenseArray)/
sizeof(kLicenseArray[0]);
std::vector<std::string> kLicenseList;
const std::vector<std::string> kEmptyUsageInfoFilesList;
const std::string kUsageInfoFileArray[] = {
kUsageEntryInfoSecureStop1.usage_info_file_name,
kUsageEntryInfoSecureStop2.usage_info_file_name,
kUsageEntryInfoSecureStop3.usage_info_file_name,
};
const size_t kUsageInfoFileArraySize = sizeof(kUsageInfoFileArray)/
sizeof(kUsageInfoFileArray[0]);
std::vector<std::string> kUsageInfoFileList;
const DeviceFiles::CdmUsageData kCdmUsageData1 = {
.provider_session_token = "provider_session_token_1",
.license_request = "license_request_1",
.license = "license_1",
.key_set_id = "key_set_id_1",
.usage_entry = "usage_entry_1",
.usage_entry_number = 0,
};
const DeviceFiles::CdmUsageData kCdmUsageData2 = {
.provider_session_token = "provider_session_token_2",
.license_request = "license_request_2",
.license = "license_2",
.key_set_id = "key_set_id_2",
.usage_entry = "usage_entry_2",
.usage_entry_number = 0,
};
const DeviceFiles::CdmUsageData kCdmUsageData3 = {
.provider_session_token = "provider_session_token_3",
.license_request = "license_request_3",
.license = "license_3",
.key_set_id = "key_set_id_3",
.usage_entry = "usage_entry_3",
.usage_entry_number = 0,
};
const std::vector<DeviceFiles::CdmUsageData> kEmptyUsageInfoUsageDataList;
const std::vector<CdmUsageEntryInfo> kEmptyUsageEntryInfoVector;
std::vector<CdmUsageEntryInfo> kUsageEntryInfoVector;
const std::vector<CdmUsageEntryInfo> kUsageEntryInfoVector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
kUsageEntryInfoStorageTypeUnknown};
const DeviceFiles::LicenseState kActiveLicenseState =
DeviceFiles::kLicenseStateActive;
const CdmInitData kPsshData = "pssh data";
@@ -118,36 +68,6 @@ int64_t kPlaybackStartTime = 1030005;
int64_t kPlaybackDuration = 300;
int64_t kGracePeriodEndTime = 60;
namespace {
void InitVectorConstants() {
kUsageEntryInfoVector.clear();
kUsageEntryInfoVector.push_back(kUsageEntryInfoOfflineLicense1);
kUsageEntryInfoVector.push_back(kUsageEntryInfoSecureStop1);
kUsageEntryInfoVector.push_back(kUsageEntryInfoStorageTypeUnknown);
kUsageInfoFileList.clear();
for (size_t i = 0; i < kUsageInfoFileArraySize; i++) {
kUsageInfoFileList.push_back(kUsageInfoFileArray[i]);
}
kLicenseList.clear();
for (size_t i = 0; i < kLicenseArraySize; i++) {
kLicenseList.push_back(kLicenseArray[i]);
}
}
void ToVector(std::vector<CdmUsageEntryInfo>& vec,
const CdmUsageEntryInfo* arr, size_t total_size) {
size_t max = total_size / sizeof(CdmUsageEntryInfo);
vec.clear();
for (size_t i = 0; i < max; i++) {
vec.push_back(arr[i]);
}
}
}; // namespace
class MockDeviceFiles : public DeviceFiles {
public:
MockDeviceFiles() : DeviceFiles(&file_system_) { Init(kSecurityLevelL1); }
@@ -162,17 +82,12 @@ class MockDeviceFiles : public DeviceFiles {
bool(const std::string&, const std::string&, std::string*,
CdmKeyMessage*, CdmKeyResponse*, CdmUsageEntry*,
uint32_t*));
MOCK_METHOD0(DeleteAllLicenses, bool());
MOCK_METHOD7(StoreUsageInfo,
bool(const std::string&, const CdmKeyMessage&,
const CdmKeyResponse&, const std::string&,
const std::string&, const CdmUsageEntry&, uint32_t));
MOCK_METHOD2(RetrieveUsageInfo,
bool(const std::string&, std::vector<CdmUsageData>*));
MOCK_METHOD1(ListLicenses,
bool(std::vector<std::string>* key_set_ids));
MOCK_METHOD1(ListUsageInfoFiles,
bool(std::vector<std::string>* usage_info_files));
private:
FileSystem file_system_;
@@ -180,8 +95,7 @@ class MockDeviceFiles : public DeviceFiles {
class MockCryptoSession : public CryptoSession {
public:
MockCryptoSession(metrics::CryptoMetrics* metrics)
: CryptoSession(metrics) {}
MockCryptoSession() : CryptoSession(NULL) {}
MOCK_METHOD1(Open, CdmResponseType(SecurityLevel));
MOCK_METHOD1(LoadUsageTableHeader,
CdmResponseType(const CdmUsageTableHeader&));
@@ -207,16 +121,11 @@ using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
class UsageTableHeaderTest : public ::testing::Test {
public:
static void SetUpTestCase() {
InitVectorConstants();
}
protected:
virtual void SetUp() {
// UsageTableHeader will take ownership of the pointer
device_files_ = new MockDeviceFiles();
crypto_session_ = new MockCryptoSession(&crypto_metrics_);
crypto_session_ = new MockCryptoSession();
usage_table_header_ = new UsageTableHeader();
// usage_table_header_ object takes ownership of these objects
@@ -242,7 +151,6 @@ class UsageTableHeaderTest : public ::testing::Test {
}
MockDeviceFiles* device_files_;
metrics::CryptoMetrics crypto_metrics_;
MockCryptoSession* crypto_session_;
UsageTableHeader* usage_table_header_;
};
@@ -259,86 +167,21 @@ TEST_F(UsageTableHeaderTest, InitError) {
class UsageTableHeaderInitializationTest
: public UsageTableHeaderTest,
public ::testing::WithParamInterface<CdmSecurityLevel> {
public:
static void SetUpTestCase() {
InitVectorConstants();
}
};
public ::testing::WithParamInterface<CdmSecurityLevel> {};
TEST_P(UsageTableHeaderInitializationTest, CreateUsageTableHeader) {
std::vector<CdmUsageEntryInfo> empty_usage_entry_info;
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
Return(false)));
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kEmptyLicenseList),
Return(false)));
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageInfoFilesList),
Return(false)));
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
.WillOnce(
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
kEmptyUsageEntryInfoVector))
.Times(2)
.WillRepeatedly(Return(true));
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
}
TEST_P(UsageTableHeaderInitializationTest, Upgrade_UnableToRetrieveLicenses) {
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
Return(false)));
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kLicenseList),
Return(true)));
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageInfoFilesList),
Return(false)));
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
.WillOnce(
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
// TODO: Why not being called?
//EXPECT_CALL(*device_files_, DeleteAllLicenses()).WillOnce(Return(true));
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
kEmptyUsageEntryInfoVector))
.Times(2)
.WillRepeatedly(Return(true));
for (size_t i = 0; i < kLicenseList.size(); ++i)
device_files_->DeleteLicense(kLicenseList[i]);
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
}
TEST_P(UsageTableHeaderInitializationTest, Upgrade_UnableToRetrieveUsageInfo) {
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
Return(false)));
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kEmptyLicenseList),
Return(false)));
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kUsageInfoFileList),
Return(true)));
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
.WillOnce(
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
kEmptyUsageEntryInfoVector))
.Times(2)
.WillRepeatedly(Return(true));
for (size_t i = 0; i < kUsageInfoFileList.size(); ++i) {
EXPECT_CALL(*device_files_,
RetrieveUsageInfo(kUsageInfoFileList[i], NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(kEmptyUsageInfoUsageDataList),
Return(false)));
}
.WillOnce(Return(true));
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
}
@@ -552,7 +395,7 @@ TEST_F(UsageTableHeaderTest, UpdateEntry) {
TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) {
Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector);
uint32_t usage_entry_number = kUsageEntryInfoVector.size();
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_NE(NO_ERROR, usage_table_header_->DeleteEntry(
usage_entry_number, device_files_, &metrics));
@@ -576,17 +419,14 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) {
//
// # of usage entries 4 4
TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -615,17 +455,14 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_CryptoSessionError) {
//
// # of usage entries 4 3
TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense2
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -663,17 +500,14 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) {
//
// # of usage entries 4 3
TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoSecureStop2};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop2
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -716,19 +550,17 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) {
// # of usage entries 5 2
TEST_F(UsageTableHeaderTest,
DeleteEntry_LastOfflineEntriesHaveMissingLicenses) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
kUsageEntryInfoOfflineLicense3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
device_files_->DeleteAllLicenses();
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
*crypto_session_,
@@ -768,18 +600,15 @@ TEST_F(UsageTableHeaderTest,
//
// # of usage entries 5 2
TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
kUsageEntryInfoSecureStop3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -834,18 +663,15 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntriesAreMissing) {
// # of usage entries 5 2
TEST_F(UsageTableHeaderTest,
DeleteEntry_LastOfflineEntriesHaveIncorrectUsageEntryNumber) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
kUsageEntryInfoOfflineLicense3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[usage_entry_info_vector.size() - 1].key_set_id,
@@ -903,20 +729,17 @@ TEST_F(UsageTableHeaderTest,
// # of usage entries 5 2
TEST_F(UsageTableHeaderTest,
DeleteEntry_LastSecureStopEntriesHaveIncorrectUsageEntryNumber) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
kUsageEntryInfoSecureStop3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
uint32_t usage_entry_number_after_deleted_entry =
usage_entry_number_to_be_deleted + 1;
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -981,18 +804,15 @@ TEST_F(UsageTableHeaderTest,
//
// # of usage entries 7 4
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoOfflineLicense2, kUsageEntryInfoOfflineLicense3,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(
@@ -1037,20 +857,17 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreStorageTypeUnknown) {
// # of usage entries 5 5
TEST_F(UsageTableHeaderTest,
DeleteEntry_LastEntryIsOffline_MoveOfflineEntryFailed) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
kUsageEntryInfoOfflineLicense3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_usage_entry_number].key_set_id,
@@ -1106,20 +923,17 @@ TEST_F(UsageTableHeaderTest,
// # of usage entries 5 5
TEST_F(UsageTableHeaderTest,
DeleteEntry_LastEntryIsSecureStop_MoveSecureStopEntryFailed) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
kUsageEntryInfoSecureStop3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_,
@@ -1182,21 +996,18 @@ TEST_F(UsageTableHeaderTest,
// # of usage entries 7 5
TEST_F(UsageTableHeaderTest,
DeleteEntry_LastEntriesAreOfflineAndUnknown_MoveOfflineEntryFailed) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
kUsageEntryInfoOfflineLicense3, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
@@ -1263,21 +1074,18 @@ TEST_F(UsageTableHeaderTest,
// # of usage entries 7 5
TEST_F(UsageTableHeaderTest,
DeleteEntry_LastEntriesAreSecureStopAndUnknown_MoveOfflineEntryFailed) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
kUsageEntryInfoSecureStop3, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.Times(2)
@@ -1339,20 +1147,17 @@ TEST_F(UsageTableHeaderTest,
//
// # of usage entries 5 4
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
kUsageEntryInfoOfflineLicense3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoOfflineLicense3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_usage_entry_number].key_set_id,
@@ -1456,20 +1261,17 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsOffline) {
//
// # of usage entries 5 4
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
kUsageEntryInfoSecureStop3};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop1
uint32_t last_usage_entry_number =
usage_entry_info_vector.size() - 1; // kUsageEntryInfoSecureStop3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.Times(2)
@@ -1558,21 +1360,18 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntryIsSecureStop) {
//
// # of usage entries 7 4
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoOfflineLicense2,
kUsageEntryInfoOfflineLicense3, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 5; // kUsageEntryInfoOfflineLicense1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoOfflineLicense3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_TRUE(device_files_->StoreLicense(
usage_entry_info_vector[last_valid_usage_entry_number].key_set_id,
@@ -1680,21 +1479,18 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreOfflineAndUnknknown) {
//
// # of usage entries 7 4
TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
kUsageEntryInfoSecureStop3, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
uint32_t usage_entry_number_to_be_deleted =
usage_entry_info_vector.size() - 5; // kUsageEntryInfoSecureStop1
uint32_t last_valid_usage_entry_number =
usage_entry_info_vector.size() - 3; // kUsageEntryInfoSecureStop3
metrics::CryptoMetrics metrics;
metrics::MetricsGroup metrics;
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.Times(2)
@@ -1762,30 +1558,4 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastEntriesAreSecureStopAndUnknknown) {
device_files_, &metrics));
}
// If the crypto session says the usage table header is stale, init should fail.
TEST_F(UsageTableHeaderTest, StaleHeader) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense2};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
EXPECT_CALL(*device_files_, RetrieveUsageTableInfo(NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader),
SetArgPointee<1>(usage_entry_info_vector),
Return(true)));
EXPECT_CALL(*crypto_session_, LoadUsageTableHeader(kUsageTableHeader))
.WillOnce(Return(LOAD_USAGE_HEADER_GENERATION_SKEW));
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
.WillOnce(
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
EXPECT_CALL(*device_files_, DeleteAllLicenses()).WillOnce(Return(true));
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
kEmptyUsageEntryInfoVector))
.WillOnce(Return(true));
EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_));
}
} // namespace wvcdm