Merge latest oemcrypto-v17 change
No-Typo-Check: Not related to this change. Bug: 161477208 Change-Id: I99e4780f6855b7045aa0cd5a49c13d2d0d51ed64
This commit is contained in:
committed by
Fred Gylys-Colwell
parent
c924960962
commit
642965c678
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "oec_session_util.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/cmac.h>
|
||||
@@ -18,7 +19,6 @@
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "clock.h"
|
||||
#include "core_message_deserialize.h"
|
||||
#include "core_message_features.h"
|
||||
#include "core_message_serialize.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "log.h"
|
||||
@@ -47,13 +48,13 @@ using namespace std;
|
||||
// which is std::vector in this case.
|
||||
namespace std {
|
||||
void PrintTo(const vector<uint8_t>& value, ostream* os) {
|
||||
*os << wvcdm::b2a_hex(value);
|
||||
*os << wvutil::b2a_hex(value);
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
namespace {
|
||||
using oemcrypto_core_message::features::CoreMessageFeatures;
|
||||
|
||||
constexpr size_t kTestSubsampleSectionSize = 256;
|
||||
|
||||
@@ -143,8 +144,8 @@ void GenerateSimpleSampleDescription(
|
||||
OEMCrypto_DestBufferDesc& out_buffer_descriptor =
|
||||
sample->buffers.output_descriptor;
|
||||
out_buffer_descriptor.type = OEMCrypto_BufferType_Clear;
|
||||
out_buffer_descriptor.buffer.clear.address = out.data();
|
||||
out_buffer_descriptor.buffer.clear.address_length = out.size();
|
||||
out_buffer_descriptor.buffer.clear.clear_buffer = out.data();
|
||||
out_buffer_descriptor.buffer.clear.clear_buffer_length = out.size();
|
||||
}
|
||||
|
||||
// Increment counter for AES-CTR. The CENC spec specifies we increment only
|
||||
@@ -155,7 +156,7 @@ void ctr128_inc64(int64_t increaseBy, uint8_t* iv) {
|
||||
ASSERT_NE(nullptr, iv);
|
||||
uint64_t* counterBuffer = reinterpret_cast<uint64_t*>(&iv[8]);
|
||||
(*counterBuffer) =
|
||||
wvcdm::htonll64(wvcdm::ntohll64(*counterBuffer) + increaseBy);
|
||||
wvutil::htonll64(wvutil::ntohll64(*counterBuffer) + increaseBy);
|
||||
}
|
||||
|
||||
// Some compilers don't like the macro htonl within an ASSERT_EQ.
|
||||
@@ -193,7 +194,7 @@ class boringssl_ptr {
|
||||
Test_PST_Report::Test_PST_Report(const std::string& pst_in,
|
||||
OEMCrypto_Usage_Entry_Status status_in)
|
||||
: status(status_in), pst(pst_in) {
|
||||
time_created = wvcdm::Clock().GetCurrentTime();
|
||||
time_created = wvutil::Clock().GetCurrentTime();
|
||||
}
|
||||
|
||||
template <class CoreRequest, PrepAndSignRequest_t PrepAndSignRequest,
|
||||
@@ -206,6 +207,9 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
|
||||
size_t gen_signature_length = 0;
|
||||
size_t core_message_length = 0;
|
||||
constexpr size_t small_size = 42; // arbitrary.
|
||||
if (RequestHasNonce()) {
|
||||
session()->GenerateNonce();
|
||||
}
|
||||
uint32_t session_id = session()->session_id();
|
||||
GetDefaultRequestSignatureAndCoreMessageLengths<PrepAndSignRequest>(
|
||||
session_id, small_size, &gen_signature_length, &core_message_length);
|
||||
@@ -296,10 +300,15 @@ OEMCrypto_Substring RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse,
|
||||
void ProvisioningRoundTrip::PrepareSession(
|
||||
const wvoec::WidevineKeybox& keybox) {
|
||||
ASSERT_NO_FATAL_FAILURE(session_->open());
|
||||
session_->GenerateNonce();
|
||||
if (global_features.provisioning_method == OEMCrypto_Keybox) {
|
||||
session_->GenerateDerivedKeysFromKeybox(keybox);
|
||||
encryptor_ = session_->key_deriver();
|
||||
} else if (global_features.provisioning_method ==
|
||||
OEMCrypto_BootCertificateChain) {
|
||||
// TODO(chelu): change this to CSR provisioning.
|
||||
session_->LoadOEMCert(true);
|
||||
session_->GenerateRSASessionKey(&message_key_, &encrypted_message_key_);
|
||||
encryptor_.set_enc_key(message_key_);
|
||||
} else {
|
||||
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_OEMCertificate);
|
||||
session_->LoadOEMCert(true);
|
||||
@@ -391,9 +400,12 @@ void ProvisioningRoundTrip::
|
||||
|
||||
void ProvisioningRoundTrip::SignResponse() {
|
||||
if (global_features.api_version >= kCoreMessagesAPI) {
|
||||
CoreMessageFeatures features =
|
||||
CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
|
||||
ASSERT_TRUE(
|
||||
oemcrypto_core_message::serialize::CreateCoreProvisioningResponse(
|
||||
core_response_, core_request_, &serialized_core_message_));
|
||||
features, core_response_, core_request_,
|
||||
&serialized_core_message_));
|
||||
// Resizing for huge core message length unit tests.
|
||||
serialized_core_message_.resize(
|
||||
std::max(required_core_message_size_, serialized_core_message_.size()));
|
||||
@@ -537,17 +549,24 @@ void ProvisioningRoundTrip::VerifyLoadFailed() {
|
||||
void LicenseRoundTrip::VerifyRequestSignature(
|
||||
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) {
|
||||
const std::vector<uint8_t> subdata(data.begin() + core_message_length,
|
||||
data.end());
|
||||
session()->VerifyRSASignature(subdata, generated_signature.data(),
|
||||
generated_signature.size(), kSign_RSASSA_PSS);
|
||||
SHA256(data.data(), core_message_length, request_hash_);
|
||||
// If the api version was not set by the test, then we record the api version
|
||||
// from the request. Also, if the api was set to be higher than oemcrypto
|
||||
// supports, then we lower it. This version will be used in the response.
|
||||
if (api_version_ == 0) api_version_ = core_request_.api_major_version;
|
||||
if (api_version_ > global_features.api_version)
|
||||
api_version_ = global_features.api_version;
|
||||
|
||||
if (global_features.api_version < 17) {
|
||||
const std::vector<uint8_t> subdata(data.begin() + core_message_length,
|
||||
data.end());
|
||||
session()->VerifyRSASignature(subdata, generated_signature.data(),
|
||||
generated_signature.size(), kSign_RSASSA_PSS);
|
||||
SHA256(data.data(), core_message_length, request_hash_);
|
||||
} else {
|
||||
session()->VerifyRSASignature(data, generated_signature.data(),
|
||||
generated_signature.size(), kSign_RSASSA_PSS);
|
||||
SHA256(data.data(), core_message_length, request_hash_);
|
||||
}
|
||||
}
|
||||
|
||||
void LicenseRoundTrip::FillAndVerifyCoreRequest(
|
||||
@@ -557,13 +576,13 @@ void LicenseRoundTrip::FillAndVerifyCoreRequest(
|
||||
core_message_string, &core_request_));
|
||||
EXPECT_EQ(global_features.api_version, core_request_.api_major_version);
|
||||
if (global_features.api_version == 16) {
|
||||
// We support either 16.3 or 16.4 for OEMCrypto 16.
|
||||
// We support either 16.3-16.4 for OEMCrypto 16 public release, and v16.5
|
||||
// for L3 release only.
|
||||
EXPECT_LE(3, core_request_.api_minor_version);
|
||||
EXPECT_GE(4, core_request_.api_minor_version);
|
||||
EXPECT_GE(5, core_request_.api_minor_version);
|
||||
} else if (global_features.api_version == ODK_MAJOR_VERSION) {
|
||||
// If we are testing the latest OEMCrypto version, make sure it is built
|
||||
// with the latest ODK version, too:
|
||||
EXPECT_EQ(ODK_MINOR_VERSION, core_request_.api_minor_version);
|
||||
// We do not expect older tests to work with a newer OEMCrypto.
|
||||
EXPECT_GE(ODK_MINOR_VERSION, core_request_.api_minor_version);
|
||||
}
|
||||
if (expect_request_has_correct_nonce_) {
|
||||
EXPECT_EQ(session()->nonce(), core_request_.nonce);
|
||||
@@ -604,7 +623,7 @@ void LicenseRoundTrip::CreateDefaultResponse() {
|
||||
response_data_.keys[i].control.duration = htonl(key_duration);
|
||||
response_data_.keys[i].control.nonce = htonl(session_->nonce());
|
||||
response_data_.keys[i].control.control_bits = htonl(control_);
|
||||
response_data_.keys[i].cipher_mode = OEMCrypto_CipherMode_CTR;
|
||||
response_data_.keys[i].cipher_mode = OEMCrypto_CipherMode_CENC;
|
||||
}
|
||||
// Fill in the default core_response_ fields, except the substrings, which are
|
||||
// filled in the next function.
|
||||
@@ -759,12 +778,20 @@ void LicenseRoundTrip::EncryptAndSignResponse() {
|
||||
sizeof(response_data_.keys[i].key_data) &&
|
||||
response_data_.keys[i].key_data_length % 16 == 0) {
|
||||
memcpy(iv_buffer, &response_data_.keys[i].control_iv[0], KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&response_data_.keys[i].key_data[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(
|
||||
reinterpret_cast<const uint8_t*>(&response_data_.keys[i].control),
|
||||
reinterpret_cast<uint8_t*>(&encrypted_response_data_.keys[i].control),
|
||||
KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
if (core_request_.api_major_version < kClearControlBlockAPIMajor ||
|
||||
(core_request_.api_major_version == kClearControlBlockAPIMajor &&
|
||||
core_request_.api_minor_version < kClearControlBlockAPIMinor)) {
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&response_data_.keys[i].key_data[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(
|
||||
reinterpret_cast<const uint8_t*>(&response_data_.keys[i].control),
|
||||
reinterpret_cast<uint8_t*>(
|
||||
&encrypted_response_data_.keys[i].control),
|
||||
KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
} else {
|
||||
encrypted_response_data_.keys[i].control =
|
||||
response_data_.keys[i].control;
|
||||
}
|
||||
session_->key_deriver().CBCEncrypt(
|
||||
&response_data_.keys[i].key_data[0],
|
||||
&encrypted_response_data_.keys[i].key_data[0],
|
||||
@@ -775,10 +802,22 @@ void LicenseRoundTrip::EncryptAndSignResponse() {
|
||||
if (api_version_ < kCoreMessagesAPI) {
|
||||
serialized_core_message_.resize(0);
|
||||
} else {
|
||||
if (core_request_.api_major_version == 0) {
|
||||
// If we don't have a valid request, then we should at least set the
|
||||
// version number of the request so that CreateCoreLicenseResponse can
|
||||
// compute the version number of the response.
|
||||
core_request_.api_major_version = ODK_MAJOR_VERSION;
|
||||
core_request_.api_minor_version = ODK_MINOR_VERSION;
|
||||
}
|
||||
std::string request_hash_string(
|
||||
reinterpret_cast<const char*>(request_hash_), sizeof(request_hash_));
|
||||
// We might try to test a future api_version_, but we can only make a core
|
||||
// message with at most the current ODK version. This is only done to verify
|
||||
// that OEMCrypto does not attempt to load a future version.
|
||||
CoreMessageFeatures features = CoreMessageFeatures::DefaultFeatures(
|
||||
std::min(api_version_, static_cast<uint32_t>(ODK_MAJOR_VERSION)));
|
||||
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreLicenseResponse(
|
||||
core_response_, core_request_, request_hash_string,
|
||||
features, core_response_, core_request_, request_hash_string,
|
||||
&serialized_core_message_));
|
||||
// Resize serialize core message to be just big enough or required core
|
||||
// message size, whichever is larger.
|
||||
@@ -983,6 +1022,17 @@ void EntitledMessage::SetEntitlementKeyId(unsigned int index,
|
||||
entitled_key_data_[index].entitlement_key_id, key_id.length());
|
||||
}
|
||||
|
||||
void EntitledMessage::SetContentKeyId(unsigned int index,
|
||||
const std::string& key_id) {
|
||||
ASSERT_LT(index, num_keys_);
|
||||
ASSERT_LE(key_id.size(), kTestKeyIdMaxLength);
|
||||
entitled_key_data_[index].content_key_id_length = key_id.size();
|
||||
memcpy(entitled_key_data_[index].content_key_id,
|
||||
reinterpret_cast<const uint8_t*>(key_id.c_str()), key_id.length());
|
||||
entitled_key_array_[index].content_key_id =
|
||||
FindSubstring(entitled_key_data_[index].content_key_id, key_id.length());
|
||||
}
|
||||
|
||||
OEMCrypto_Substring EntitledMessage::FindSubstring(const void* ptr,
|
||||
size_t size) {
|
||||
OEMCrypto_Substring substring{0, 0};
|
||||
@@ -998,7 +1048,7 @@ void EntitledMessage::LoadKeys(OEMCryptoResult expected_sts) {
|
||||
EncryptContentKey();
|
||||
ASSERT_EQ(expected_sts,
|
||||
OEMCrypto_LoadEntitledContentKeys(
|
||||
license_messages_->session()->session_id(),
|
||||
entitled_key_session_,
|
||||
reinterpret_cast<const uint8_t*>(entitled_key_data_),
|
||||
sizeof(entitled_key_data_), num_keys_, entitled_key_array_));
|
||||
if (expected_sts != OEMCrypto_SUCCESS) {
|
||||
@@ -1009,14 +1059,14 @@ void EntitledMessage::LoadKeys(OEMCryptoResult expected_sts) {
|
||||
}
|
||||
|
||||
OEMCryptoResult EntitledMessage::LoadKeys(const vector<uint8_t>& message) {
|
||||
return OEMCrypto_LoadEntitledContentKeys(
|
||||
license_messages_->session()->session_id(), message.data(),
|
||||
message.size(), num_keys_, entitled_key_array_);
|
||||
return OEMCrypto_LoadEntitledContentKeys(entitled_key_session_,
|
||||
message.data(), message.size(),
|
||||
num_keys_, entitled_key_array_);
|
||||
}
|
||||
|
||||
OEMCryptoResult EntitledMessage::LoadKeys() {
|
||||
return OEMCrypto_LoadEntitledContentKeys(
|
||||
license_messages_->session()->session_id(),
|
||||
entitled_key_session_,
|
||||
reinterpret_cast<const uint8_t*>(entitled_key_data_),
|
||||
sizeof(entitled_key_data_), num_keys_, entitled_key_array_);
|
||||
}
|
||||
@@ -1045,10 +1095,69 @@ void EntitledMessage::EncryptContentKey() {
|
||||
// Corpus for load entitled keys fuzzer should be in the format:
|
||||
// message buffer to be verified | entitled content key object array.
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(entitled_key_data_),
|
||||
sizeof(entitled_key_data_));
|
||||
num_keys_ * sizeof(EntitledContentKeyData));
|
||||
AppendSeparator(file_name);
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(entitled_key_array_),
|
||||
num_keys_);
|
||||
num_keys_ * sizeof(OEMCrypto_EntitledContentKeyObject));
|
||||
}
|
||||
}
|
||||
|
||||
void EntitledMessage::LoadCasKeys(bool load_even, bool load_odd,
|
||||
OEMCryptoResult expected_sts) {
|
||||
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_EntitledContentKeyObject even_key;
|
||||
OEMCrypto_EntitledContentKeyObject 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;
|
||||
}
|
||||
|
||||
OEMCryptoResult sts = OEMCrypto_LoadCasECMKeys(
|
||||
entitled_key_session_,
|
||||
reinterpret_cast<const uint8_t*>(entitled_key_data_),
|
||||
sizeof(entitled_key_data_), has_even ? &even_key : nullptr,
|
||||
has_odd ? &odd_key : nullptr);
|
||||
ASSERT_EQ(expected_sts, sts);
|
||||
if (expected_sts != OEMCrypto_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_even) {
|
||||
VerifyEntitlementTestKey(0);
|
||||
}
|
||||
if (has_odd) {
|
||||
VerifyEntitlementTestKey(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,48 +1167,51 @@ void EntitledMessage::EncryptContentKey() {
|
||||
// control block.
|
||||
void EntitledMessage::VerifyKCBs() {
|
||||
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(
|
||||
license_messages_->session()->session_id(), 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(entitled_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;
|
||||
}
|
||||
}
|
||||
|
||||
void EntitledMessage::VerifyDecrypt() {
|
||||
const OEMCrypto_SESSION session_id =
|
||||
license_messages_->session()->session_id();
|
||||
|
||||
// Loop through all the keys and try decrypt with each one.
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
const EntitledContentKeyData* const key_data = &entitled_key_data_[i];
|
||||
|
||||
OEMCryptoResult result = OEMCrypto_SelectKey(
|
||||
session_id, key_data->content_key_id, key_data->content_key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
entitled_key_session_, key_data->content_key_id,
|
||||
key_data->content_key_id_length, OEMCrypto_CipherMode_CENC);
|
||||
ASSERT_EQ(result, OEMCrypto_SUCCESS) << "For key " << i;
|
||||
|
||||
vector<uint8_t> expected_data;
|
||||
vector<uint8_t> actual_data;
|
||||
result = DecryptCTR(session_id, key_data->content_key_data, &expected_data,
|
||||
&actual_data);
|
||||
result = DecryptCTR(entitled_key_session_, key_data->content_key_data,
|
||||
&expected_data, &actual_data);
|
||||
EXPECT_EQ(result, OEMCrypto_SUCCESS) << "For key " << i;
|
||||
EXPECT_EQ(actual_data, expected_data) << "For key " << i;
|
||||
}
|
||||
@@ -1133,7 +1245,7 @@ void RenewalRoundTrip::FillAndVerifyCoreRequest(
|
||||
EXPECT_TRUE(
|
||||
oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage(
|
||||
core_message_string, &core_request_));
|
||||
EXPECT_EQ(license_messages_->core_request().api_major_version,
|
||||
EXPECT_EQ(license_messages_->api_version(),
|
||||
core_request_.api_major_version);
|
||||
EXPECT_EQ(license_messages_->core_request().nonce, core_request_.nonce);
|
||||
EXPECT_EQ(license_messages_->core_request().session_id,
|
||||
@@ -1184,8 +1296,14 @@ void RenewalRoundTrip::EncryptAndSignResponse() {
|
||||
sizeof(response_data_.keys[0].control));
|
||||
serialized_core_message_.resize(0);
|
||||
} else {
|
||||
// TODO(b/191724203): Test renewal server has different version from license
|
||||
// server.
|
||||
ASSERT_NE(license_messages_, nullptr);
|
||||
CoreMessageFeatures features =
|
||||
CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
|
||||
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreRenewalResponse(
|
||||
core_request_, renewal_duration_seconds_, &serialized_core_message_));
|
||||
features, core_request_, renewal_duration_seconds_,
|
||||
&serialized_core_message_));
|
||||
// Resize serialize core message to be just big enough or required core
|
||||
// message size, whichever is larger.
|
||||
serialized_core_message_.resize(
|
||||
@@ -1218,15 +1336,20 @@ void RenewalRoundTrip::EncryptAndSignResponse() {
|
||||
void RenewalRoundTrip::InjectFuzzedResponseData(
|
||||
OEMCrypto_Renewal_Response_Fuzz& fuzzed_data,
|
||||
const uint8_t* renewal_response, const size_t renewal_response_size) {
|
||||
// TODO(b/191724203): Test renewal server has different version from license
|
||||
// server.
|
||||
ASSERT_NE(license_messages_, nullptr);
|
||||
CoreMessageFeatures features =
|
||||
CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
|
||||
// Serializing core message.
|
||||
// This call also sets nonce in core response to match with session nonce.
|
||||
oemcrypto_core_message::serialize::CreateCoreRenewalResponse(
|
||||
fuzzed_data.core_request, fuzzed_data.renewal_duration_seconds,
|
||||
features, fuzzed_data.core_request, fuzzed_data.renewal_duration_seconds,
|
||||
&serialized_core_message_);
|
||||
|
||||
// Copy serialized core message and encrypted response from data and
|
||||
// calculate signature. Now we will have a valid signature for data generated
|
||||
// by fuzzer.
|
||||
// calculate signature. Now we will have a valid signature for data
|
||||
// generated by fuzzer.
|
||||
encrypted_response_.assign(serialized_core_message_.begin(),
|
||||
serialized_core_message_.end());
|
||||
encrypted_response_.insert(encrypted_response_.end(), renewal_response,
|
||||
@@ -1310,7 +1433,7 @@ void Session::GenerateNonce(int* error_counter) {
|
||||
if (error_counter) {
|
||||
(*error_counter)++;
|
||||
} else {
|
||||
wvcdm::TestSleep::Sleep(1); // wait a second, then try again.
|
||||
wvutil::TestSleep::Sleep(1); // wait a second, then try again.
|
||||
// The following is after a 1 second pause, so it cannot be from a nonce
|
||||
// flood.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
@@ -1325,13 +1448,13 @@ void Session::FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
* from a license request message.
|
||||
* They are used to test MAC and ENC key generation.
|
||||
*/
|
||||
*mac_context = wvcdm::a2b_hex(
|
||||
*mac_context = wvutil::a2b_hex(
|
||||
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
|
||||
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
|
||||
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
|
||||
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
|
||||
"34333231180120002a0c31383836373837343035000000000200");
|
||||
*enc_context = wvcdm::a2b_hex(
|
||||
*enc_context = wvutil::a2b_hex(
|
||||
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
|
||||
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
|
||||
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
|
||||
@@ -1382,7 +1505,7 @@ void Session::TestDecryptCTR(bool select_key_first,
|
||||
// Select the key (from FillSimpleMessage)
|
||||
select_result = OEMCrypto_SelectKey(
|
||||
session_id(), license_.keys[key_index].key_id,
|
||||
license_.keys[key_index].key_id_length, OEMCrypto_CipherMode_CTR);
|
||||
license_.keys[key_index].key_id_length, OEMCrypto_CipherMode_CENC);
|
||||
}
|
||||
|
||||
vector<uint8_t> unencrypted_data;
|
||||
@@ -1440,7 +1563,7 @@ void Session::TestSelectExpired(size_t key_index) {
|
||||
if (global_features.api_version >= 13) {
|
||||
OEMCryptoResult status = OEMCrypto_SelectKey(
|
||||
session_id(), license().keys[key_index].key_id,
|
||||
license().keys[key_index].key_id_length, OEMCrypto_CipherMode_CTR);
|
||||
license().keys[key_index].key_id_length, OEMCrypto_CipherMode_CENC);
|
||||
// It is OK for SelectKey to succeed with an expired key, but if there is
|
||||
// an error, it must be OEMCrypto_ERROR_KEY_EXIRED.
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
@@ -1554,6 +1677,58 @@ void Session::PreparePublicKey(const uint8_t* rsa_key, size_t rsa_key_length) {
|
||||
}
|
||||
}
|
||||
|
||||
void Session::SetRsaPublicKey(const uint8_t* buffer, size_t length) {
|
||||
if (public_rsa_) {
|
||||
RSA_free(public_rsa_);
|
||||
public_rsa_ = nullptr;
|
||||
}
|
||||
if (public_ec_) {
|
||||
EC_KEY_free(public_ec_);
|
||||
public_ec_ = nullptr;
|
||||
}
|
||||
public_rsa_ = d2i_RSA_PUBKEY(nullptr, &buffer, length);
|
||||
if (!public_rsa_) {
|
||||
cout << "d2i_RSAPrivateKey failed. ";
|
||||
dump_boringssl_error();
|
||||
FAIL() << "Could not parse public RSA key.";
|
||||
}
|
||||
switch (RSA_check_key(public_rsa_)) {
|
||||
case 1: // valid.
|
||||
return;
|
||||
case 0: // not valid.
|
||||
dump_boringssl_error();
|
||||
FAIL() << "[rsa key not valid] ";
|
||||
default: // -1 == check failed.
|
||||
dump_boringssl_error();
|
||||
FAIL() << "[error checking rsa key] ";
|
||||
}
|
||||
}
|
||||
|
||||
void Session::SetEcPublicKey(const uint8_t* buffer, size_t length) {
|
||||
if (public_rsa_) {
|
||||
RSA_free(public_rsa_);
|
||||
public_rsa_ = nullptr;
|
||||
}
|
||||
if (public_ec_) {
|
||||
EC_KEY_free(public_ec_);
|
||||
public_ec_ = nullptr;
|
||||
}
|
||||
public_ec_ = d2i_EC_PUBKEY(nullptr, &buffer, length);
|
||||
if (!public_ec_) {
|
||||
cout << "d2i_RSAPrivateKey failed. ";
|
||||
dump_boringssl_error();
|
||||
FAIL() << "Could not parse public RSA key.";
|
||||
}
|
||||
switch (EC_KEY_check_key(public_ec_)) {
|
||||
case 1: // valid.
|
||||
return;
|
||||
case 0: // not valid.
|
||||
default:
|
||||
dump_boringssl_error();
|
||||
FAIL() << "[ec key not valid] ";
|
||||
}
|
||||
}
|
||||
|
||||
bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
@@ -1643,7 +1818,7 @@ bool Session::GenerateRSASessionKey(vector<uint8_t>* session_key,
|
||||
cerr << "No public RSA key loaded in test code.\n";
|
||||
return false;
|
||||
}
|
||||
*session_key = wvcdm::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
|
||||
*session_key = wvutil::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
|
||||
enc_session_key->assign(RSA_size(public_rsa_), 0);
|
||||
int status = RSA_public_encrypt(
|
||||
static_cast<int>(session_key->size()), &(session_key->front()),
|
||||
@@ -1692,8 +1867,6 @@ void Session::UpdateUsageEntry(std::vector<uint8_t>* header_buffer) {
|
||||
}
|
||||
|
||||
void Session::LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer) {
|
||||
usage_entry_number_ = index;
|
||||
encrypted_usage_entry_ = buffer;
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadUsageEntry(session_id(), index, buffer.data(),
|
||||
buffer.size()));
|
||||
@@ -1735,7 +1908,7 @@ void Session::GenerateReport(const std::string& pst,
|
||||
if (expected_result != OEMCrypto_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
EXPECT_EQ(wvcdm::Unpacked_PST_Report::report_size(pst.length()), length);
|
||||
EXPECT_EQ(wvutil::Unpacked_PST_Report::report_size(pst.length()), length);
|
||||
vector<uint8_t> computed_signature(SHA_DIGEST_LENGTH);
|
||||
key_deriver_.ClientSignPstReport(pst_report_buffer_, &computed_signature);
|
||||
EXPECT_EQ(0, memcmp(computed_signature.data(), pst_report().signature(),
|
||||
@@ -1747,12 +1920,12 @@ void Session::GenerateReport(const std::string& pst,
|
||||
}
|
||||
|
||||
void Session::VerifyPST(const Test_PST_Report& expected) {
|
||||
wvcdm::Unpacked_PST_Report computed = pst_report();
|
||||
wvutil::Unpacked_PST_Report computed = pst_report();
|
||||
EXPECT_EQ(expected.status, computed.status());
|
||||
char* pst_ptr = reinterpret_cast<char*>(computed.pst());
|
||||
std::string computed_pst(pst_ptr, pst_ptr + computed.pst_length());
|
||||
ASSERT_EQ(expected.pst, computed_pst);
|
||||
int64_t now = wvcdm::Clock().GetCurrentTime();
|
||||
int64_t now = wvutil::Clock().GetCurrentTime();
|
||||
int64_t age = now - expected.time_created; // How old is this report.
|
||||
EXPECT_NEAR(expected.seconds_since_license_received + age,
|
||||
computed.seconds_since_license_received(), kTimeTolerance);
|
||||
@@ -1775,7 +1948,7 @@ void Session::VerifyReport(Test_PST_Report expected,
|
||||
int64_t time_license_received,
|
||||
int64_t time_first_decrypt,
|
||||
int64_t time_last_decrypt) {
|
||||
const int64_t now = wvcdm::Clock().GetCurrentTime();
|
||||
const int64_t now = wvutil::Clock().GetCurrentTime();
|
||||
expected.seconds_since_license_received =
|
||||
(time_license_received > 0 && time_license_received < now)
|
||||
? now - time_license_received
|
||||
@@ -1820,10 +1993,11 @@ void WriteRequestApiCorpus(size_t signature_length, size_t core_message_length,
|
||||
}
|
||||
// Corpus for request APIs should be signature_length + core_message_length +
|
||||
// data pointer.
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(&signature_length),
|
||||
sizeof(signature_length));
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(&core_message_length),
|
||||
sizeof(core_message_length));
|
||||
OEMCrypto_Request_Fuzz request_fuzz_struct;
|
||||
request_fuzz_struct.core_message_length = core_message_length;
|
||||
request_fuzz_struct.signature_length = signature_length;
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(&request_fuzz_struct),
|
||||
sizeof(OEMCrypto_Request_Fuzz));
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(data.data()),
|
||||
data.size());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user