Fix entitlement keys encryption and content key loading.
Merge from Widevine repo of http://go/wvgerrit/41831 Bug: 72418096 OEMCrypto14 entitlement keys failed decryption testing Test: in child CL Change-Id: Ie92c34edb6162fb1e4553c5364f478de189ab793
This commit is contained in:
committed by
Rahul Frias
parent
795cf8a624
commit
8de7caf788
@@ -95,8 +95,8 @@ class EntitlementKey : public Key {
|
|||||||
const std::vector<uint8_t>& content_key() { 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>& content_key_id() { return content_key_id_; }
|
||||||
const std::vector<uint8_t>& entitlement_key() { return Key::value(); }
|
const std::vector<uint8_t>& entitlement_key() { return Key::value(); }
|
||||||
bool SetContentKey(const std::vector<uint8_t>& content_key,
|
bool SetContentKey(const std::vector<uint8_t>& content_key_id,
|
||||||
const std::vector<uint8_t>& content_key_id) {
|
const std::vector<uint8_t>& content_key) {
|
||||||
content_key_.assign(content_key.begin(), content_key.end());
|
content_key_.assign(content_key.begin(), content_key.end());
|
||||||
content_key_id_.assign(content_key_id.begin(), content_key_id.end());
|
content_key_id_.assign(content_key_id.begin(), content_key_id.end());
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -73,8 +73,7 @@ class ContentKeysContext : public SessionContextKeys {
|
|||||||
virtual bool SetContentKey(const KeyId& entitlement_id,
|
virtual bool SetContentKey(const KeyId& entitlement_id,
|
||||||
const KeyId& content_key_id,
|
const KeyId& content_key_id,
|
||||||
const std::vector<uint8_t>& content_key);
|
const std::vector<uint8_t>& content_key);
|
||||||
virtual bool GetEntitlementKey(
|
virtual bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||||
const KeyId& entitlement_id,
|
|
||||||
const std::vector<uint8_t>** entitlement_key);
|
const std::vector<uint8_t>** entitlement_key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -105,8 +104,8 @@ bool ContentKeysContext::SetContentKey(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContentKeysContext::GetEntitlementKey(
|
bool ContentKeysContext::GetEntitlementKey(const KeyId& entitlement_id,
|
||||||
const KeyId& entitlement_id, const std::vector<uint8_t>** key) {
|
const std::vector<uint8_t>** key) {
|
||||||
// Unsupported action for this type.
|
// Unsupported action for this type.
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -314,7 +313,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *mac_key = NULL;
|
const uint8_t* mac_key = NULL;
|
||||||
bool using_usage_mac_key_client = false;
|
bool using_usage_mac_key_client = false;
|
||||||
if (mac_key_client_.size() == wvcdm::MAC_KEY_SIZE) {
|
if (mac_key_client_.size() == wvcdm::MAC_KEY_SIZE) {
|
||||||
// If we have a mac key, use it.
|
// If we have a mac key, use it.
|
||||||
@@ -620,9 +619,9 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
key_control_iv.assign(key_array[i].key_control_iv,
|
key_control_iv.assign(key_array[i].key_control_iv,
|
||||||
key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE);
|
key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE);
|
||||||
|
|
||||||
OEMCryptoResult result = InstallKey(
|
OEMCryptoResult result =
|
||||||
key_id, enc_key_data, key_data_iv, key_control, key_control_iv,
|
InstallKey(key_id, enc_key_data, key_data_iv, key_control,
|
||||||
second_license);
|
key_control_iv, second_license);
|
||||||
if (result != OEMCrypto_SUCCESS) {
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
status = result;
|
status = result;
|
||||||
break;
|
break;
|
||||||
@@ -683,8 +682,7 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
||||||
size_t num_keys,
|
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array) {
|
||||||
const OEMCrypto_EntitledContentKeyObject* key_array) {
|
|
||||||
if (!key_array) {
|
if (!key_array) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -694,9 +692,9 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
|||||||
for (size_t i = 0; i < num_keys; ++i) {
|
for (size_t i = 0; i < num_keys; ++i) {
|
||||||
const OEMCrypto_EntitledContentKeyObject* key_data = &key_array[i];
|
const OEMCrypto_EntitledContentKeyObject* key_data = &key_array[i];
|
||||||
std::vector<uint8_t> entitlement_key_id;
|
std::vector<uint8_t> entitlement_key_id;
|
||||||
entitlement_key_id.assign(key_data->entitlement_key_id,
|
entitlement_key_id.assign(
|
||||||
key_data->entitlement_key_id +
|
key_data->entitlement_key_id,
|
||||||
key_data->entitlement_key_id_length);
|
key_data->entitlement_key_id + key_data->entitlement_key_id_length);
|
||||||
|
|
||||||
const std::vector<uint8_t>* entitlement_key = NULL;
|
const std::vector<uint8_t>* entitlement_key = NULL;
|
||||||
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
|
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
|
||||||
@@ -716,12 +714,12 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
|||||||
content_key_id.assign(
|
content_key_id.assign(
|
||||||
key_data->content_key_id,
|
key_data->content_key_id,
|
||||||
key_data->content_key_id + key_data->content_key_id_length);
|
key_data->content_key_id + key_data->content_key_id_length);
|
||||||
if (!DecryptEntitlement(*entitlement_key, iv,
|
if (!DecryptMessage(*entitlement_key, iv, encrypted_content_key,
|
||||||
encrypted_content_key, &content_key)) {
|
&content_key)) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
if (!session_keys_->SetContentKey(
|
if (!session_keys_->SetContentKey(entitlement_key_id, content_key_id,
|
||||||
entitlement_key_id, content_key_id, content_key)) {
|
content_key)) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -732,8 +730,7 @@ OEMCryptoResult SessionContext::InstallKey(
|
|||||||
const KeyId& key_id, const std::vector<uint8_t>& key_data,
|
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_data_iv,
|
||||||
const std::vector<uint8_t>& key_control,
|
const std::vector<uint8_t>& key_control,
|
||||||
const std::vector<uint8_t>& key_control_iv,
|
const std::vector<uint8_t>& key_control_iv, bool second_license) {
|
||||||
bool second_license) {
|
|
||||||
// Decrypt encrypted key_data using derived encryption key and offered iv
|
// Decrypt encrypted key_data using derived encryption key and offered iv
|
||||||
std::vector<uint8_t> content_key;
|
std::vector<uint8_t> content_key;
|
||||||
std::vector<uint8_t> key_control_str;
|
std::vector<uint8_t> key_control_str;
|
||||||
@@ -1339,26 +1336,7 @@ bool SessionContext::DecryptMessage(const std::vector<uint8_t>& key,
|
|||||||
uint8_t iv_buffer[16];
|
uint8_t iv_buffer[16];
|
||||||
memcpy(iv_buffer, &iv[0], 16);
|
memcpy(iv_buffer, &iv[0], 16);
|
||||||
AES_KEY aes_key;
|
AES_KEY aes_key;
|
||||||
AES_set_decrypt_key(&key[0], 128, &aes_key);
|
AES_set_decrypt_key(&key[0], key.size() * 8, &aes_key);
|
||||||
AES_cbc_encrypt(&message[0], &(decrypted->front()), message.size(), &aes_key,
|
|
||||||
iv_buffer, AES_DECRYPT);
|
|
||||||
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,
|
AES_cbc_encrypt(&message[0], &(decrypted->front()), message.size(), &aes_key,
|
||||||
iv_buffer, AES_DECRYPT);
|
iv_buffer, AES_DECRYPT);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -190,10 +190,6 @@ class SessionContext {
|
|||||||
const std::vector<uint8_t>& iv,
|
const std::vector<uint8_t>& iv,
|
||||||
const std::vector<uint8_t>& message,
|
const std::vector<uint8_t>& message,
|
||||||
std::vector<uint8_t>* decrypted);
|
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
|
// Either verify the nonce or usage entry, as required by the key control
|
||||||
// block.
|
// block.
|
||||||
OEMCryptoResult CheckNonceOrEntry(const KeyControlBlock& key_control_block);
|
OEMCryptoResult CheckNonceOrEntry(const KeyControlBlock& key_control_block);
|
||||||
|
|||||||
@@ -596,7 +596,8 @@ void Session::EncryptAndSign() {
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||||
memcpy(iv_buffer, &license_.keys[i].control_iv[0], wvcdm::KEY_IV_SIZE);
|
memcpy(iv_buffer, &license_.keys[i].control_iv[0], wvcdm::KEY_IV_SIZE);
|
||||||
AES_set_encrypt_key(&license_.keys[i].key_data[0], 128, &aes_key);
|
AES_set_encrypt_key(&license_.keys[i].key_data[0],
|
||||||
|
license_.keys[i].key_data_length * 8, &aes_key);
|
||||||
AES_cbc_encrypt(
|
AES_cbc_encrypt(
|
||||||
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
|
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
|
||||||
reinterpret_cast<uint8_t*>(&encrypted_license().keys[i].control),
|
reinterpret_cast<uint8_t*>(&encrypted_license().keys[i].control),
|
||||||
|
|||||||
@@ -5265,7 +5265,7 @@ TEST_F(UsageTableDefragTest, ReloadUsageEntryBadData) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||||
vector<uint8_t> data = s.encrypted_usage_entry();
|
vector<uint8_t> data = s.encrypted_usage_entry();
|
||||||
ASSERT_LT(0, data.size());
|
ASSERT_LT(0UL, data.size());
|
||||||
data[0] ^= 42;
|
data[0] ^= 42;
|
||||||
// Error could be signature or verification error.
|
// Error could be signature or verification error.
|
||||||
ASSERT_NE(OEMCrypto_SUCCESS,
|
ASSERT_NE(OEMCrypto_SUCCESS,
|
||||||
|
|||||||
Reference in New Issue
Block a user