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

@@ -97,6 +97,26 @@ class boringssl_ptr {
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
};
OEMCrypto_Substring GetSubstring(const std::string& message,
const std::string& field, bool set_zero) {
OEMCrypto_Substring substring;
if (set_zero || field.empty() || message.empty()) {
substring.offset = 0;
substring.length = 0;
} else {
size_t pos = message.find(field);
if (pos == std::string::npos) {
LOGW("GetSubstring : Cannot find offset for %s", field.c_str());
substring.offset = 0;
substring.length = 0;
} else {
substring.offset = pos;
substring.length = field.length();
}
}
return substring;
}
Session::Session()
: open_(false),
forced_session_id_(false),
@@ -254,129 +274,146 @@ void Session::GenerateDerivedKeysFromSessionKey() {
DeriveKeys(&session_key[0], mac_context, enc_context);
}
void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
uint8_t* pst_ptr = NULL;
if (pst.length() > 0) {
pst_ptr = encrypted_license().pst;
}
void Session::LoadTestKeys(const std::string& provider_session_token,
bool new_mac_keys) {
std::string message =
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
OEMCrypto_Substring pst = GetSubstring(message, provider_session_token);
OEMCrypto_Substring enc_mac_keys_iv = GetSubstring(
message, wvcdm::BytesToString(encrypted_license().mac_key_iv,
sizeof(encrypted_license().mac_key_iv)));
OEMCrypto_Substring enc_mac_keys = GetSubstring(
message, wvcdm::BytesToString(encrypted_license().mac_keys,
sizeof(encrypted_license().mac_keys)));
if (new_mac_keys) {
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
&signature_[0], signature_.size(),
encrypted_license().mac_key_iv,
encrypted_license().mac_keys, num_keys_,
key_array_, pst_ptr, pst.length(), NULL,
OEMCrypto_ContentLicense));
OEMCrypto_LoadKeys(
session_id(), message_ptr(), message_size_, &signature_[0],
signature_.size(), enc_mac_keys_iv, enc_mac_keys, num_keys_,
key_array_, pst, GetSubstring(), OEMCrypto_ContentLicense));
// Update new generated keys.
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE,
MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE, MAC_KEY_SIZE);
} else {
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
&signature_[0], signature_.size(), NULL, NULL,
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
OEMCrypto_ContentLicense));
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_LoadKeys(
session_id(), message_ptr(), message_size_, &signature_[0],
signature_.size(), GetSubstring(), GetSubstring(), num_keys_,
key_array_, pst, GetSubstring(), OEMCrypto_ContentLicense));
}
VerifyTestKeys();
}
void Session::LoadEntitlementTestKeys(const std::string& pst,
bool new_mac_keys,
OEMCryptoResult expected_sts) {
uint8_t* pst_ptr = NULL;
if (pst.length() > 0) {
pst_ptr = encrypted_license().pst;
}
void Session::LoadEntitlementTestKeys(const std::string& provider_session_token,
bool new_mac_keys,
OEMCryptoResult expected_sts) {
std::string message =
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
OEMCrypto_Substring pst = GetSubstring(message, provider_session_token);
OEMCrypto_Substring enc_mac_keys_iv = GetSubstring(
message, wvcdm::BytesToString(encrypted_license().mac_key_iv,
sizeof(encrypted_license().mac_key_iv)));
OEMCrypto_Substring enc_mac_keys = GetSubstring(
message, wvcdm::BytesToString(encrypted_license().mac_keys,
sizeof(encrypted_license().mac_keys)));
if (new_mac_keys) {
ASSERT_EQ(expected_sts,
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
&signature_[0], signature_.size(),
encrypted_license().mac_key_iv,
encrypted_license().mac_keys, num_keys_,
key_array_, pst_ptr, pst.length(), NULL,
OEMCrypto_EntitlementLicense));
ASSERT_EQ(
expected_sts,
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
&signature_[0], signature_.size(), enc_mac_keys_iv,
enc_mac_keys, num_keys_, key_array_, pst,
GetSubstring(), OEMCrypto_EntitlementLicense));
// Update new generated keys.
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE,
MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE, MAC_KEY_SIZE);
} else {
ASSERT_EQ(
expected_sts,
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
&signature_[0], signature_.size(), NULL, NULL,
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
OEMCrypto_EntitlementLicense));
&signature_[0], signature_.size(), GetSubstring(),
GetSubstring(), num_keys_, key_array_, pst,
GetSubstring(), OEMCrypto_EntitlementLicense));
}
}
void Session::FillEntitledKeyArray() {
int offset = 0;
entitled_message_.clear();
for (size_t i = 0; i < num_keys_; ++i) {
EntitledContentKeyData* key_data = &entitled_key_data_[i];
entitled_key_array_[i].entitlement_key_id = key_array_[i].key_id;
entitled_key_array_[i].entitlement_key_id_length =
key_array_[i].key_id_length;
entitled_key_array_[i].entitlement_key_id.offset = offset;
entitled_key_array_[i].entitlement_key_id.length =
key_array_[i].key_id.length;
offset += key_array_[i].key_id.length;
entitled_message_ +=
wvcdm::BytesToString(message_ptr() + key_array_[i].key_id.offset,
key_array_[i].key_id.length);
EXPECT_EQ(
1, GetRandBytes(key_data->content_key_id,
sizeof(key_data->content_key_id)));
entitled_key_array_[i].content_key_id = key_data->content_key_id;
entitled_key_array_[i].content_key_id_length =
EXPECT_EQ(1, GetRandBytes(key_data->content_key_id,
sizeof(key_data->content_key_id)));
entitled_key_array_[i].content_key_id.offset = offset;
entitled_key_array_[i].content_key_id.length =
sizeof(key_data->content_key_id);
offset += sizeof(key_data->content_key_id);
entitled_message_ += wvcdm::BytesToString(key_data->content_key_id,
sizeof(key_data->content_key_id));
EXPECT_EQ(
1, GetRandBytes(key_data->content_key_data,
sizeof(key_data->content_key_data)));
entitled_key_array_[i].content_key_data = key_data->content_key_data;
entitled_key_array_[i].content_key_data_length =
EXPECT_EQ(1, GetRandBytes(key_data->content_key_data,
sizeof(key_data->content_key_data)));
entitled_key_array_[i].content_key_data.offset = offset;
entitled_key_array_[i].content_key_data.length =
sizeof(key_data->content_key_data);
offset += sizeof(key_data->content_key_data);
entitled_message_ += wvcdm::BytesToString(
key_data->content_key_data, sizeof(key_data->content_key_data));
EXPECT_EQ(
1, GetRandBytes(entitled_key_data_[i].content_key_data_iv,
sizeof(entitled_key_data_[i].content_key_data_iv)));
entitled_key_array_[i].content_key_data_iv = key_data->content_key_data_iv;
EXPECT_EQ(1, GetRandBytes(key_data[i].content_key_data_iv,
sizeof(key_data[i].content_key_data_iv)));
entitled_key_array_[i].content_key_data_iv.offset = offset;
entitled_key_array_[i].content_key_data_iv.length =
sizeof(key_data->content_key_data_iv);
offset += sizeof(key_data->content_key_data_iv);
entitled_message_ += wvcdm::BytesToString(
key_data->content_key_data_iv, sizeof(key_data->content_key_data_iv));
}
}
void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) {
// Create a copy of the stored |entitled_key_array_|.
encrypted_entitled_message_ = entitled_message_;
std::vector<OEMCrypto_EntitledContentKeyObject> encrypted_entitled_key_array;
encrypted_entitled_key_array.resize(num_keys_);
memcpy(&encrypted_entitled_key_array[0], &entitled_key_array_[0],
sizeof(OEMCrypto_EntitledContentKeyObject) * num_keys_);
// Create an encrypted version of all of the content keys stored in
// |entitled_key_array_|.
std::vector<std::vector<uint8_t> > encrypted_content_keys;
encrypted_content_keys.resize(num_keys_);
for (size_t i = 0; i < num_keys_; ++i) {
// Load the entitlement key from |key_array_|.
AES_KEY aes_key;
AES_set_encrypt_key(&key_array_[i].key_data[0], 256, &aes_key);
encrypted_content_keys[i].resize(
encrypted_entitled_key_array[i].content_key_data_length);
AES_set_encrypt_key(message_ptr() + key_array_[i].key_data.offset, 256,
&aes_key);
// Encrypt the content key with the entitlement key.
uint8_t iv[16];
memcpy(&iv[0], &encrypted_entitled_key_array[i].content_key_data[0], 16);
AES_cbc_encrypt(
&entitled_key_array_[i].content_key_data[0],
const_cast<uint8_t*>(
&encrypted_entitled_key_array[i].content_key_data[0]),
encrypted_entitled_key_array[i].content_key_data_length,
&aes_key, iv, AES_ENCRYPT);
// Set the |encrypted_entitled_key_array| to point to the encrypted copy
// of the content key.
encrypted_entitled_key_array[i].content_key_data =
encrypted_content_keys[i].data();
const uint8_t* content_key_data = reinterpret_cast<const uint8_t*>(
entitled_message_.data() +
entitled_key_array_[i].content_key_data.offset);
const uint8_t* encrypted_content_key_data =
reinterpret_cast<const uint8_t*>(
encrypted_entitled_message_.data() +
encrypted_entitled_key_array[i].content_key_data.offset);
memcpy(&iv[0], encrypted_content_key_data, 16);
AES_cbc_encrypt(content_key_data,
const_cast<uint8_t*>(encrypted_content_key_data),
encrypted_entitled_key_array[i].content_key_data.length,
&aes_key, iv, AES_ENCRYPT);
}
ASSERT_EQ(expected_sts,
OEMCrypto_LoadEntitledContentKeys(
session_id(), num_keys_, &encrypted_entitled_key_array[0]));
ASSERT_EQ(
expected_sts,
OEMCrypto_LoadEntitledContentKeys(
session_id(),
reinterpret_cast<const uint8_t*>(encrypted_entitled_message_.data()),
encrypted_entitled_message_.size(), num_keys_,
&encrypted_entitled_key_array[0]));
if (expected_sts != OEMCrypto_SUCCESS) {
return;
}
@@ -409,9 +446,12 @@ void Session::VerifyEntitlementTestKeys() {
for (unsigned int i = 0; i < num_keys_; i++) {
KeyControlBlock block;
size_t size = sizeof(block);
const uint8_t* content_key_id =
reinterpret_cast<const uint8_t*>(entitled_message_.data());
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
session_id(), entitled_key_array_[i].content_key_id,
entitled_key_array_[i].content_key_id_length,
session_id(),
content_key_id + entitled_key_array_[i].content_key_id.offset,
entitled_key_array_[i].content_key_id.length,
reinterpret_cast<uint8_t*>(&block), &size);
if (sts != OEMCrypto_ERROR_NOT_IMPLEMENTED) {
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
@@ -578,6 +618,27 @@ void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
}
}
void Session::SetLoadKeysSubstringParams() {
load_keys_params_.resize(4);
std::string message =
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
OEMCrypto_Substring* enc_mac_keys_iv = &load_keys_params_[0];
*enc_mac_keys_iv = GetSubstring(
message, wvcdm::BytesToString(encrypted_license().mac_key_iv,
sizeof(encrypted_license().mac_key_iv)));
OEMCrypto_Substring* enc_mac_keys = &load_keys_params_[1];
*enc_mac_keys = GetSubstring(
message, wvcdm::BytesToString(encrypted_license().mac_keys,
sizeof(encrypted_license().mac_keys)));
OEMCrypto_Substring* pst = &load_keys_params_[2];
size_t pst_length =
strlen(reinterpret_cast<const char*>(encrypted_license().pst));
*pst = GetSubstring(
message, wvcdm::BytesToString(encrypted_license().pst, pst_length));
OEMCrypto_Substring* srm_req = &load_keys_params_[3];
*srm_req = GetSubstring();
}
void Session::EncryptAndSign() {
encrypted_license() = license_;
@@ -606,6 +667,7 @@ void Session::EncryptAndSign() {
ServerSignBuffer(reinterpret_cast<const uint8_t*>(&padded_message_),
message_size_, &signature_);
FillKeyArray(encrypted_license(), key_array_);
SetLoadKeysSubstringParams();
}
void Session::EncryptProvisioningMessage(
@@ -664,31 +726,45 @@ void Session::VerifyClientSignature(size_t data_length) {
void Session::FillKeyArray(const MessageData& data,
OEMCrypto_KeyObject* key_array) {
const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&data);
std::string message = wvcdm::BytesToString(data_ptr, sizeof(MessageData));
for (unsigned int i = 0; i < num_keys_; i++) {
key_array[i].key_id = data.keys[i].key_id;
key_array[i].key_id_length = data.keys[i].key_id_length;
key_array[i].key_data_iv = data.keys[i].key_iv;
key_array[i].key_data = data.keys[i].key_data;
key_array[i].key_data_length = data.keys[i].key_data_length;
key_array[i].key_control_iv = data.keys[i].control_iv;
key_array[i].key_control =
key_array[i].key_id = GetSubstring(
message,
wvcdm::BytesToString(data.keys[i].key_id, data.keys[i].key_id_length));
key_array[i].key_data_iv = GetSubstring(
message,
wvcdm::BytesToString(data.keys[i].key_iv, sizeof(data.keys[i].key_iv)));
key_array[i].key_data = GetSubstring(
message, wvcdm::BytesToString(data.keys[i].key_data,
data.keys[i].key_data_length));
key_array[i].key_control_iv = GetSubstring(
message, wvcdm::BytesToString(data.keys[i].control_iv,
sizeof(data.keys[i].control_iv)));
const uint8_t* key_control_ptr =
reinterpret_cast<const uint8_t*>(&data.keys[i].control);
key_array[i].key_control = GetSubstring(
message,
wvcdm::BytesToString(key_control_ptr, sizeof(data.keys[i].control)));
}
}
void Session::FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
size_t key_count) {
std::string message =
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
for (size_t i = 0; i < key_count; i++) {
if (key_count > 1) {
key_array[i].key_id = encrypted_license().keys[i].key_id;
key_array[i].key_id_length = encrypted_license().keys[i].key_id_length;
} else {
key_array[i].key_id = NULL;
key_array[i].key_id_length = 0;
}
key_array[i].key_control_iv = NULL;
key_array[i].key_control =
reinterpret_cast<const uint8_t*>(&encrypted_license().keys[i].control);
key_array[i].key_id = GetSubstring(
message,
wvcdm::BytesToString(encrypted_license().keys[i].key_id,
sizeof(encrypted_license().keys[i].key_id)),
key_count <= 1);
key_array[i].key_control_iv = GetSubstring();
key_array[i].key_control = GetSubstring(
message,
wvcdm::BytesToString(reinterpret_cast<const uint8_t*>(
&encrypted_license().keys[i].control),
sizeof(encrypted_license().keys[i].control)));
}
}
@@ -1290,4 +1366,8 @@ void Session::set_message_size(size_t size) {
ASSERT_LE(message_size_, kMaxMessageSize);
}
const uint8_t* Session::encrypted_entitled_message_ptr() {
return reinterpret_cast<const uint8_t*>(encrypted_entitled_message_.data());
}
} // namespace wvoec