Add Entitlement License to OEMCrypto
This CL adds entitlement license features and moves cipher mode from LoadKeys to SelectKeys. Merge from Widevine repo of http://go/wvgerrit/41660 bug: 70334840 Entitlement License - cdm layer bug: 70334345 Entitlement License - reference code and unit tests test: Entitlement license unit tests pass. Change-Id: Ic7d7f42c15e6d83ef7fcfd8a866c778adc4c8095
This commit is contained in:
@@ -43,7 +43,8 @@ class KeySession {
|
||||
const std::string& provider_session_token,
|
||||
CdmCipherMode* cipher_mode,
|
||||
const std::string& srm_requirement) = 0;
|
||||
virtual OEMCryptoResult SelectKey(const std::string& key_id) = 0;
|
||||
virtual OEMCryptoResult SelectKey(const std::string& key_id,
|
||||
CdmCipherMode cipher_mode) = 0;
|
||||
virtual OEMCryptoResult Decrypt(
|
||||
const CdmDecryptionParameters& params,
|
||||
OEMCrypto_DestBufferDesc& buffer_descriptor,
|
||||
@@ -241,7 +242,8 @@ class CryptoSession {
|
||||
const std::string& private_key, const std::string& iv,
|
||||
const std::string& wrapping_key, std::string* wrapped_private_key);
|
||||
|
||||
CdmResponseType SelectKey(const std::string& key_id);
|
||||
CdmResponseType SelectKey(const std::string& key_id,
|
||||
CdmCipherMode cipher_mode);
|
||||
|
||||
static const OEMCrypto_Algorithm kInvalidAlgorithm =
|
||||
static_cast<OEMCrypto_Algorithm>(-1);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -69,15 +69,15 @@ class Key {
|
||||
public:
|
||||
Key(const Key& key)
|
||||
: value_(key.value_), control_(key.control_), ctr_mode_(key.ctr_mode_) {}
|
||||
Key(const std::vector<uint8_t>& key_string, const KeyControlBlock& control,
|
||||
bool ctr_mode)
|
||||
: value_(key_string), control_(control), ctr_mode_(ctr_mode){};
|
||||
Key(const std::vector<uint8_t>& key_string, const KeyControlBlock& control)
|
||||
: value_(key_string), control_(control), ctr_mode_(true){};
|
||||
|
||||
virtual ~Key(){};
|
||||
void UpdateDuration(const KeyControlBlock& control);
|
||||
const std::vector<uint8_t>& value() const { return value_; }
|
||||
virtual const std::vector<uint8_t>& value() const { return value_; }
|
||||
const KeyControlBlock& control() const { return control_; }
|
||||
bool ctr_mode() const { return ctr_mode_; }
|
||||
void set_ctr_mode(bool ctr_mode) { ctr_mode_ = ctr_mode; }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> value_;
|
||||
@@ -85,6 +85,28 @@ class Key {
|
||||
bool ctr_mode_;
|
||||
};
|
||||
|
||||
// AES-256 entitlement key. |Key| holds the entitlement key. |EntitlementKey|
|
||||
// holds the content key.
|
||||
class EntitlementKey : public Key {
|
||||
public:
|
||||
EntitlementKey(const Key& key) : Key(key) {}
|
||||
virtual ~EntitlementKey() {}
|
||||
virtual const std::vector<uint8_t>& value() const { return content_key_; }
|
||||
const std::vector<uint8_t>& content_key() { return content_key_; }
|
||||
const std::vector<uint8_t>& content_key_id() { return content_key_id_; }
|
||||
const std::vector<uint8_t>& entitlement_key() { return Key::value(); }
|
||||
bool SetContentKey(const std::vector<uint8_t>& content_key,
|
||||
const std::vector<uint8_t>& content_key_id) {
|
||||
content_key_.assign(content_key.begin(), content_key.end());
|
||||
content_key_id_.assign(content_key_id.begin(), content_key_id.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> content_key_;
|
||||
std::vector<uint8_t> content_key_id_;
|
||||
};
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif // OEMCRYPTO_KEY_MOCK_H_
|
||||
|
||||
@@ -31,7 +31,7 @@ const uint8_t kBakedInCertificateMagicBytes[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
|
||||
// Return uint32 referenced through a potentially unaligned pointer.
|
||||
// If the pointer is NULL, return 0.
|
||||
uint32_t unaligned_dereference_uint32(const uint32_t* unaligned_ptr) {
|
||||
uint32_t unaligned_dereference_uint32(const void* unaligned_ptr) {
|
||||
if (unaligned_ptr == NULL) return 0;
|
||||
uint32_t value;
|
||||
const uint8_t* src = reinterpret_cast<const uint8_t*>(unaligned_ptr);
|
||||
@@ -299,7 +299,7 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_keys, size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array, const uint8_t* pst, size_t pst_length,
|
||||
const uint8_t* srm_requirement) {
|
||||
const uint8_t* srm_requirement, OEMCrypto_LicenseType license_type) {
|
||||
if (!crypto_engine) {
|
||||
LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
@@ -326,9 +326,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE);
|
||||
dump_array_part("key_array", i, "key_control", key_array[i].key_control,
|
||||
wvcdm::KEY_IV_SIZE);
|
||||
LOGV("key_array[%zu].cipher_mode=%s;\n", i,
|
||||
key_array[i].cipher_mode == OEMCrypto_CipherMode_CTR ? "CTR"
|
||||
: "CBC");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -389,7 +386,32 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
return session_ctx->LoadKeys(message, message_length, signature,
|
||||
signature_length, enc_mac_key_iv, enc_mac_keys,
|
||||
num_keys, key_array, pst, pst_length,
|
||||
srm_requirement);
|
||||
srm_requirement, license_type);
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
|
||||
OEMCrypto_SESSION session,
|
||||
size_t num_keys,
|
||||
const OEMCrypto_EntitledContentKeyObject* key_array) {
|
||||
if (num_keys == 0) {
|
||||
LOGE("[OEMCrypto_LoadEntitledContentKeys(): key_array is empty.");
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
if (!key_array) {
|
||||
LOGE("[OEMCrypto_LoadEntitledContentKeys(): missing key_array.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!crypto_engine) {
|
||||
LOGE("OEMCrypto_LoadEntitledContentKeys: OEMCrypto Not Initialized.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (!session_ctx || !session_ctx->isValid()) {
|
||||
LOGE("[OEMCrypto_LoadEntitledContentKeys(): ERROR_INVALID_SESSION]");
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
|
||||
return session_ctx->LoadEntitledContentKeys(num_keys, key_array);
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||
@@ -521,9 +543,9 @@ extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl(
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session,
|
||||
const uint8_t* key_id,
|
||||
size_t key_id_length) {
|
||||
extern "C" OEMCryptoResult OEMCrypto_SelectKey(
|
||||
const OEMCrypto_SESSION session, const uint8_t* key_id,
|
||||
size_t key_id_length, OEMCryptoCipherMode cipher_mode) {
|
||||
if (LogCategoryEnabled(kLoggingTraceDecryptCalls)) {
|
||||
LOGI("-- OEMCryptoResult OEMCrypto_SelectKey(%d, id=%s)", session,
|
||||
wvcdm::HexEncode(key_id, key_id_length).c_str());
|
||||
@@ -543,7 +565,7 @@ extern "C" OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session,
|
||||
|
||||
const std::vector<uint8_t> key_id_str =
|
||||
std::vector<uint8_t>(key_id, key_id + key_id_length);
|
||||
return session_ctx->SelectContentKey(key_id_str);
|
||||
return session_ctx->SelectContentKey(key_id_str, cipher_mode);
|
||||
}
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_DecryptCENC(
|
||||
|
||||
@@ -56,11 +56,124 @@ void dump_boringssl_error() {
|
||||
|
||||
namespace wvoec_mock {
|
||||
|
||||
/***************************************/
|
||||
|
||||
class ContentKeysContext : public SessionContextKeys {
|
||||
public:
|
||||
explicit ContentKeysContext() {}
|
||||
virtual ~ContentKeysContext() {}
|
||||
virtual size_t size() { return session_keys_.size(); }
|
||||
bool Insert(const KeyId& key_id, const Key& key_data);
|
||||
virtual Key* Find(const KeyId& key_id);
|
||||
virtual void Remove(const KeyId& key_id);
|
||||
virtual void UpdateDuration(const KeyControlBlock& control);
|
||||
|
||||
virtual OEMCrypto_LicenseType type() { return OEMCrypto_ContentLicense; }
|
||||
|
||||
virtual bool SetContentKey(const KeyId& entitlement_id,
|
||||
const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key);
|
||||
virtual bool GetEntitlementKey(
|
||||
const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key);
|
||||
|
||||
private:
|
||||
SessionKeyTable session_keys_;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(ContentKeysContext);
|
||||
};
|
||||
|
||||
bool ContentKeysContext::Insert(const KeyId& key_id, const Key& key_data) {
|
||||
return session_keys_.Insert(key_id, key_data);
|
||||
}
|
||||
|
||||
Key* ContentKeysContext::Find(const KeyId& key_id) {
|
||||
return session_keys_.Find(key_id);
|
||||
}
|
||||
|
||||
void ContentKeysContext::Remove(const KeyId& key_id) {
|
||||
session_keys_.Remove(key_id);
|
||||
}
|
||||
|
||||
void ContentKeysContext::UpdateDuration(const KeyControlBlock& control) {
|
||||
session_keys_.UpdateDuration(control);
|
||||
}
|
||||
|
||||
bool ContentKeysContext::SetContentKey(
|
||||
const KeyId& entitlement_id, const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key) {
|
||||
// Unsupported action for this type.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ContentKeysContext::GetEntitlementKey(
|
||||
const KeyId& entitlement_id, const std::vector<uint8_t>** key) {
|
||||
// Unsupported action for this type.
|
||||
return false;
|
||||
};
|
||||
|
||||
/***************************************/
|
||||
|
||||
class EntitlementKeysContext : public SessionContextKeys {
|
||||
public:
|
||||
EntitlementKeysContext() {}
|
||||
virtual ~EntitlementKeysContext() {}
|
||||
virtual size_t size() { return session_keys_.size(); }
|
||||
bool Insert(const KeyId& key_id, const Key& key_data);
|
||||
virtual Key* Find(const KeyId& key_id);
|
||||
virtual void Remove(const KeyId& key_id);
|
||||
virtual void UpdateDuration(const KeyControlBlock& control);
|
||||
virtual bool SetContentKey(const KeyId& entitlement_id,
|
||||
const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key);
|
||||
virtual bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** key);
|
||||
|
||||
virtual OEMCrypto_LicenseType type() { return OEMCrypto_EntitlementLicense; }
|
||||
|
||||
private:
|
||||
EntitlementKeyTable session_keys_;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(EntitlementKeysContext);
|
||||
};
|
||||
|
||||
bool EntitlementKeysContext::Insert(const KeyId& key_id, const Key& key_data) {
|
||||
return session_keys_.Insert(key_id, key_data);
|
||||
}
|
||||
|
||||
Key* EntitlementKeysContext::Find(const KeyId& key_id) {
|
||||
return session_keys_.Find(key_id);
|
||||
}
|
||||
|
||||
void EntitlementKeysContext::Remove(const KeyId& key_id) {
|
||||
session_keys_.Remove(key_id);
|
||||
}
|
||||
|
||||
void EntitlementKeysContext::UpdateDuration(const KeyControlBlock& control) {
|
||||
session_keys_.UpdateDuration(control);
|
||||
}
|
||||
|
||||
bool EntitlementKeysContext::SetContentKey(
|
||||
const KeyId& entitlement_id, const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key) {
|
||||
return session_keys_.SetContentKey(entitlement_id, content_key_id,
|
||||
content_key);
|
||||
}
|
||||
|
||||
bool EntitlementKeysContext::GetEntitlementKey(
|
||||
const KeyId& entitlement_id, const std::vector<uint8_t>** out_key) {
|
||||
return session_keys_.GetEntitlementKey(entitlement_id, out_key);
|
||||
}
|
||||
|
||||
/***************************************/
|
||||
|
||||
SessionContext::~SessionContext() {
|
||||
if (usage_entry_) {
|
||||
delete usage_entry_;
|
||||
usage_entry_ = NULL;
|
||||
}
|
||||
if (session_keys_) {
|
||||
delete session_keys_;
|
||||
session_keys_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal utility function to derive key using CMAC-128
|
||||
@@ -398,7 +511,7 @@ OEMCryptoResult SessionContext::CheckNonceOrEntry(
|
||||
return CheckStatusOnline(key_control_block.nonce(),
|
||||
key_control_block.control_bits());
|
||||
break;
|
||||
case kControlNonceOrEntry: // Offline license. Nonce required on first use.
|
||||
case kControlNonceOrEntry: // Offline license. Nonce required on first use.
|
||||
return CheckStatusOffline(key_control_block.nonce(),
|
||||
key_control_block.control_bits());
|
||||
break;
|
||||
@@ -423,13 +536,32 @@ OEMCryptoResult SessionContext::LoadKeys(
|
||||
const uint8_t* message, size_t message_length, const uint8_t* signature,
|
||||
size_t signature_length, const uint8_t* enc_mac_key_iv,
|
||||
const uint8_t* enc_mac_keys, size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array, const uint8_t* pst,
|
||||
size_t pst_length, const uint8_t* srm_requirement) {
|
||||
const OEMCrypto_KeyObject* key_array, const uint8_t* pst, size_t pst_length,
|
||||
const uint8_t* srm_requirement, OEMCrypto_LicenseType license_type) {
|
||||
// Validate message signature
|
||||
if (!ValidateMessage(message, message_length, signature, signature_length)) {
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
}
|
||||
|
||||
if (!session_keys_) {
|
||||
switch (license_type) {
|
||||
case OEMCrypto_ContentLicense:
|
||||
session_keys_ = new ContentKeysContext();
|
||||
break;
|
||||
|
||||
case OEMCrypto_EntitlementLicense:
|
||||
session_keys_ = new EntitlementKeysContext();
|
||||
break;
|
||||
|
||||
default:
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
} else {
|
||||
if (session_keys_->type() != license_type) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
StartTimer();
|
||||
|
||||
if (srm_requirement) {
|
||||
@@ -454,15 +586,15 @@ OEMCryptoResult SessionContext::LoadKeys(
|
||||
LOGW("[LoadKeys: SRM blacklisted device attached]");
|
||||
srm_requirements_status_ = InvalidSRMVersion;
|
||||
} else {
|
||||
LOGI("[LoadKeys: SRM Versions is %d, required: %d]",
|
||||
current_version, minimum_version);
|
||||
LOGI("[LoadKeys: SRM Versions is %d, required: %d]", current_version,
|
||||
minimum_version);
|
||||
srm_requirements_status_ = ValidSRMVersion;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are already keys installed in this session, then we can load
|
||||
// a shared license.
|
||||
bool second_license = (session_keys_.size() > 0);
|
||||
bool second_license = (session_keys_->size() > 0);
|
||||
|
||||
// Decrypt and install keys in key object
|
||||
// Each key will have a key control block. They will all have the same nonce.
|
||||
@@ -490,7 +622,7 @@ OEMCryptoResult SessionContext::LoadKeys(
|
||||
|
||||
OEMCryptoResult result = InstallKey(
|
||||
key_id, enc_key_data, key_data_iv, key_control, key_control_iv,
|
||||
key_array[i].cipher_mode == OEMCrypto_CipherMode_CTR, second_license);
|
||||
second_license);
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
status = result;
|
||||
break;
|
||||
@@ -550,11 +682,57 @@ OEMCryptoResult SessionContext::LoadKeys(
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
||||
size_t num_keys,
|
||||
const OEMCrypto_EntitledContentKeyObject* key_array) {
|
||||
if (!key_array) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!session_keys_ || session_keys_->type() != OEMCrypto_EntitlementLicense) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
for (size_t i = 0; i < num_keys; ++i) {
|
||||
const OEMCrypto_EntitledContentKeyObject* key_data = &key_array[i];
|
||||
std::vector<uint8_t> entitlement_key_id;
|
||||
entitlement_key_id.assign(key_data->entitlement_key_id,
|
||||
key_data->entitlement_key_id +
|
||||
key_data->entitlement_key_id_length);
|
||||
|
||||
const std::vector<uint8_t>* entitlement_key = NULL;
|
||||
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
|
||||
&entitlement_key)) {
|
||||
return OEMCrypto_KEY_NOT_ENTITLED;
|
||||
}
|
||||
std::vector<uint8_t> content_key;
|
||||
std::vector<uint8_t> iv;
|
||||
std::vector<uint8_t> encrypted_content_key;
|
||||
std::vector<uint8_t> content_key_id;
|
||||
|
||||
iv.assign(key_data->content_key_data_iv,
|
||||
key_data->content_key_data_iv + 16);
|
||||
encrypted_content_key.assign(
|
||||
key_data->content_key_data,
|
||||
key_data->content_key_data + key_data->content_key_data_length);
|
||||
content_key_id.assign(
|
||||
key_data->content_key_id,
|
||||
key_data->content_key_id + key_data->content_key_id_length);
|
||||
if (!DecryptEntitlement(*entitlement_key, iv,
|
||||
encrypted_content_key, &content_key)) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!session_keys_->SetContentKey(
|
||||
entitlement_key_id, content_key_id, content_key)) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::InstallKey(
|
||||
const KeyId& key_id, const std::vector<uint8_t>& key_data,
|
||||
const std::vector<uint8_t>& key_data_iv,
|
||||
const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv, bool ctr_mode,
|
||||
const std::vector<uint8_t>& key_control_iv,
|
||||
bool second_license) {
|
||||
// Decrypt encrypted key_data using derived encryption key and offered iv
|
||||
std::vector<uint8_t> content_key;
|
||||
@@ -566,12 +744,11 @@ OEMCryptoResult SessionContext::InstallKey(
|
||||
}
|
||||
|
||||
if (LogCategoryEnabled(kLoggingDumpContentKeys)) {
|
||||
LOGI((" InstallKey: key_id = " +
|
||||
wvcdm::b2a_hex(key_id)).c_str());
|
||||
LOGI((" InstallKey: content_key = " +
|
||||
wvcdm::b2a_hex(content_key)).c_str());
|
||||
LOGI((" InstallKey: key_control = " +
|
||||
wvcdm::b2a_hex(key_control_str)).c_str());
|
||||
LOGI((" InstallKey: key_id = " + wvcdm::b2a_hex(key_id)).c_str());
|
||||
LOGI(
|
||||
(" InstallKey: content_key = " + wvcdm::b2a_hex(content_key)).c_str());
|
||||
LOGI((" InstallKey: key_control = " + wvcdm::b2a_hex(key_control_str))
|
||||
.c_str());
|
||||
}
|
||||
|
||||
// Key control must be supplied by license server
|
||||
@@ -633,8 +810,11 @@ OEMCryptoResult SessionContext::InstallKey(
|
||||
}
|
||||
}
|
||||
|
||||
Key key(content_key, key_control_block, ctr_mode);
|
||||
session_keys_.Insert(key_id, key);
|
||||
Key key(content_key, key_control_block);
|
||||
if (!session_keys_) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
session_keys_->Insert(key_id, key);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -663,6 +843,9 @@ bool SessionContext::InstallRSAEncryptedKey(
|
||||
OEMCryptoResult SessionContext::RefreshKey(
|
||||
const KeyId& key_id, const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv) {
|
||||
if (!session_keys_) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (key_id.empty()) {
|
||||
// Key control is not encrypted if key id is NULL
|
||||
KeyControlBlock key_control_block(key_control);
|
||||
@@ -676,11 +859,11 @@ OEMCryptoResult SessionContext::RefreshKey(
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
// Apply duration to all keys in this session
|
||||
session_keys_.UpdateDuration(key_control_block);
|
||||
session_keys_->UpdateDuration(key_control_block);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
Key* content_key = session_keys_.Find(key_id);
|
||||
Key* content_key = session_keys_->Find(key_id);
|
||||
|
||||
if (NULL == content_key) {
|
||||
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
|
||||
@@ -1014,7 +1197,10 @@ bool SessionContext::UpdateMacKeys(const std::vector<uint8_t>& enc_mac_keys,
|
||||
}
|
||||
|
||||
bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) {
|
||||
const Key* content_key = session_keys_.Find(key_id);
|
||||
if (!session_keys_) {
|
||||
return false;
|
||||
}
|
||||
const Key* content_key = session_keys_->Find(key_id);
|
||||
if (LogCategoryEnabled(kLoggingTraceDecryption)) {
|
||||
LOGI(("Select Key: key_id = " + wvcdm::b2a_hex(key_id)).c_str());
|
||||
if (content_key) {
|
||||
@@ -1035,25 +1221,34 @@ bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::SelectContentKey(const KeyId& key_id) {
|
||||
const Key* content_key = session_keys_.Find(key_id);
|
||||
|
||||
OEMCryptoResult SessionContext::SelectContentKey(
|
||||
const KeyId& key_id, OEMCryptoCipherMode cipher_mode) {
|
||||
if (LogCategoryEnabled(kLoggingTraceDecryption)) {
|
||||
LOGI((" Select Key: key_id = " + wvcdm::b2a_hex(key_id)).c_str());
|
||||
LOGI((" Select Key: key = " + wvcdm::b2a_hex(content_key->value()))
|
||||
.c_str());
|
||||
LOGI(" Select Key: key_id = %s", wvcdm::b2a_hex(key_id).c_str());
|
||||
LOGI(" Select Key: cipher_mode = %s",
|
||||
(cipher_mode == OEMCrypto_CipherMode_CTR) ? "CTR" : "CBC");
|
||||
}
|
||||
|
||||
if (!session_keys_) {
|
||||
LOGE("Select Key: no session keys.");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
Key* content_key = session_keys_->Find(key_id);
|
||||
if (NULL == content_key) {
|
||||
LOGE("[SelectContentKey(): No key matches key id]");
|
||||
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||
}
|
||||
if (LogCategoryEnabled(kLoggingTraceDecryption)) {
|
||||
LOGI((" Select Key: key = " + wvcdm::b2a_hex(content_key->value()))
|
||||
.c_str());
|
||||
}
|
||||
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
|
||||
current_content_key_ = content_key;
|
||||
const KeyControlBlock& control = current_content_key()->control();
|
||||
|
||||
if (control.duration() > 0) {
|
||||
if (control.duration() < CurrentTimer()) {
|
||||
LOGE("[SelectContentKey(): KEY_EXPIRED %d versus %d]",
|
||||
control.duration(), CurrentTimer());
|
||||
LOGE("[SelectContentKey(): KEY_EXPIRED %d versus %d]", control.duration(),
|
||||
CurrentTimer());
|
||||
return OEMCrypto_ERROR_KEY_EXPIRED;
|
||||
}
|
||||
}
|
||||
@@ -1131,7 +1326,6 @@ OEMCryptoResult SessionContext::CopyOldUsageEntry(
|
||||
return usage_entry_->CopyOldUsageEntry(pst);
|
||||
}
|
||||
|
||||
|
||||
// Internal utility function to decrypt the message
|
||||
bool SessionContext::DecryptMessage(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv,
|
||||
@@ -1151,6 +1345,25 @@ bool SessionContext::DecryptMessage(const std::vector<uint8_t>& key,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionContext::DecryptEntitlement(
|
||||
const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv,
|
||||
const std::vector<uint8_t>& message,
|
||||
std::vector<uint8_t>* decrypted) {
|
||||
if (key.empty() || iv.empty() || message.empty() || !decrypted) {
|
||||
LOGE("[DecryptMessage(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||
return false;
|
||||
}
|
||||
decrypted->resize(message.size());
|
||||
uint8_t iv_buffer[16];
|
||||
memcpy(iv_buffer, &iv[0], 16);
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(&key[0], 256, &aes_key);
|
||||
AES_cbc_encrypt(&message[0], &(decrypted->front()), message.size(), &aes_key,
|
||||
iv_buffer, AES_DECRYPT);
|
||||
return true;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::DecryptCENC(
|
||||
const uint8_t* iv, size_t block_offset,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
||||
|
||||
@@ -30,6 +30,34 @@ typedef uint32_t SessionId;
|
||||
|
||||
enum SRMVersionStatus { NoSRMVersion, ValidSRMVersion, InvalidSRMVersion };
|
||||
|
||||
// TODO(jfore): Is there a better name?
|
||||
class SessionContextKeys {
|
||||
public:
|
||||
virtual OEMCrypto_LicenseType type() = 0;
|
||||
virtual size_t size() = 0;
|
||||
virtual bool Insert(const KeyId& key_id, const Key& key_data) = 0;
|
||||
virtual Key* Find(const KeyId& key_id) = 0;
|
||||
virtual void Remove(const KeyId& key_id) = 0;
|
||||
virtual void UpdateDuration(const KeyControlBlock& control) = 0;
|
||||
|
||||
// Methods supported exclusively for entitlement keys. Returns false if
|
||||
// entitlement keys are not found or not supported by the current key table.
|
||||
// It is the caller's responsibility to check the context.
|
||||
virtual bool SetContentKey(const KeyId& entitlement_id,
|
||||
const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key) = 0;
|
||||
virtual bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** key) = 0;
|
||||
|
||||
virtual ~SessionContextKeys() {}
|
||||
|
||||
protected:
|
||||
SessionContextKeys() {}
|
||||
|
||||
private:
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContextKeys);
|
||||
};
|
||||
|
||||
class SessionContext {
|
||||
private:
|
||||
SessionContext() {}
|
||||
@@ -40,6 +68,7 @@ class SessionContext {
|
||||
ce_(ce),
|
||||
id_(sid),
|
||||
current_content_key_(NULL),
|
||||
session_keys_(NULL),
|
||||
rsa_key_(rsa_key),
|
||||
allowed_schemes_(kSign_RSASSA_PSS),
|
||||
usage_entry_(NULL),
|
||||
@@ -89,19 +118,22 @@ class SessionContext {
|
||||
size_t signature_length);
|
||||
void StartTimer();
|
||||
uint32_t CurrentTimer(); // (seconds).
|
||||
OEMCryptoResult LoadKeys(const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
const uint8_t* enc_mac_key_iv,
|
||||
const uint8_t* enc_mac_keys, size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array,
|
||||
const uint8_t* pst, size_t pst_length,
|
||||
const uint8_t* srm_requirement);
|
||||
OEMCryptoResult LoadKeys(
|
||||
const uint8_t* message, size_t message_length, const uint8_t* signature,
|
||||
size_t signature_length, const uint8_t* enc_mac_key_iv,
|
||||
const uint8_t* enc_mac_keys, size_t num_keys,
|
||||
const OEMCrypto_KeyObject* key_array, const uint8_t* pst,
|
||||
size_t pst_length, const uint8_t* srm_requirement,
|
||||
OEMCrypto_LicenseType license_type);
|
||||
OEMCryptoResult LoadEntitledContentKeys(
|
||||
size_t num_keys,
|
||||
const OEMCrypto_EntitledContentKeyObject* key_array);
|
||||
OEMCryptoResult InstallKey(const KeyId& key_id,
|
||||
const std::vector<uint8_t>& key_data,
|
||||
const std::vector<uint8_t>& key_data_iv,
|
||||
const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv,
|
||||
bool ctr_mode, bool second_license);
|
||||
bool second_license);
|
||||
bool InstallRSAEncryptedKey(const uint8_t* encrypted_message_key,
|
||||
size_t encrypted_message_key_length);
|
||||
bool DecryptRSAKey(const uint8_t* enc_rsa_key, size_t enc_rsa_key_length,
|
||||
@@ -115,7 +147,8 @@ class SessionContext {
|
||||
bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys,
|
||||
const std::vector<uint8_t>& iv);
|
||||
bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
|
||||
OEMCryptoResult SelectContentKey(const KeyId& key_id);
|
||||
OEMCryptoResult SelectContentKey(const KeyId& key_id,
|
||||
OEMCryptoCipherMode cipher_mode);
|
||||
const Key* current_content_key(void) { return current_content_key_; }
|
||||
void set_mac_key_server(const std::vector<uint8_t>& mac_key_server) {
|
||||
mac_key_server_ = mac_key_server;
|
||||
@@ -157,6 +190,10 @@ class SessionContext {
|
||||
const std::vector<uint8_t>& iv,
|
||||
const std::vector<uint8_t>& message,
|
||||
std::vector<uint8_t>* decrypted);
|
||||
bool DecryptEntitlement(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv,
|
||||
const std::vector<uint8_t>& message,
|
||||
std::vector<uint8_t>* decrypted);
|
||||
// Either verify the nonce or usage entry, as required by the key control
|
||||
// block.
|
||||
OEMCryptoResult CheckNonceOrEntry(const KeyControlBlock& key_control_block);
|
||||
@@ -193,7 +230,7 @@ class SessionContext {
|
||||
std::vector<uint8_t> encryption_key_;
|
||||
std::vector<uint8_t> session_key_;
|
||||
const Key* current_content_key_;
|
||||
SessionKeyTable session_keys_;
|
||||
SessionContextKeys* session_keys_;
|
||||
NonceTable nonce_table_;
|
||||
RSA_shared_ptr rsa_key_;
|
||||
uint32_t allowed_schemes_; // for RSA signatures.
|
||||
|
||||
@@ -43,4 +43,75 @@ void SessionKeyTable::UpdateDuration(const KeyControlBlock& control) {
|
||||
}
|
||||
}
|
||||
|
||||
bool EntitlementKeyTable::Insert(const KeyId key_id, const Key& key_data) {
|
||||
// |key_id| and |key_data| are for an entitlement key. Insert a new
|
||||
// entitlement key entry.
|
||||
if (keys_.find(key_id) != keys_.end()) return false;
|
||||
keys_[key_id] = new EntitlementKey(key_data);
|
||||
// If this is a new insertion, we don't have a content key assigned yet.
|
||||
return true;
|
||||
}
|
||||
|
||||
Key* EntitlementKeyTable::Find(const KeyId key_id) {
|
||||
// |key_id| refers to a content key.
|
||||
ContentIdToEntitlementIdMap::iterator it =
|
||||
contentid_to_entitlementid_.find(key_id);
|
||||
if (it == contentid_to_entitlementid_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (keys_.find(it->second) == keys_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return keys_[it->second];
|
||||
}
|
||||
|
||||
void EntitlementKeyTable::Remove(const KeyId key_id) {
|
||||
// |key_id| refers to a content key. No one currently calls Remove so this
|
||||
// method is free to change if needed.
|
||||
ContentIdToEntitlementIdMap::iterator it =
|
||||
contentid_to_entitlementid_.find(key_id);
|
||||
if (it == contentid_to_entitlementid_.end()) {
|
||||
return;
|
||||
}
|
||||
keys_.erase(it->second);
|
||||
contentid_to_entitlementid_.erase(key_id);
|
||||
}
|
||||
|
||||
void EntitlementKeyTable::UpdateDuration(const KeyControlBlock& control) {
|
||||
for (EntitlementKeyMap::iterator it = keys_.begin(); it != keys_.end();
|
||||
++it) {
|
||||
it->second->UpdateDuration(control);
|
||||
}
|
||||
}
|
||||
|
||||
bool EntitlementKeyTable::SetContentKey(
|
||||
const KeyId& entitlement_id, const KeyId& content_key_id,
|
||||
const std::vector<uint8_t> content_key) {
|
||||
EntitlementKeyMap::iterator it = keys_.find(entitlement_id);
|
||||
if (it == keys_.end()) {
|
||||
return false;
|
||||
}
|
||||
contentid_to_entitlementid_.erase(it->second->content_key_id());
|
||||
if (!it->second->SetContentKey(content_key_id, content_key)) {
|
||||
return false;
|
||||
}
|
||||
contentid_to_entitlementid_[content_key_id] = entitlement_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntitlementKeyTable::GetEntitlementKey(
|
||||
const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key) {
|
||||
if (!entitlement_key) {
|
||||
return false;
|
||||
}
|
||||
EntitlementKeyMap::iterator it = keys_.find(entitlement_id);
|
||||
if (it == keys_.end()) {
|
||||
return false;
|
||||
}
|
||||
*entitlement_key = &it->second->entitlement_key();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -19,8 +19,9 @@ class CryptoEngine;
|
||||
class UsageTable;
|
||||
class UsageTableEntry;
|
||||
|
||||
typedef std::vector<uint8_t> KeyId;
|
||||
typedef std::vector<uint8_t> KeyId;
|
||||
typedef std::map<KeyId, Key*> KeyMap;
|
||||
typedef std::map<KeyId, EntitlementKey*> EntitlementKeyMap;
|
||||
|
||||
// SessionKeyTable holds the keys for the current session
|
||||
class SessionKeyTable {
|
||||
@@ -40,6 +41,28 @@ class SessionKeyTable {
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionKeyTable);
|
||||
};
|
||||
|
||||
class EntitlementKeyTable {
|
||||
typedef std::map<KeyId, KeyId> ContentIdToEntitlementIdMap;
|
||||
|
||||
public:
|
||||
EntitlementKeyTable() {}
|
||||
~EntitlementKeyTable() {}
|
||||
bool Insert(const KeyId key_id, const Key& key_data);
|
||||
Key* Find(const KeyId key_id);
|
||||
void Remove(const KeyId key_id);
|
||||
void UpdateDuration(const KeyControlBlock& control);
|
||||
size_t size() const { return contentid_to_entitlementid_.size(); }
|
||||
bool SetContentKey(const KeyId& entitlement_id, const KeyId& content_key_id,
|
||||
const std::vector<uint8_t> content_key);
|
||||
bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key);
|
||||
|
||||
private:
|
||||
EntitlementKeyMap keys_;
|
||||
ContentIdToEntitlementIdMap contentid_to_entitlementid_;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(EntitlementKeyTable);
|
||||
};
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif // MOCK_OEMCRYPTO_SESSION_KEY_TABLE_H_
|
||||
|
||||
@@ -227,7 +227,8 @@ void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
||||
&signature_[0], signature_.size(),
|
||||
encrypted_license().mac_key_iv,
|
||||
encrypted_license().mac_keys, num_keys_,
|
||||
key_array_, pst_ptr, pst.length(), NULL));
|
||||
key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
// Update new generated keys.
|
||||
memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE);
|
||||
memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE,
|
||||
@@ -237,11 +238,113 @@ void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||
&signature_[0], signature_.size(), NULL, NULL,
|
||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL));
|
||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
VerifyTestKeys();
|
||||
}
|
||||
|
||||
void Session::LoadEnitlementTestKeys(const std::string& pst,
|
||||
bool new_mac_keys,
|
||||
OEMCryptoResult expected_sts) {
|
||||
uint8_t* pst_ptr = NULL;
|
||||
if (pst.length() > 0) {
|
||||
pst_ptr = encrypted_license().pst;
|
||||
}
|
||||
if (new_mac_keys) {
|
||||
ASSERT_EQ(expected_sts,
|
||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||
&signature_[0], signature_.size(),
|
||||
encrypted_license().mac_key_iv,
|
||||
encrypted_license().mac_keys, num_keys_,
|
||||
key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_EntitlementLicense));
|
||||
// Update new generated keys.
|
||||
memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE);
|
||||
memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE,
|
||||
wvcdm::MAC_KEY_SIZE);
|
||||
} else {
|
||||
ASSERT_EQ(
|
||||
expected_sts,
|
||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||
&signature_[0], signature_.size(), NULL, NULL,
|
||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_EntitlementLicense));
|
||||
}
|
||||
}
|
||||
|
||||
void Session::FillEntitledKeyArray() {
|
||||
for (size_t i = 0; i < num_keys_; ++i) {
|
||||
EntitledContentKeyData* key_data = &entitled_key_data_[i];
|
||||
|
||||
entitled_key_array_[i].entitlement_key_id = key_array_[i].key_id;
|
||||
entitled_key_array_[i].entitlement_key_id_length =
|
||||
key_array_[i].key_id_length;
|
||||
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(key_data->content_key_id,
|
||||
sizeof(key_data->content_key_id)));
|
||||
entitled_key_array_[i].content_key_id = key_data->content_key_id;
|
||||
entitled_key_array_[i].content_key_id_length =
|
||||
sizeof(key_data->content_key_id);
|
||||
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(key_data->content_key_data,
|
||||
sizeof(key_data->content_key_data)));
|
||||
entitled_key_array_[i].content_key_data = key_data->content_key_data;
|
||||
entitled_key_array_[i].content_key_data_length =
|
||||
sizeof(key_data->content_key_data);
|
||||
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(entitled_key_data_[i].content_key_data_iv,
|
||||
sizeof(entitled_key_data_[i].content_key_data_iv)));
|
||||
entitled_key_array_[i].content_key_data_iv = key_data->content_key_data_iv;
|
||||
}
|
||||
}
|
||||
|
||||
void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) {
|
||||
// Create a copy of the stored |entitled_key_array_|.
|
||||
std::vector<OEMCrypto_EntitledContentKeyObject> encrypted_entitled_key_array;
|
||||
encrypted_entitled_key_array.resize(num_keys_);
|
||||
memcpy(&encrypted_entitled_key_array[0], &entitled_key_array_[0],
|
||||
sizeof(OEMCrypto_EntitledContentKeyObject) * num_keys_);
|
||||
|
||||
// Create a encrypted version of all of the content keys stored in
|
||||
// |entitled_key_array_|.
|
||||
std::vector<std::vector<uint8_t> > encrypted_content_keys;
|
||||
encrypted_content_keys.resize(num_keys_);
|
||||
|
||||
for (size_t i = 0; i < num_keys_; ++i) {
|
||||
// Load the entitlement key from |key_array_|.
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&key_array_[i].key_data[0], 256, &aes_key);
|
||||
encrypted_content_keys[i].resize(
|
||||
encrypted_entitled_key_array[i].content_key_data_length);
|
||||
|
||||
// Encrypt the content key with the entitlement key.
|
||||
uint8_t iv[16];
|
||||
memcpy(&iv[0], &encrypted_entitled_key_array[i].content_key_data[0], 16);
|
||||
AES_cbc_encrypt(
|
||||
&entitled_key_array_[i].content_key_data[0],
|
||||
const_cast<uint8_t*>(
|
||||
&encrypted_entitled_key_array[i].content_key_data[0]),
|
||||
encrypted_entitled_key_array[i].content_key_data_length,
|
||||
&aes_key, iv, AES_ENCRYPT);
|
||||
|
||||
// Set the |encrypted_entitled_key_array| to point to the encrypted copy
|
||||
// of the content key.
|
||||
encrypted_entitled_key_array[i].content_key_data =
|
||||
encrypted_content_keys[i].data();
|
||||
}
|
||||
ASSERT_EQ(expected_sts,
|
||||
OEMCrypto_LoadEntitledContentKeys(
|
||||
session_id(), num_keys_, &encrypted_entitled_key_array[0]));
|
||||
if (expected_sts != OEMCrypto_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
VerifyEntitlementTestKeys();
|
||||
}
|
||||
|
||||
void Session::VerifyTestKeys() {
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
KeyControlBlock block;
|
||||
@@ -264,6 +367,29 @@ void Session::VerifyTestKeys() {
|
||||
}
|
||||
}
|
||||
|
||||
void Session::VerifyEntitlementTestKeys() {
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
KeyControlBlock block;
|
||||
size_t size = sizeof(block);
|
||||
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
|
||||
session_id(), entitled_key_array_[i].content_key_id,
|
||||
entitled_key_array_[i].content_key_id_length,
|
||||
reinterpret_cast<uint8_t*>(&block), &size);
|
||||
if (sts != OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_EQ(sizeof(block), size);
|
||||
// control duration and bits stored in network byte order. For printing
|
||||
// we change to host byte order.
|
||||
ASSERT_EQ((htonl_fnc(license_.keys[i].control.duration)),
|
||||
(htonl_fnc(block.duration)))
|
||||
<< "For key " << i;
|
||||
ASSERT_EQ(htonl_fnc(license_.keys[i].control.control_bits),
|
||||
htonl_fnc(block.control_bits))
|
||||
<< "For key " << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::RefreshTestKeys(const size_t key_count, uint32_t control_bits,
|
||||
uint32_t nonce, OEMCryptoResult expected_result) {
|
||||
// Note: we store the message in encrypted_license_, but the refresh key
|
||||
@@ -319,7 +445,57 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
|
||||
sizeof(license_.keys[i].key_iv)));
|
||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
||||
sizeof(license_.keys[i].control_iv)));
|
||||
if (global_features.api_version == 13) {
|
||||
if (global_features.api_version == 14) {
|
||||
// For version 14, we require OEMCrypto to handle kc14 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc14", 4);
|
||||
} else if (global_features.api_version == 13) {
|
||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc13", 4);
|
||||
} else if (global_features.api_version == 12) {
|
||||
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc12", 4);
|
||||
} else if (control & wvoec_mock::kControlSecurityPatchLevelMask) {
|
||||
// For versions before 12, we require the special key control block only
|
||||
// when there are newer features present.
|
||||
memcpy(license_.keys[i].control.verification, "kc11", 4);
|
||||
} else if (control & wvoec_mock::kControlRequireAntiRollbackHardware) {
|
||||
memcpy(license_.keys[i].control.verification, "kc10", 4);
|
||||
} else if (control & (wvoec_mock::kControlHDCPVersionMask |
|
||||
wvoec_mock::kControlReplayMask)) {
|
||||
memcpy(license_.keys[i].control.verification, "kc09", 4);
|
||||
} else {
|
||||
memcpy(license_.keys[i].control.verification, "kctl", 4);
|
||||
}
|
||||
license_.keys[i].control.duration = htonl(duration);
|
||||
license_.keys[i].control.nonce = htonl(nonce);
|
||||
license_.keys[i].control.control_bits = htonl(control);
|
||||
license_.keys[i].cipher_mode = OEMCrypto_CipherMode_CTR;
|
||||
}
|
||||
memcpy(license_.pst, pst.c_str(), min(sizeof(license_.pst), pst.length()));
|
||||
pst_ = pst;
|
||||
}
|
||||
|
||||
void Session::FillSimpleEntitlementMessage(
|
||||
uint32_t duration, uint32_t control, uint32_t nonce,
|
||||
const std::string& pst) {
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(license_.mac_key_iv, sizeof(license_.mac_key_iv)));
|
||||
EXPECT_EQ(1, GetRandBytes(license_.mac_keys, sizeof(license_.mac_keys)));
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
memset(license_.keys[i].key_id, 0, kTestKeyIdMaxLength);
|
||||
license_.keys[i].key_id_length = kDefaultKeyIdLength;
|
||||
memset(license_.keys[i].key_id, i, license_.keys[i].key_id_length);
|
||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].key_data,
|
||||
sizeof(license_.keys[i].key_data)));
|
||||
license_.keys[i].key_data_length = wvcdm::KEY_SIZE * 2; // AES-256 keys
|
||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].key_iv,
|
||||
sizeof(license_.keys[i].key_iv)));
|
||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
||||
sizeof(license_.keys[i].control_iv)));
|
||||
if (global_features.api_version == 14) {
|
||||
// For version 13, we require OEMCrypto to handle kc14 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc14", 4);
|
||||
} else if (global_features.api_version == 13) {
|
||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc13", 4);
|
||||
} else if (global_features.api_version == 12) {
|
||||
@@ -464,7 +640,6 @@ void Session::FillKeyArray(const MessageData& data,
|
||||
key_array[i].key_control_iv = data.keys[i].control_iv;
|
||||
key_array[i].key_control =
|
||||
reinterpret_cast<const uint8_t*>(&data.keys[i].control);
|
||||
key_array[i].cipher_mode = data.keys[i].cipher_mode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,7 +689,8 @@ void Session::TestDecryptCTR(bool select_key_first,
|
||||
if (select_key_first) {
|
||||
// Select the key (from FillSimpleMessage)
|
||||
sts = OEMCrypto_SelectKey(session_id(), license_.keys[key_index].key_id,
|
||||
license_.keys[key_index].key_id_length);
|
||||
license_.keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -578,7 +754,8 @@ void Session::TestSelectExpired(unsigned int key_index) {
|
||||
if (global_features.api_version >= 13) {
|
||||
OEMCryptoResult status =
|
||||
OEMCrypto_SelectKey(session_id(), license().keys[key_index].key_id,
|
||||
license().keys[key_index].key_id_length);
|
||||
license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
// It is OK for SelectKey to succeed with an expired key, but if there is
|
||||
// an error, it must be OEMCrypto_ERROR_KEY_EXIRED.
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
|
||||
@@ -103,6 +103,13 @@ struct Test_PST_Report {
|
||||
std::string pst;
|
||||
};
|
||||
|
||||
struct EntitledContentKeyData {
|
||||
uint8_t entitlement_key_id[wvcdm::KEY_SIZE];
|
||||
uint8_t content_key_id[wvcdm::KEY_SIZE];
|
||||
uint8_t content_key_data_iv[wvcdm::KEY_SIZE];
|
||||
uint8_t content_key_data[wvcdm::KEY_SIZE];
|
||||
};
|
||||
|
||||
// Increment counter for AES-CTR. The CENC spec specifies we increment only
|
||||
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This
|
||||
// is different from the OpenSSL implementation, so we implement the CTR loop
|
||||
@@ -151,9 +158,27 @@ class Session {
|
||||
// by FillSimpleMessage, modified if needed, and then encrypted and signed by
|
||||
// the server's mac key in EncryptAndSign.
|
||||
void LoadTestKeys(const std::string& pst = "", bool new_mac_keys = true);
|
||||
// Loads the entitlement keys in the message pointed to by message_ptr()
|
||||
// using OEMCrypto_LoadKeys. This message should have already been created
|
||||
// by FillSimpleEntitlementMessage, modified if needed, and then encrypted
|
||||
// and signed by the server's mac key in EncryptAndSign.
|
||||
void LoadEnitlementTestKeys(const std::string& pst = "",
|
||||
bool new_mac_keys = true,
|
||||
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
|
||||
// Fills an OEMCrypto_EntitledContentKeyObject using the information from
|
||||
// the license_ and randomly generated content keys. This method should be
|
||||
// called after LoadEnitlementTestKeys.
|
||||
void FillEntitledKeyArray();
|
||||
// Encrypts and loads the entitled content keys via
|
||||
// OEMCrypto_LoadEntitledContentKeys.
|
||||
void LoadEntitledContentKeys(
|
||||
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
|
||||
// This uses OEMCrypto_QueryKeyControl to check that the keys in OEMCrypto
|
||||
// have the correct key control data.
|
||||
void VerifyTestKeys();
|
||||
// This uses OEMCrypto_QueryKeyControl to check that the keys in OEMCrypto
|
||||
// have the correct key control data.
|
||||
void VerifyEntitlementTestKeys();
|
||||
// This creates a refresh key or license renewal message, signs it with the
|
||||
// server's mac key, and calls OEMCrypto_RefreshKeys.
|
||||
void RefreshTestKeys(const size_t key_count, uint32_t control_bits,
|
||||
@@ -166,6 +191,12 @@ class Session {
|
||||
// before being loaded in LoadTestKeys.
|
||||
void FillSimpleMessage(uint32_t duration, uint32_t control, uint32_t nonce,
|
||||
const std::string& pst = "");
|
||||
// This fills the data structure license_ with entitlement key information.
|
||||
// This data can be modified, and then should be encrypted and signed in
|
||||
// EncryptAndSign before being loaded in LoadEnitlementTestKeys.
|
||||
void FillSimpleEntitlementMessage(
|
||||
uint32_t duration, uint32_t control,
|
||||
uint32_t nonce, const std::string& pst = "");
|
||||
// Like FillSimpleMessage, this fills encrypted_license_ with data. The name
|
||||
// is a little misleading: the license renewal message is not encrypted, it
|
||||
// is just signed. The signature is computed in RefreshTestKeys, above.
|
||||
@@ -360,6 +391,12 @@ class Session {
|
||||
vector<uint8_t> encrypted_usage_entry_;
|
||||
uint32_t usage_entry_number_;
|
||||
string pst_;
|
||||
|
||||
// Clear Entitlement key data. This is the backing data for
|
||||
// |entitled_key_array_|.
|
||||
EntitledContentKeyData entitled_key_data_[kMaxNumKeys];
|
||||
// Entitled key object. Pointers are backed by |entitled_key_data_|.
|
||||
OEMCrypto_EntitledContentKeyObject entitled_key_array_[kMaxNumKeys];
|
||||
};
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -835,6 +835,29 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithNoMAC) {
|
||||
ASSERT_EQ(expected_signature, signature);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, LoadEntitlementKeys) {
|
||||
Session s;
|
||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||
ASSERT_NO_FATAL_FAILURE(s.FillSimpleEntitlementMessage(0, 0, 0));
|
||||
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
||||
ASSERT_NO_FATAL_FAILURE(s.LoadEnitlementTestKeys());
|
||||
s.FillEntitledKeyArray();
|
||||
ASSERT_NO_FATAL_FAILURE(s.LoadEntitledContentKeys());
|
||||
s.FillEntitledKeyArray();
|
||||
ASSERT_NO_FATAL_FAILURE(s.LoadEntitledContentKeys());
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, LoadEntitlementKeysNoEntitlementKeys) {
|
||||
Session s;
|
||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||
ASSERT_NO_FATAL_FAILURE(s.FillSimpleEntitlementMessage(0, 0, 0));
|
||||
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
||||
s.FillEntitledKeyArray();
|
||||
s.LoadEntitledContentKeys(OEMCrypto_ERROR_INVALID_CONTEXT);
|
||||
}
|
||||
|
||||
// This tests GenerateSignature with an 8k licnese request.
|
||||
TEST_F(OEMCryptoSessionTests, ClientSignatureLargeBuffer) {
|
||||
Session s;
|
||||
@@ -894,7 +917,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange1) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
&mac_keys[0], // Not pointing into buffer.
|
||||
s.num_keys(), s.key_array(), NULL, 0, NULL);
|
||||
s.num_keys(), s.key_array(), NULL, 0, NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -913,7 +936,8 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange2) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
&mac_key_iv[0], // bad.
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), NULL, 0, NULL);
|
||||
s.key_array(), NULL, 0, NULL,
|
||||
OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -932,7 +956,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange3) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -952,7 +976,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange4) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -970,7 +994,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange5) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -990,7 +1014,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange6) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -1010,7 +1034,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange7) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -1026,7 +1050,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadNonce) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
@@ -1052,7 +1076,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithRepeatNonce) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
@@ -1068,7 +1092,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadVerification) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
@@ -1104,7 +1128,7 @@ TEST_P(SessionTestAlternateVerification, LoadKeys) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
// If this is a future API, then LoadKeys should fail.
|
||||
if (global_features.api_version < target_api_) {
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
@@ -1132,7 +1156,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeysBadSignature) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -1146,7 +1170,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeysWithNoDerivedKeys) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -1163,7 +1187,8 @@ TEST_F(OEMCryptoSessionTests, LoadKeyNoKeys) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(),
|
||||
&s.signature()[0], s.signature().size(), NULL, NULL,
|
||||
kNoKeys, s.key_array(), NULL, 0, NULL));
|
||||
kNoKeys, s.key_array(), NULL, 0, NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, LoadKeyNoKeyWithNonce) {
|
||||
@@ -1178,7 +1203,8 @@ TEST_F(OEMCryptoSessionTests, LoadKeyNoKeyWithNonce) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(),
|
||||
&s.signature()[0], s.signature().size(), NULL, NULL,
|
||||
kNoKeys, s.key_array(), NULL, 0, NULL));
|
||||
kNoKeys, s.key_array(), NULL, 0, NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, QueryKeyControl) {
|
||||
@@ -1219,7 +1245,7 @@ TEST_F(OEMCryptoSessionTests, AntiRollbackHardwareRequired) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
if (OEMCrypto_IsAntiRollbackHwPresent()) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
} else {
|
||||
@@ -1243,7 +1269,8 @@ TEST_F(OEMCryptoSessionTests, CheckMinimumPatchLevel) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), NULL, 0, NULL));
|
||||
s.key_array(), NULL, 0, NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
if (patch_level < 0x3F) {
|
||||
Session s;
|
||||
@@ -1259,7 +1286,8 @@ TEST_F(OEMCryptoSessionTests, CheckMinimumPatchLevel) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), NULL, 0, NULL));
|
||||
s.key_array(), NULL, 0, NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
if (patch_level > 0) {
|
||||
Session s;
|
||||
@@ -1275,7 +1303,8 @@ TEST_F(OEMCryptoSessionTests, CheckMinimumPatchLevel) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), NULL, 0, NULL));
|
||||
s.key_array(), NULL, 0, NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1687,7 +1716,8 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
||||
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
|
||||
sts = OEMCrypto_SelectKey(s.session_id(), s.license().keys[0].key_id,
|
||||
s.license().keys[0].key_id_length);
|
||||
s.license().keys[0].key_id_length,
|
||||
cipher_mode_);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
|
||||
// We decrypt each subsample.
|
||||
@@ -2016,7 +2046,7 @@ INSTANTIATE_TEST_CASE_P(CTRTests, OEMCryptoSessionTestsPartialBlockTests,
|
||||
|
||||
// Decrypt in place for CBC tests was only required in v13.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
CBCTestsAPI13, OEMCryptoSessionTestsPartialBlockTests,
|
||||
CBCTestsAPI14, OEMCryptoSessionTestsPartialBlockTests,
|
||||
Combine(
|
||||
Values(MakePattern(0, 0),
|
||||
MakePattern(3, 7),
|
||||
@@ -2039,7 +2069,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
|
||||
// Decrypt in place for CBC tests was only required in v13.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
CBCTestsAPI13, OEMCryptoSessionTestsDecryptTests,
|
||||
CBCTestsAPI14, OEMCryptoSessionTestsDecryptTests,
|
||||
Combine(
|
||||
Values(MakePattern(0, 0),
|
||||
MakePattern(3, 7),
|
||||
@@ -3783,7 +3813,8 @@ class GenericCryptoTest : public OEMCryptoSessionTests {
|
||||
EncryptBuffer(key_index, clear_buffer_, &expected_encrypted);
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
vector<uint8_t> encrypted(buffer_length);
|
||||
sts =
|
||||
@@ -3801,7 +3832,8 @@ class GenericCryptoTest : public OEMCryptoSessionTests {
|
||||
EncryptBuffer(key_index, clear_buffer_, &encrypted);
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
vector<uint8_t> resultant(encrypted.size());
|
||||
sts =
|
||||
@@ -3818,7 +3850,8 @@ class GenericCryptoTest : public OEMCryptoSessionTests {
|
||||
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
size_t signature_length = (size_t)SHA256_DIGEST_LENGTH;
|
||||
vector<uint8_t> signature(SHA256_DIGEST_LENGTH);
|
||||
@@ -3840,7 +3873,8 @@ class GenericCryptoTest : public OEMCryptoSessionTests {
|
||||
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
sts = OEMCrypto_Generic_Verify(session_.session_id(), &clear_buffer_[0],
|
||||
clear_buffer_.size(), algorithm,
|
||||
@@ -3867,7 +3901,8 @@ TEST_F(GenericCryptoTest, GenericKeyEncrypt) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
vector<uint8_t> encrypted(clear_buffer_.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Encrypt(
|
||||
@@ -3895,7 +3930,8 @@ TEST_F(GenericCryptoTest, GenericKeyEncryptSameBufferAPI12) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
// Input and output are same buffer:
|
||||
vector<uint8_t> buffer = clear_buffer_;
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
@@ -3914,7 +3950,8 @@ TEST_F(GenericCryptoTest, GenericKeyDecrypt) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
vector<uint8_t> resultant(encrypted.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Decrypt(
|
||||
@@ -3932,7 +3969,8 @@ TEST_F(GenericCryptoTest, GenericKeyDecryptSameBufferAPI12) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
vector<uint8_t> buffer = encrypted;
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Decrypt(
|
||||
@@ -3952,7 +3990,8 @@ TEST_F(GenericCryptoTest, GenericSecureToClear) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
vector<uint8_t> resultant(encrypted.size());
|
||||
ASSERT_NE(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Decrypt(
|
||||
@@ -3981,7 +4020,8 @@ TEST_F(GenericCryptoTest, GenericKeySign) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
size_t gen_signature_length = 0;
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
OEMCrypto_Generic_Sign(session_.session_id(), &clear_buffer_[0],
|
||||
@@ -4014,7 +4054,8 @@ TEST_F(GenericCryptoTest, GenericKeyVerify) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Verify(
|
||||
session_.session_id(), &clear_buffer_[0], clear_buffer_.size(),
|
||||
@@ -4042,7 +4083,8 @@ TEST_F(GenericCryptoTest, GenericKeyEncryptLargeBuffer) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
vector<uint8_t> encrypted(clear_buffer_.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Encrypt(
|
||||
@@ -4062,7 +4104,8 @@ TEST_F(GenericCryptoTest, GenericKeyDecryptLargeBuffer) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
vector<uint8_t> resultant(encrypted.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Decrypt(
|
||||
@@ -4082,7 +4125,8 @@ TEST_F(GenericCryptoTest, GenericKeySignLargeBuffer) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
size_t gen_signature_length = 0;
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
OEMCrypto_Generic_Sign(session_.session_id(), &clear_buffer_[0],
|
||||
@@ -4108,7 +4152,8 @@ TEST_F(GenericCryptoTest, GenericKeyVerifyLargeBuffer) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Verify(
|
||||
session_.session_id(), &clear_buffer_[0], clear_buffer_.size(),
|
||||
@@ -4128,7 +4173,8 @@ TEST_F(GenericCryptoTest, KeyDurationEncrypt) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Encrypt(
|
||||
session_.session_id(), &clear_buffer_[0], clear_buffer_.size(),
|
||||
@@ -4157,7 +4203,8 @@ TEST_F(GenericCryptoTest, KeyDurationDecrypt) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
|
||||
sleep(kShortSleep); // Should still be valid key.
|
||||
|
||||
@@ -4193,7 +4240,8 @@ TEST_F(GenericCryptoTest, KeyDurationSign) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
|
||||
sleep(kShortSleep); // Should still be valid key.
|
||||
|
||||
@@ -4226,7 +4274,8 @@ TEST_F(GenericCryptoTest, KeyDurationVerify) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
|
||||
sleep(kShortSleep); // Should still be valid key.
|
||||
|
||||
@@ -4292,7 +4341,8 @@ class GenericCryptoKeyIdLengthTest : public GenericCryptoTest {
|
||||
ASSERT_EQ(
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(session_.session_id(), key_id_buffer.data(),
|
||||
session_.license().keys[key_index].key_id_length));
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR));
|
||||
vector<uint8_t> resultant(encrypted.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_Generic_Decrypt(
|
||||
@@ -4500,7 +4550,8 @@ TEST_F(UsageTableTest, RepeatOnlineLicense) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), pst_ptr, pst.length(), NULL));
|
||||
s.key_array(), pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
ASSERT_NO_FATAL_FAILURE(s2.close());
|
||||
}
|
||||
|
||||
@@ -4518,7 +4569,7 @@ TEST_F(UsageTableTest, OnlineEmptyPST) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_NO_FATAL_FAILURE(s.close());
|
||||
}
|
||||
@@ -4538,7 +4589,7 @@ TEST_F(UsageTableTest, OnlineMissingEntry) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(),
|
||||
s.encrypted_license().pst, pst.length(), NULL);
|
||||
s.encrypted_license().pst, pst.length(), NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_NO_FATAL_FAILURE(s.close());
|
||||
}
|
||||
@@ -4617,7 +4668,8 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoEncrypt) {
|
||||
EncryptBuffer(key_index, clear_buffer_, &expected_encrypted);
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
vector<uint8_t> encrypted(clear_buffer_.size());
|
||||
sts = OEMCrypto_Generic_Encrypt(
|
||||
@@ -4653,7 +4705,8 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoDecrypt) {
|
||||
EncryptBuffer(key_index, clear_buffer_, &encrypted);
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
vector<uint8_t> resultant(encrypted.size());
|
||||
sts = OEMCrypto_Generic_Decrypt(
|
||||
@@ -4692,7 +4745,8 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoSign) {
|
||||
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
size_t gen_signature_length = 0;
|
||||
sts = OEMCrypto_Generic_Sign(session_.session_id(), &clear_buffer_[0],
|
||||
@@ -4738,7 +4792,8 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoVerify) {
|
||||
|
||||
sts = OEMCrypto_SelectKey(session_.session_id(),
|
||||
session_.license().keys[key_index].key_id,
|
||||
session_.license().keys[key_index].key_id_length);
|
||||
session_.license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
sts = OEMCrypto_Generic_Verify(session_.session_id(), &clear_buffer_[0],
|
||||
clear_buffer_.size(), OEMCrypto_HMAC_SHA256,
|
||||
@@ -4885,7 +4940,8 @@ TEST_P(UsageTableTestWithMAC, BadReloadOfflineLicense) {
|
||||
&s2.signature()[0], s2.signature().size(),
|
||||
s2.encrypted_license().mac_key_iv,
|
||||
s2.encrypted_license().mac_keys, s.num_keys(),
|
||||
s2.key_array(), pst_ptr, pst.length(), NULL));
|
||||
s2.key_array(), pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
ASSERT_NO_FATAL_FAILURE(s2.close());
|
||||
|
||||
// Offline license with same mac keys should still be OK.
|
||||
@@ -4912,7 +4968,7 @@ TEST_P(UsageTableTestWithMAC, OfflineBadNonce) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), pst_ptr,
|
||||
pst.length(), NULL);
|
||||
pst.length(), NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_NO_FATAL_FAILURE(s.close());
|
||||
}
|
||||
@@ -4930,7 +4986,7 @@ TEST_P(UsageTableTestWithMAC, OfflineEmptyPST) {
|
||||
s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0],
|
||||
s.signature().size(), s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0,
|
||||
NULL);
|
||||
NULL, OEMCrypto_ContentLicense);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_NO_FATAL_FAILURE(s.close());
|
||||
}
|
||||
@@ -4952,7 +5008,8 @@ TEST_P(UsageTableTestWithMAC, ReloadOfflineWrongPST) {
|
||||
OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(),
|
||||
&s.signature()[0], s.signature().size(), NULL, NULL,
|
||||
s.num_keys(), s.key_array(),
|
||||
pst_ptr, bad_pst.length(), NULL));
|
||||
pst_ptr, bad_pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
|
||||
TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) {
|
||||
@@ -4986,7 +5043,8 @@ TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), pst_ptr, pst.length(), NULL));
|
||||
s.key_array(), pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
s2.close();
|
||||
// But we can still generate a report.
|
||||
Session s3;
|
||||
@@ -5013,7 +5071,8 @@ TEST_P(UsageTableTestWithMAC, BadRange) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), pst_ptr, pst.length(), NULL));
|
||||
s.key_array(), pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
|
||||
TEST_F(UsageTableTest, UpdateFailsWithNullPtr) {
|
||||
@@ -5090,7 +5149,8 @@ class UsageTableDefragTest : public UsageTableTest {
|
||||
&s->signature()[0], s->signature().size(),
|
||||
s->encrypted_license().mac_key_iv,
|
||||
s->encrypted_license().mac_keys, s->num_keys(),
|
||||
s->key_array(), pst_ptr, s->pst().length(), NULL));
|
||||
s->key_array(), pst_ptr, s->pst().length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
ASSERT_NO_FATAL_FAILURE(s->close());
|
||||
}
|
||||
|
||||
@@ -5212,6 +5272,7 @@ TEST_F(UsageTableDefragTest, ReloadUsageEntryBadData) {
|
||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||
vector<uint8_t> data = s.encrypted_usage_entry();
|
||||
ASSERT_LT(0, data.size());
|
||||
data[0] ^= 42;
|
||||
// Error could be signature or verification error.
|
||||
ASSERT_NE(OEMCrypto_SUCCESS,
|
||||
@@ -5607,7 +5668,8 @@ TEST_F(UsageTableTest, LoadSharedLicenseWithNoMaster) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys,
|
||||
s.num_keys(), s.key_array(), pst_ptr, pst.length(), NULL));
|
||||
s.num_keys(), s.key_array(), pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
ASSERT_NO_FATAL_FAILURE(s.close());
|
||||
}
|
||||
|
||||
@@ -5642,7 +5704,8 @@ TEST_F(UsageTableTest, PSTLargeBuffer) {
|
||||
&s.signature()[0], s.signature().size(),
|
||||
s.encrypted_license().mac_key_iv,
|
||||
s.encrypted_license().mac_keys, s.num_keys(),
|
||||
s.key_array(), pst_ptr, pst.length(), NULL));
|
||||
s.key_array(), pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
s2.close();
|
||||
// But we can still generate a report.
|
||||
Session s3;
|
||||
|
||||
Reference in New Issue
Block a user