Regular update

Plugin:
1. Process ECM v3 and send fingerprinting/service_blocking events
2. Rmove unused function Ctr128Add
3. Add support for ECM v3

OEMCrypto:
1. Update API description of OEMCrypto_LoadCasECMKeys
2. Fix android build files for ODK
3. Load content keys to shared memory
4. Move KCB check to LoadCasKeys call
5. Support even/odd content keys to share entitlement key
This commit is contained in:
Lu Chen
2021-01-05 10:16:26 -08:00
parent 66d8498d2c
commit 00785b2ccd
38 changed files with 2234 additions and 747 deletions

View File

@@ -794,33 +794,98 @@ void EntitledMessage::LoadKeys(OEMCryptoResult expected_sts) {
VerifyEntitlementTestKeys();
}
void EntitledMessage::LoadCasKeys(OEMCryptoResult expected_sts, bool load_even,
bool load_odd) {
for (size_t i = 0; i < num_keys_; ++i) {
EntitledContentKeyData* key_data = &entitled_key_data_[i];
const size_t entitlement_key_index = key_data->key_index;
MessageKeyData* entitlement_key =
&license_messages_->response_data().keys[entitlement_key_index];
// Load the entitlement key from |key_array_|.
AES_KEY aes_key;
AES_set_encrypt_key(entitlement_key->key_data, 256, &aes_key);
// Encrypt the content key with the entitlement key.
uint8_t iv[16];
memcpy(&iv[0], key_data->content_key_data_iv, KEY_IV_SIZE);
AES_cbc_encrypt(key_data->content_key_data,
key_data->encrypted_content_key_data, KEY_SIZE, &aes_key,
iv, AES_ENCRYPT);
}
// Convert the OEMCrypto_EntitledContentKeyObject to
// OEMCrypto_EntitledCasKeyObject. Only the first two key object is used.
OEMCrypto_EntitledCasKeyObject even_key;
OEMCrypto_EntitledCasKeyObject odd_key;
bool has_even = load_even && num_keys_ >= 1;
bool has_odd = load_odd && num_keys_ >= 2;
if (has_even) {
even_key.entitlement_key_id = entitled_key_array_[0].entitlement_key_id;
even_key.content_key_id = entitled_key_array_[0].content_key_id;
even_key.content_key_data_iv = entitled_key_array_[0].content_key_data_iv;
even_key.content_key_data = entitled_key_array_[0].content_key_data;
even_key.content_iv.length = 0;
}
if (has_odd) {
odd_key.entitlement_key_id = entitled_key_array_[1].entitlement_key_id;
odd_key.content_key_id = entitled_key_array_[1].content_key_id;
odd_key.content_key_data_iv = entitled_key_array_[1].content_key_data_iv;
odd_key.content_key_data = entitled_key_array_[1].content_key_data;
odd_key.content_iv.length = 0;
}
ASSERT_EQ(
expected_sts,
OEMCrypto_LoadCasECMKeys(
key_session_, reinterpret_cast<const uint8_t*>(entitled_key_data_),
sizeof(entitled_key_data_), has_even ? &even_key : nullptr,
has_odd ? &odd_key : nullptr));
if (expected_sts != OEMCrypto_SUCCESS) {
return;
}
if (has_even) {
VerifyEntitlementTestKey(0);
}
if (has_odd) {
VerifyEntitlementTestKey(1);
}
}
// This function verifies that the key control block reported by OEMCrypto agree
// with the truth key control block. Failures in this function probably
// indicate the OEMCrypto_LoadEntitledKeys did not correctly process the key
// control block.
void EntitledMessage::VerifyEntitlementTestKeys() {
for (unsigned int i = 0; i < num_keys_; i++) {
EntitledContentKeyData* key_data = &entitled_key_data_[i];
const size_t entitlement_key_index = key_data->key_index;
MessageKeyData* entitlement_key =
&license_messages_->response_data().keys[entitlement_key_index];
KeyControlBlock block;
size_t size = sizeof(block);
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
key_session_, key_data->content_key_id, key_data->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(entitlement_key->control.duration)),
(htonl_fnc(block.duration)))
<< "For key " << i;
ASSERT_EQ(htonl_fnc(entitlement_key->control.control_bits),
htonl_fnc(block.control_bits))
<< "For key " << i;
}
VerifyEntitlementTestKey(i);
}
}
void EntitledMessage::VerifyEntitlementTestKey(size_t index) {
ASSERT_GE(num_keys_, index);
EntitledContentKeyData* key_data = &entitled_key_data_[index];
const size_t entitlement_key_index = key_data->key_index;
MessageKeyData* entitlement_key =
&license_messages_->response_data().keys[entitlement_key_index];
KeyControlBlock block;
size_t size = sizeof(block);
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
key_session_, key_data->content_key_id, key_data->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(entitlement_key->control.duration)),
(htonl_fnc(block.duration)))
<< "For key " << index;
ASSERT_EQ(htonl_fnc(entitlement_key->control.control_bits),
htonl_fnc(block.control_bits))
<< "For key " << index;
}
}