Update OEMCrypto calls to use substrings

Merge from master branch of Widevine repo of http://go/wvgerrit/66073
Merge from oemcrypto-v15 branch of Widevine repo of http://go/wvgerrit/64083

As part of the update to v15, LoadKeys, RefreshKeys, and
LoadEntitledContentKeys should all use offsets and lengths into the
message rather than a pointer for its parameters. The CDM, tests,
adapters, and OEMCrypto implementations are changed to reflect this.

Test: tested as part of http://go/ag/5501993
Bug: 115874964

Change-Id: I981fa322dec7c565066fd163ca5775dbff71fccf
This commit is contained in:
Srujan Gaddam
2018-11-12 14:18:00 -08:00
committed by Fred Gylys-Colwell
parent 4550979f22
commit e6439255ba
20 changed files with 1057 additions and 776 deletions

View File

@@ -492,10 +492,11 @@ uint32_t SessionContext::CurrentTimer() {
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, OEMCrypto_LicenseType license_type) {
size_t signature_length, OEMCrypto_Substring enc_mac_keys_iv,
OEMCrypto_Substring enc_mac_keys, size_t num_keys,
const OEMCrypto_KeyObject* key_array, OEMCrypto_Substring pst,
OEMCrypto_Substring srm_restriction_data,
OEMCrypto_LicenseType license_type) {
// Validate message signature
if (!ValidateMessage(message, message_length, signature, signature_length)) {
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
@@ -522,16 +523,16 @@ OEMCryptoResult SessionContext::LoadKeys(
StartTimer();
if (srm_requirement) {
if (srm_restriction_data.length != 0) {
const std::string kSRMVerificationString = "HDCPDATA";
if (memcmp(srm_requirement, kSRMVerificationString.c_str(),
kSRMVerificationString.size())) {
if (memcmp(message + srm_restriction_data.offset,
kSRMVerificationString.c_str(), kSRMVerificationString.size())) {
LOGE("SRM Requirement Data has bad verification string: %8s",
srm_requirement);
message + srm_restriction_data.offset);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
uint32_t minimum_version =
htonl(*reinterpret_cast<const uint32_t*>(srm_requirement + 8));
uint32_t minimum_version = htonl(*reinterpret_cast<const uint32_t*>(
message + srm_restriction_data.offset + 8));
uint16_t current_version = 0;
if (OEMCrypto_SUCCESS != ce_->current_srm_version(&current_version)) {
LOGW("[LoadKeys: SRM Version not available.");
@@ -563,20 +564,25 @@ OEMCryptoResult SessionContext::LoadKeys(
std::vector<uint8_t> key_control;
std::vector<uint8_t> key_control_iv;
for (unsigned int i = 0; i < num_keys; i++) {
key_id.assign(key_array[i].key_id,
key_array[i].key_id + key_array[i].key_id_length);
enc_key_data.assign(key_array[i].key_data,
key_array[i].key_data + key_array[i].key_data_length);
key_data_iv.assign(key_array[i].key_data_iv,
key_array[i].key_data_iv + wvoec::KEY_IV_SIZE);
if (key_array[i].key_control == NULL) {
key_id.assign(
message + key_array[i].key_id.offset,
message + key_array[i].key_id.offset + key_array[i].key_id.length);
enc_key_data.assign(
message + key_array[i].key_data.offset,
message + key_array[i].key_data.offset + key_array[i].key_data.length);
key_data_iv.assign(
message + key_array[i].key_data_iv.offset,
message + key_array[i].key_data_iv.offset + wvoec::KEY_IV_SIZE);
if (key_array[i].key_control.length == 0) {
status = OEMCrypto_ERROR_UNKNOWN_FAILURE;
break;
}
key_control.assign(key_array[i].key_control,
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
key_control_iv.assign(key_array[i].key_control_iv,
key_array[i].key_control_iv + wvoec::KEY_IV_SIZE);
key_control.assign(
message + key_array[i].key_control.offset,
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
key_control_iv.assign(
message + key_array[i].key_control_iv.offset,
message + key_array[i].key_control_iv.offset + wvoec::KEY_IV_SIZE);
OEMCryptoResult result =
InstallKey(key_id, enc_key_data, key_data_iv, key_control,
@@ -590,12 +596,14 @@ OEMCryptoResult SessionContext::LoadKeys(
if (status != OEMCrypto_SUCCESS) return status;
// enc_mac_key can be NULL if license renewal is not supported
if (enc_mac_keys != NULL) {
if (enc_mac_keys.length != 0) {
// V2.1 license protocol: update mac keys after processing license response
const std::vector<uint8_t> enc_mac_keys_str = std::vector<uint8_t>(
enc_mac_keys, enc_mac_keys + 2 * wvoec::MAC_KEY_SIZE);
message + enc_mac_keys.offset,
message + enc_mac_keys.offset + 2 * wvoec::MAC_KEY_SIZE);
const std::vector<uint8_t> enc_mac_key_iv_str = std::vector<uint8_t>(
enc_mac_key_iv, enc_mac_key_iv + wvoec::KEY_IV_SIZE);
message + enc_mac_keys_iv.offset,
message + enc_mac_keys_iv.offset + wvoec::KEY_IV_SIZE);
if (!UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) {
LOGE("Failed to update mac keys.\n");
@@ -606,13 +614,13 @@ OEMCryptoResult SessionContext::LoadKeys(
OEMCryptoResult result = OEMCrypto_SUCCESS;
switch (usage_entry_status_) {
case kNoUsageEntry:
if (pst_length > 0) {
if (pst.length > 0) {
LOGE("LoadKeys: PST specified but no usage entry loaded.");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
break; // no extra check.
case kUsageEntryNew:
result = usage_entry_->SetPST(pst, pst_length);
result = usage_entry_->SetPST(message + pst.offset, pst.length);
if (result != OEMCrypto_SUCCESS) {
return result;
}
@@ -622,7 +630,7 @@ OEMCryptoResult SessionContext::LoadKeys(
}
break;
case kUsageEntryLoaded:
if (!usage_entry_->VerifyPST(pst, pst_length)) {
if (!usage_entry_->VerifyPST(message + pst.offset, pst.length)) {
return OEMCrypto_ERROR_WRONG_PST;
}
if (!usage_entry_->VerifyMacKeys(mac_key_server_, mac_key_client_)) {
@@ -637,7 +645,8 @@ OEMCryptoResult SessionContext::LoadKeys(
}
OEMCryptoResult SessionContext::LoadEntitledContentKeys(
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array) {
const uint8_t* message, size_t message_length, size_t num_keys,
const OEMCrypto_EntitledContentKeyObject* key_array) {
if (!key_array) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -647,9 +656,9 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
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);
entitlement_key_id.assign(message + key_data->entitlement_key_id.offset,
message + key_data->entitlement_key_id.offset +
key_data->entitlement_key_id.length);
const std::vector<uint8_t>* entitlement_key = NULL;
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
@@ -661,14 +670,14 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
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);
iv.assign(message + key_data->content_key_data_iv.offset,
message + key_data->content_key_data_iv.offset + 16);
encrypted_content_key.assign(message + key_data->content_key_data.offset,
message + key_data->content_key_data.offset +
key_data->content_key_data.length);
content_key_id.assign(message + key_data->content_key_id.offset,
message + key_data->content_key_id.offset +
key_data->content_key_id.length);
if (!DecryptMessage(*entitlement_key, iv, encrypted_content_key,
&content_key, 256 /* key size */)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;