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:
committed by
Fred Gylys-Colwell
parent
4550979f22
commit
e6439255ba
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user