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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user