Merge latest oemcrypto-v17 change

No-Typo-Check: Not related to this change.

Bug: 161477208
Change-Id: I99e4780f6855b7045aa0cd5a49c13d2d0d51ed64
This commit is contained in:
Kyle Zhang
2022-01-21 05:58:12 +00:00
committed by Fred Gylys-Colwell
parent c924960962
commit 642965c678
176 changed files with 301013 additions and 296749 deletions

View File

@@ -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());
}