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:
Fred Gylys-Colwell
2018-01-25 15:09:54 -08:00
committed by Rahul Frias
parent 795cf8a624
commit 8de7caf788
5 changed files with 24 additions and 49 deletions

View File

@@ -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;

View File

@@ -73,9 +73,8 @@ 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:
SessionKeyTable session_keys_; SessionKeyTable session_keys_;
@@ -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.
@@ -333,7 +332,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
} }
if (using_usage_mac_key_client && if (using_usage_mac_key_client &&
LogCategoryEnabled(kLoggingDumpDerivedKeys)) { LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> usage_entry_mac_key_client( std::vector<uint8_t> usage_entry_mac_key_client(
usage_entry_->mac_key_client(), usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t)); usage_entry_->mac_key_client() + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
@@ -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;

View File

@@ -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);

View File

@@ -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),

View File

@@ -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,