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

@@ -239,12 +239,21 @@ bool RangeCheck(const uint8_t* message, uint32_t message_length,
return true;
}
bool RangeCheck(uint32_t message_length, const OEMCrypto_Substring& substring,
bool allow_null) {
if (!substring.length) return allow_null;
if (substring.offset > message_length) return false;
if (substring.offset + substring.length > message_length) return false;
return true;
}
extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
OEMCrypto_SESSION session, 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) {
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) {
if (!crypto_engine) {
LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -263,20 +272,12 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
// Later on, we use pst_length to verify the the pst is valid. This makes
// sure that we aren't given a null string but told it has postiive length.
if (pst == NULL && pst_length > 0) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_ONCTEXT - null pst.]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
// Range check
if (!RangeCheck(message, message_length, enc_mac_keys, 2 * wvoec::MAC_KEY_SIZE,
true) ||
!RangeCheck(message, message_length, enc_mac_key_iv, wvoec::KEY_IV_SIZE, true) ||
!RangeCheck(message, message_length, pst, pst_length, true) ||
!RangeCheck(message, message_length, srm_requirement,
wvoec::SRM_REQUIREMENT_SIZE, true)) {
if (!RangeCheck(message_length, enc_mac_keys_iv, true) ||
!RangeCheck(message_length, enc_mac_keys, true) ||
!RangeCheck(message_length, pst, true) ||
!RangeCheck(message_length, srm_restriction_data, true)) {
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range "
"check.]");
@@ -284,16 +285,11 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
}
for (unsigned int i = 0; i < num_keys; i++) {
if (!RangeCheck(message, message_length, key_array[i].key_id,
key_array[i].key_id_length, false) ||
!RangeCheck(message, message_length, key_array[i].key_data,
key_array[i].key_data_length, false) ||
!RangeCheck(message, message_length, key_array[i].key_data_iv,
wvoec::KEY_IV_SIZE, false) ||
!RangeCheck(message, message_length, key_array[i].key_control,
wvoec::KEY_CONTROL_SIZE, false) ||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
wvoec::KEY_IV_SIZE, false)) {
if (!RangeCheck(message_length, key_array[i].key_id, false) ||
!RangeCheck(message_length, key_array[i].key_data, false) ||
!RangeCheck(message_length, key_array[i].key_data_iv, false) ||
!RangeCheck(message_length, key_array[i].key_control, false) ||
!RangeCheck(message_length, key_array[i].key_control_iv, false)) {
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT -range "
"check %d]",
@@ -302,14 +298,14 @@ 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, license_type);
signature_length, enc_mac_keys_iv, enc_mac_keys,
num_keys, key_array, pst, srm_restriction_data,
license_type);
}
extern "C" OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
OEMCrypto_SESSION session, size_t num_keys,
const OEMCrypto_EntitledContentKeyObject* key_array) {
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array) {
if (num_keys == 0) {
LOGE("[OEMCrypto_LoadEntitledContentKeys(): key_array is empty.");
return OEMCrypto_SUCCESS;
@@ -327,8 +323,22 @@ extern "C" OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
LOGE("[OEMCrypto_LoadEntitledContentKeys(): ERROR_INVALID_SESSION]");
return OEMCrypto_ERROR_INVALID_SESSION;
}
for (unsigned int i = 0; i < num_keys; i++) {
if (!RangeCheck(message_length, key_array[i].entitlement_key_id, false) ||
!RangeCheck(message_length, key_array[i].content_key_id, false) ||
!RangeCheck(message_length, key_array[i].content_key_data_iv, false) ||
!RangeCheck(message_length, key_array[i].content_key_data, false)) {
LOGE(
"[OEMCrypto_LoadEntitledContentKeys(): "
"OEMCrypto_ERROR_INVALID_CONTEXT -range "
"check %d]",
i);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
}
return session_ctx->LoadEntitledContentKeys(num_keys, key_array);
return session_ctx->LoadEntitledContentKeys(message, message_length, num_keys,
key_array);
}
extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
@@ -359,12 +369,9 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
// Range check
for (unsigned int i = 0; i < num_keys; i++) {
if (!RangeCheck(message, message_length, key_array[i].key_id,
key_array[i].key_id_length, true) ||
!RangeCheck(message, message_length, key_array[i].key_control,
wvoec::KEY_CONTROL_SIZE, false) ||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
wvoec::KEY_IV_SIZE, true)) {
if (!RangeCheck(message_length, key_array[i].key_id, true) ||
!RangeCheck(message_length, key_array[i].key_control, false) ||
!RangeCheck(message_length, key_array[i].key_control_iv, true)) {
LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -383,24 +390,28 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
std::vector<uint8_t> key_control;
std::vector<uint8_t> key_control_iv;
for (unsigned int i = 0; i < num_keys; i++) {
if (key_array[i].key_id != NULL) {
key_id.assign(key_array[i].key_id,
key_array[i].key_id + key_array[i].key_id_length);
key_control.assign(key_array[i].key_control,
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
if (key_array[i].key_control_iv == NULL) {
if (key_array[i].key_id.length != 0) {
key_id.assign(
message + key_array[i].key_id.offset,
message + key_array[i].key_id.offset + key_array[i].key_id.length);
key_control.assign(
message + key_array[i].key_control.offset,
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
if (key_array[i].key_control_iv.length == 0) {
key_control_iv.clear();
} else {
key_control_iv.assign(key_array[i].key_control_iv,
key_array[i].key_control_iv + wvoec::KEY_IV_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);
}
} else {
// key_id could be null if special control key type
// key_control is not encrypted in this case
key_id.clear();
key_control_iv.clear();
key_control.assign(key_array[i].key_control,
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
key_control.assign(
message + key_array[i].key_control.offset,
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
}
status = session_ctx->RefreshKey(key_id, key_control, key_control_iv);