Revert "Merge latest oemcrypto-v17 change"

This reverts commit 642965c678.

Reason for revert: Droidfood Blocking Bug: 217145027

Change-Id: I669b72fcd91c62e28883b5f55eb36af274d85806
(cherry picked from commit 8dbea15e5da05b371572297041454569dc166c90)
Merged-In:I669b72fcd91c62e28883b5f55eb36af274d85806
This commit is contained in:
Daniel Chapin
2022-01-31 19:21:18 +00:00
committed by Android Build Coastguard Worker
parent 860a48ff8c
commit 5558e492c9
176 changed files with 296842 additions and 301106 deletions

View File

@@ -1,16 +1,4 @@
#!/bin/bash
echo "XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX"
echo "XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX"
echo "TODO(b/192560463): The OPK does not build because it expects an"
echo "older version of the ODK library. The ipc_ref tests do not work because"
echo "the reference code is v17 but OPK is v16."
# Also, if you are fixing this script, it should probably be moved to the jenkins
# directory, so that it is next to all the other scripts that Luci runs.
echo "XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX"
echo "XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX---XXX"
exit 0
set -ex
export CXX=clang++
@@ -28,4 +16,4 @@ python3 $PATH_TO_CDM_DIR/third_party/gyp/__init__.py --format=ninja \
--depth=$(pwd) \
--include=oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gypi \
oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gyp
ninja -C out/Default
ninja -C out/Default

View File

@@ -1,94 +0,0 @@
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "OEMCryptoCENC.h"
#include "log.h"
#include "oemcrypto_fuzz_helper.h"
#include "oemcrypto_fuzz_structs.h"
namespace wvoec {
// Free dynamic memory allocated by fuzzer script.
void FreeOutputBuffers(OEMCrypto_SESSION session_id,
OEMCrypto_DestBufferDesc& output_descriptor,
int* secure_fd) {
switch (output_descriptor.type) {
case OEMCrypto_BufferType_Clear: {
delete[] output_descriptor.buffer.clear.address;
break;
}
case OEMCrypto_BufferType_Secure: {
OEMCrypto_FreeSecureBuffer(session_id, &output_descriptor, *secure_fd);
break;
}
case OEMCrypto_BufferType_Direct: {
break;
}
}
}
bool InitializeOutputBuffers(OEMCrypto_SESSION session_id,
OEMCrypto_DestBufferDesc& output_descriptor,
int* secure_fd, size_t input_buffer_size) {
switch (output_descriptor.type) {
case OEMCrypto_BufferType_Clear: {
output_descriptor.buffer.clear.address =
new OEMCrypto_SharedMemory[input_buffer_size];
return true;
}
case OEMCrypto_BufferType_Secure: {
OEMCryptoResult sts = OEMCrypto_AllocateSecureBuffer(
session_id, input_buffer_size, &output_descriptor, secure_fd);
return sts == OEMCrypto_SUCCESS;
}
case OEMCrypto_BufferType_Direct: {
return true;
}
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Redirect printf and log statements from oemcrypto functions to a file to
// reduce noise
RedirectStdoutToFile();
uint8_t subsample_flags;
// OEMCrypto_DestBufferDesc and a buffer from which data needs to be copied
// are expected as inputs to copy buffer API.
// Input fuzzed data is interpreted as
// (OEMCrypto_DestBufferDesc | subsample_flags | input_buffer)
if (size <= sizeof(OEMCrypto_Copy_Buffer_Fuzz)) {
return 0;
}
OEMCrypto_Copy_Buffer_Fuzz fuzzed_structure;
// Fuzz dest_buffer_desc.
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
ConvertDataToValidEnum(OEMCrypto_BufferType_MaxValue,
&fuzzed_structure.dest_buffer_desc.type);
OEMCryptoLicenseAPIFuzz license_api_fuzz;
Session* session = license_api_fuzz.session();
// Fuzz input buffer to be copied.
size_t input_buffer_size = size - sizeof(fuzzed_structure);
int secure_fd = 0;
// Create output buffer pointers. If secure buffer is not supported, we
// explicitly convert to clear buffer and fuzz.
if (!InitializeOutputBuffers(session->session_id(),
fuzzed_structure.dest_buffer_desc, &secure_fd,
input_buffer_size)) {
LOGI(
"[OEMCrypto decrypt CENC fuzz] Secure buffers are not supported. Use "
"clear buffer instead.");
fuzzed_structure.dest_buffer_desc.type = OEMCrypto_BufferType_Clear;
InitializeOutputBuffers(session->session_id(),
fuzzed_structure.dest_buffer_desc, &secure_fd,
input_buffer_size);
}
OEMCrypto_CopyBuffer(session->session_id(), data + sizeof(fuzzed_structure),
input_buffer_size, &fuzzed_structure.dest_buffer_desc,
subsample_flags);
FreeOutputBuffers(session->session_id(), fuzzed_structure.dest_buffer_desc,
&secure_fd);
return 0;
}
} // namespace wvoec

View File

@@ -20,7 +20,7 @@ void FreeOutputBuffers(OEMCrypto_SESSION session_id,
sample_description[i].buffers.output_descriptor;
switch (fuzzed_output_descriptor.type) {
case OEMCrypto_BufferType_Clear: {
delete[] fuzzed_output_descriptor.buffer.clear.clear_buffer;
delete[] fuzzed_output_descriptor.buffer.clear.address;
break;
}
case OEMCrypto_BufferType_Secure: {
@@ -44,10 +44,9 @@ bool InitializeOutputBuffers(OEMCrypto_SESSION session_id,
vector<int>& secure_fd_array) {
switch (output_descriptor.type) {
case OEMCrypto_BufferType_Clear: {
output_descriptor.buffer.clear.clear_buffer =
new OEMCrypto_SharedMemory[std::min(
MAX_FUZZ_SAMPLE_SIZE,
output_descriptor.buffer.clear.clear_buffer_length)];
output_descriptor.buffer.clear
.address = new OEMCrypto_SharedMemory[std::min(
MAX_FUZZ_SAMPLE_SIZE, output_descriptor.buffer.clear.address_length)];
return true;
}
case OEMCrypto_BufferType_Secure: {
@@ -55,7 +54,7 @@ bool InitializeOutputBuffers(OEMCrypto_SESSION session_id,
OEMCryptoResult sts = OEMCrypto_AllocateSecureBuffer(
session_id,
std::min(MAX_FUZZ_SAMPLE_SIZE,
output_descriptor.buffer.secure.secure_buffer_length),
output_descriptor.buffer.secure.handle_length),
&output_descriptor, secure_fd);
if (sts == OEMCrypto_SUCCESS) secure_fd_array[sample_index] = *secure_fd;
return sts == OEMCrypto_SUCCESS;

View File

@@ -68,14 +68,6 @@ struct OEMCrypto_Generate_RSA_Signature_Fuzz {
// input buffer data is of variable length and not included in
// this structure.
};
struct OEMCrypto_Copy_Buffer_Fuzz {
// Corpus format is as below.
// dest_buffer_desc + subsample_flags + input buffer
OEMCrypto_DestBufferDesc dest_buffer_desc;
uint8_t subsample_flags;
// Input buffer of variable length is not included in this structure.
};
} // namespace wvoec
#endif // OEMCRYPTO_FUZZ_STRUCTS_H_

View File

@@ -10,7 +10,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (!is_init) {
wvoec::global_features.Initialize();
wvoec::global_features.RestrictFilter("*");
wvutil::Properties::Init();
wvcdm::Properties::Init();
is_init = true;
}

View File

@@ -16,8 +16,8 @@ namespace {
void advance_dest_buffer(OEMCrypto_DestBufferDesc* dest_buffer, size_t bytes) {
switch (dest_buffer->type) {
case OEMCrypto_BufferType_Clear:
dest_buffer->buffer.clear.clear_buffer += bytes;
dest_buffer->buffer.clear.clear_buffer_length -= bytes;
dest_buffer->buffer.clear.address += bytes;
dest_buffer->buffer.clear.address_length -= bytes;
break;
case OEMCrypto_BufferType_Secure:
@@ -37,7 +37,7 @@ void advance_iv_ctr(uint8_t (*subsample_iv)[wvoec::KEY_IV_SIZE], size_t bytes) {
const size_t increment =
bytes / wvoec::AES_128_BLOCK_SIZE; // The truncation here is intentional
counter = wvutil::htonll64(wvutil::ntohll64(counter) + increment);
counter = wvcdm::htonll64(wvcdm::ntohll64(counter) + increment);
memcpy(&(*subsample_iv)[half_iv_size], &counter, half_iv_size);
}
@@ -104,7 +104,7 @@ OEMCryptoResult DecryptFallbackChain::DecryptSample(
fake_sample.buffers.input_data += length;
advance_dest_buffer(&fake_sample.buffers.output_descriptor, length);
if (cipher_mode == OEMCrypto_CipherMode_CENC) {
if (cipher_mode == OEMCrypto_CipherMode_CTR) {
advance_iv_ctr(&fake_sample.iv,
subsample.block_offset + subsample.num_bytes_encrypted);
}

View File

@@ -48,8 +48,7 @@ void DeviceFeatures::Initialize() {
// If the device uses a keybox, check to see if loading a certificate is
// installed.
if (provisioning_method == OEMCrypto_Keybox ||
provisioning_method == OEMCrypto_OEMCertificate ||
provisioning_method == OEMCrypto_BootCertificateChain) {
provisioning_method == OEMCrypto_OEMCertificate) {
// Devices with a keybox or OEM Certificate are required to support loading
// a DRM certificate.
loads_certificate = true;
@@ -82,8 +81,8 @@ void DeviceFeatures::Initialize() {
}
printf("cast_receiver = %s.\n", cast_receiver ? "true" : "false");
resource_rating = OEMCrypto_ResourceRatingTier();
printf("resource_rating = %u, security level %u.\n", resource_rating,
static_cast<unsigned int>(OEMCrypto_SecurityLevel()));
printf("resource_rating = %u, security level %s.\n", resource_rating,
OEMCrypto_SecurityLevel());
uint32_t decrypt_hash_type = OEMCrypto_SupportsDecryptHash();
supports_crc = (decrypt_hash_type == OEMCrypto_CRC_Clear_Buffer);
if (supports_crc) {
@@ -110,17 +109,13 @@ void DeviceFeatures::Initialize() {
printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n");
break;
case TEST_PROVISION_30:
printf("TEST_PROVISION_30: Device provisioned with OEM Cert.\n");
break;
case TEST_PROVISION_40:
printf("TEST_PROVISION_40: Device has boot certificate chain.\n");
printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n");
break;
}
OEMCrypto_Security_Level security_level = OEMCrypto_SecurityLevel();
supports_level_1 = (security_level == OEMCrypto_Level1);
printf("SecurityLevel is %s (L%u)\n",
supports_level_1 ? "Level 1" : "Not Level 1",
static_cast<unsigned int>(security_level));
std::string security_level = OEMCrypto_SecurityLevel();
supports_level_1 = (security_level == "L1");
printf("SecurityLevel is %s (%s)\n",
supports_level_1 ? "Level 1" : "Not Level 1", security_level.c_str());
CheckSecureBuffers();
OEMCrypto_Terminate();
initialized_ = true;
@@ -130,18 +125,14 @@ std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
std::string filter = initial_filter;
// clang-format off
if (!uses_keybox) FilterOut(&filter, "*KeyboxTest*");
// TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for
// provisioning 4. Disabled here temporarily.
if (!loads_certificate ||
provisioning_method == OEMCrypto_BootCertificateChain)
FilterOut(&filter, "OEMCryptoLoadsCert*");
if (!loads_certificate) FilterOut(&filter, "OEMCryptoLoadsCert*");
if (!generic_crypto) FilterOut(&filter, "*GenericCrypto*");
if (!cast_receiver) FilterOut(&filter, "*CastReceiver*");
if (!usage_table) FilterOut(&filter, "*UsageTable*");
if (!usage_table) FilterOut(&filter, "*BadRange_pst*");
if (derive_key_method == NO_METHOD) FilterOut(&filter, "*SessionTest*");
if (provisioning_method
!= OEMCrypto_OEMCertificate) FilterOut(&filter, "*Prov30*");
if (provisioning_method != OEMCrypto_BootCertificateChain)
FilterOut(&filter, "*Prov40*");
if (!supports_rsa_3072) FilterOut(&filter, "*RSAKey3072*");
if (api_version < 9) FilterOut(&filter, "*API09*");
if (api_version < 10) FilterOut(&filter, "*API10*");
@@ -151,11 +142,10 @@ std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
if (api_version < 14) FilterOut(&filter, "*API14*");
if (api_version < 15) FilterOut(&filter, "*API15*");
if (api_version < 16) FilterOut(&filter, "*API16*");
if (api_version < 17) FilterOut(&filter, "*API17*");
// clang-format on
// Some tests may require root access. If user is not root, filter these tests
// out.
if (!wvutil::TestSleep::CanChangeSystemTime()) {
if (!wvcdm::TestSleep::CanChangeSystemTime()) {
printf("Filtering out TimeRollbackPrevention.\n");
FilterOut(&filter, "*TimeRollbackPrevention*");
} else {
@@ -183,9 +173,6 @@ void DeviceFeatures::PickDerivedKey() {
case OEMCrypto_Keybox:
// Fall through to api_version < 12 case.
break;
case OEMCrypto_BootCertificateChain:
derive_key_method = TEST_PROVISION_40;
return;
case OEMCrypto_ProvisioningError:
printf(
"ERROR: OEMCrypto_GetProvisioningMethod() returns "
@@ -265,8 +252,6 @@ const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method) {
return "OEMCrypto_Keybox";
case OEMCrypto_OEMCertificate:
return "OEMCrypto_OEMCertificate";
case OEMCrypto_BootCertificateChain:
return "OEMCrypto_BootCertificateChain";
}
// Not reachable
return "";

View File

@@ -10,12 +10,9 @@
namespace wvoec {
// These tests are designed to work for this version:
constexpr unsigned int kCurrentAPI = 17;
constexpr unsigned int kCurrentAPI = 16;
// The API version when Core Messages were introduced.
constexpr unsigned int kCoreMessagesAPI = 16;
// The API version when we stopped encrypting key control blocks.
constexpr unsigned int kClearControlBlockAPIMajor = 16;
constexpr unsigned int kClearControlBlockAPIMinor = 5;
// An output type for testing. The type field is secure, clear, or direct. If
// the type is clear, then decrypt_inplace could be true. Otherwise,
@@ -32,24 +29,23 @@ class DeviceFeatures {
// There are several possible methods used to derive a set of known session
// keys. For example, the test can install a known test keybox, or it can
// parse the OEM certificate.
enum DeriveMethod { // Method to use derive session keys.
NO_METHOD, // Cannot derive known session keys.
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
LOAD_TEST_RSA_KEY, // Call LoadTestRSAKey before deriving keys.
TEST_PROVISION_30, // Device has OEM Certificate installed.
TEST_PROVISION_40, // Device has Boot Certificate Chain installed.
enum DeriveMethod { // Method to use derive session keys.
NO_METHOD, // Cannot derive known session keys.
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
LOAD_TEST_RSA_KEY, // Call LoadTestRSAKey before deriving keys.
TEST_PROVISION_30, // Device has OEM Certificate installed.
};
enum DeriveMethod derive_key_method;
bool uses_keybox; // Device uses a keybox to derive session keys.
bool loads_certificate; // Device can load a certificate from the server.
bool generic_crypto; // Device supports generic crypto.
bool cast_receiver; // Device supports alternate rsa signature padding.
bool usage_table; // Device saves usage information.
bool supports_rsa_3072; // Device supports 3072 bit RSA keys.
bool supports_level_1; // Device supports Level 1 security.
uint32_t resource_rating; // Device's resource rating tier.
bool supports_crc; // Supported decrypt hash type CRC.
bool uses_keybox; // Device uses a keybox to derive session keys.
bool loads_certificate; // Device can load a certificate from the server.
bool generic_crypto; // Device supports generic crypto.
bool cast_receiver; // Device supports alternate rsa signature padding.
bool usage_table; // Device saves usage information.
bool supports_rsa_3072; // Device supports 3072 bit RSA keys.
bool supports_level_1; // Device supports Level 1 security.
uint32_t resource_rating; // Device's resource rating tier.
bool supports_crc; // Supported decrypt hash type CRC.
bool test_secure_buffers; // If we can create a secure buffer for testing.
uint32_t api_version;
OEMCrypto_ProvisioningMethod provisioning_method;

View File

@@ -5,7 +5,7 @@
// OEMCrypto unit tests
//
#include "oec_key_deriver.h"
#include "oec_session_util.h"
#include <openssl/aes.h>
#include <openssl/bio.h>
@@ -58,7 +58,7 @@ void Encryptor::CBCEncrypt(const uint8_t* data, uint8_t* encrypted_data,
void Encryptor::PadAndEncryptProvisioningMessage(
RSAPrivateKeyMessage* data, RSAPrivateKeyMessage* encrypted) const {
EXPECT_EQ(1, RAND_bytes(data->rsa_key_iv, KEY_IV_SIZE));
EXPECT_EQ(1, GetRandBytes(data->rsa_key_iv, KEY_IV_SIZE));
ASSERT_EQ(enc_key_.size(), KEY_SIZE);
*encrypted = *data;
if (data->rsa_key_length > sizeof(data->rsa_key)) {

View File

@@ -7,7 +7,6 @@
#include "oec_session_util.h"
#include <gtest/gtest.h>
#include <openssl/aes.h>
#include <openssl/bio.h>
#include <openssl/cmac.h>
@@ -19,6 +18,7 @@
#include <openssl/x509_vfy.h>
#include <stdint.h>
#include <gtest/gtest.h>
#include <algorithm>
#include <iostream>
#include <memory>
@@ -28,7 +28,6 @@
#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"
@@ -48,13 +47,13 @@ using namespace std;
// which is std::vector in this case.
namespace std {
void PrintTo(const vector<uint8_t>& value, ostream* os) {
*os << wvutil::b2a_hex(value);
*os << wvcdm::b2a_hex(value);
}
} // namespace std
namespace wvoec {
namespace {
using oemcrypto_core_message::features::CoreMessageFeatures;
constexpr size_t kTestSubsampleSectionSize = 256;
@@ -144,8 +143,8 @@ void GenerateSimpleSampleDescription(
OEMCrypto_DestBufferDesc& out_buffer_descriptor =
sample->buffers.output_descriptor;
out_buffer_descriptor.type = OEMCrypto_BufferType_Clear;
out_buffer_descriptor.buffer.clear.clear_buffer = out.data();
out_buffer_descriptor.buffer.clear.clear_buffer_length = out.size();
out_buffer_descriptor.buffer.clear.address = out.data();
out_buffer_descriptor.buffer.clear.address_length = out.size();
}
// Increment counter for AES-CTR. The CENC spec specifies we increment only
@@ -156,7 +155,7 @@ void ctr128_inc64(int64_t increaseBy, uint8_t* iv) {
ASSERT_NE(nullptr, iv);
uint64_t* counterBuffer = reinterpret_cast<uint64_t*>(&iv[8]);
(*counterBuffer) =
wvutil::htonll64(wvutil::ntohll64(*counterBuffer) + increaseBy);
wvcdm::htonll64(wvcdm::ntohll64(*counterBuffer) + increaseBy);
}
// Some compilers don't like the macro htonl within an ASSERT_EQ.
@@ -194,7 +193,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 = wvutil::Clock().GetCurrentTime();
time_created = wvcdm::Clock().GetCurrentTime();
}
template <class CoreRequest, PrepAndSignRequest_t PrepAndSignRequest,
@@ -207,9 +206,6 @@ 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);
@@ -300,15 +296,10 @@ 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);
@@ -400,12 +391,9 @@ 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(
features, core_response_, core_request_,
&serialized_core_message_));
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()));
@@ -549,24 +537,17 @@ 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(
@@ -576,13 +557,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-16.4 for OEMCrypto 16 public release, and v16.5
// for L3 release only.
// We support either 16.3 or 16.4 for OEMCrypto 16.
EXPECT_LE(3, core_request_.api_minor_version);
EXPECT_GE(5, core_request_.api_minor_version);
EXPECT_GE(4, core_request_.api_minor_version);
} else if (global_features.api_version == ODK_MAJOR_VERSION) {
// We do not expect older tests to work with a newer OEMCrypto.
EXPECT_GE(ODK_MINOR_VERSION, core_request_.api_minor_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);
}
if (expect_request_has_correct_nonce_) {
EXPECT_EQ(session()->nonce(), core_request_.nonce);
@@ -623,7 +604,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_CENC;
response_data_.keys[i].cipher_mode = OEMCrypto_CipherMode_CTR;
}
// Fill in the default core_response_ fields, except the substrings, which are
// filled in the next function.
@@ -778,20 +759,12 @@ 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);
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;
}
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);
session_->key_deriver().CBCEncrypt(
&response_data_.keys[i].key_data[0],
&encrypted_response_data_.keys[i].key_data[0],
@@ -802,22 +775,10 @@ 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(
features, core_response_, core_request_, request_hash_string,
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.
@@ -1022,17 +983,6 @@ 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};
@@ -1048,7 +998,7 @@ void EntitledMessage::LoadKeys(OEMCryptoResult expected_sts) {
EncryptContentKey();
ASSERT_EQ(expected_sts,
OEMCrypto_LoadEntitledContentKeys(
entitled_key_session_,
license_messages_->session()->session_id(),
reinterpret_cast<const uint8_t*>(entitled_key_data_),
sizeof(entitled_key_data_), num_keys_, entitled_key_array_));
if (expected_sts != OEMCrypto_SUCCESS) {
@@ -1059,14 +1009,14 @@ void EntitledMessage::LoadKeys(OEMCryptoResult expected_sts) {
}
OEMCryptoResult EntitledMessage::LoadKeys(const vector<uint8_t>& message) {
return OEMCrypto_LoadEntitledContentKeys(entitled_key_session_,
message.data(), message.size(),
num_keys_, entitled_key_array_);
return OEMCrypto_LoadEntitledContentKeys(
license_messages_->session()->session_id(), message.data(),
message.size(), num_keys_, entitled_key_array_);
}
OEMCryptoResult EntitledMessage::LoadKeys() {
return OEMCrypto_LoadEntitledContentKeys(
entitled_key_session_,
license_messages_->session()->session_id(),
reinterpret_cast<const uint8_t*>(entitled_key_data_),
sizeof(entitled_key_data_), num_keys_, entitled_key_array_);
}
@@ -1095,69 +1045,10 @@ 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_),
num_keys_ * sizeof(EntitledContentKeyData));
sizeof(entitled_key_data_));
AppendSeparator(file_name);
AppendToFile(file_name, reinterpret_cast<const char*>(entitled_key_array_),
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);
num_keys_);
}
}
@@ -1167,51 +1058,48 @@ void EntitledMessage::LoadCasKeys(bool load_even, bool load_odd,
// control block.
void EntitledMessage::VerifyKCBs() {
for (unsigned int i = 0; i < num_keys_; 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;
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;
}
}
}
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(
entitled_key_session_, key_data->content_key_id,
key_data->content_key_id_length, OEMCrypto_CipherMode_CENC);
session_id, key_data->content_key_id, key_data->content_key_id_length,
OEMCrypto_CipherMode_CTR);
ASSERT_EQ(result, OEMCrypto_SUCCESS) << "For key " << i;
vector<uint8_t> expected_data;
vector<uint8_t> actual_data;
result = DecryptCTR(entitled_key_session_, key_data->content_key_data,
&expected_data, &actual_data);
result = DecryptCTR(session_id, 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;
}
@@ -1245,7 +1133,7 @@ void RenewalRoundTrip::FillAndVerifyCoreRequest(
EXPECT_TRUE(
oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage(
core_message_string, &core_request_));
EXPECT_EQ(license_messages_->api_version(),
EXPECT_EQ(license_messages_->core_request().api_major_version,
core_request_.api_major_version);
EXPECT_EQ(license_messages_->core_request().nonce, core_request_.nonce);
EXPECT_EQ(license_messages_->core_request().session_id,
@@ -1296,14 +1184,8 @@ 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(
features, core_request_, renewal_duration_seconds_,
&serialized_core_message_));
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(
@@ -1336,20 +1218,15 @@ 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(
features, fuzzed_data.core_request, fuzzed_data.renewal_duration_seconds,
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,
@@ -1433,7 +1310,7 @@ void Session::GenerateNonce(int* error_counter) {
if (error_counter) {
(*error_counter)++;
} else {
wvutil::TestSleep::Sleep(1); // wait a second, then try again.
wvcdm::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,
@@ -1448,13 +1325,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 = wvutil::a2b_hex(
*mac_context = wvcdm::a2b_hex(
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
"34333231180120002a0c31383836373837343035000000000200");
*enc_context = wvutil::a2b_hex(
*enc_context = wvcdm::a2b_hex(
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
@@ -1505,7 +1382,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_CENC);
license_.keys[key_index].key_id_length, OEMCrypto_CipherMode_CTR);
}
vector<uint8_t> unencrypted_data;
@@ -1563,7 +1440,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_CENC);
license().keys[key_index].key_id_length, OEMCrypto_CipherMode_CTR);
// 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) {
@@ -1677,58 +1554,6 @@ 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,
@@ -1818,7 +1643,7 @@ bool Session::GenerateRSASessionKey(vector<uint8_t>* session_key,
cerr << "No public RSA key loaded in test code.\n";
return false;
}
*session_key = wvutil::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
*session_key = wvcdm::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()),
@@ -1867,6 +1692,8 @@ 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()));
@@ -1908,7 +1735,7 @@ void Session::GenerateReport(const std::string& pst,
if (expected_result != OEMCrypto_SUCCESS) {
return;
}
EXPECT_EQ(wvutil::Unpacked_PST_Report::report_size(pst.length()), length);
EXPECT_EQ(wvcdm::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(),
@@ -1920,12 +1747,12 @@ void Session::GenerateReport(const std::string& pst,
}
void Session::VerifyPST(const Test_PST_Report& expected) {
wvutil::Unpacked_PST_Report computed = pst_report();
wvcdm::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 = wvutil::Clock().GetCurrentTime();
int64_t now = wvcdm::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);
@@ -1948,7 +1775,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 = wvutil::Clock().GetCurrentTime();
const int64_t now = wvcdm::Clock().GetCurrentTime();
expected.seconds_since_license_received =
(time_license_received > 0 && time_license_received < now)
? now - time_license_received
@@ -1993,11 +1820,10 @@ void WriteRequestApiCorpus(size_t signature_length, size_t core_message_length,
}
// Corpus for request APIs should be signature_length + core_message_length +
// data pointer.
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*>(&signature_length),
sizeof(signature_length));
AppendToFile(file_name, reinterpret_cast<const char*>(&core_message_length),
sizeof(core_message_length));
AppendToFile(file_name, reinterpret_cast<const char*>(data.data()),
data.size());
}

View File

@@ -8,10 +8,8 @@
// OEMCrypto unit tests
//
#include <gtest/gtest.h>
#include <openssl/ec.h>
#include <openssl/rsa.h>
#include <time.h>
#include <string>
#include <vector>
@@ -56,6 +54,13 @@ constexpr int32_t kTimeTolerance = 3 * kSpeedMultiplier;
constexpr int64_t kUsageTableTimeTolerance = 10 * kSpeedMultiplier;
} // namespace
typedef struct {
uint8_t verification[4];
uint32_t duration;
uint32_t nonce;
uint32_t control_bits;
} KeyControlBlock;
// Note: The API does not specify a maximum key id length. We specify a
// maximum just for these tests, so that we have a fixed message size.
constexpr size_t kTestKeyIdMaxLength = 16;
@@ -213,9 +218,6 @@ class RoundTrip {
}
protected:
// Returns true if a nonce should be generated before signing the request.
virtual bool RequestHasNonce() = 0;
// ----------------------------------------------------------------------
// Specialized functionality for each message type.
@@ -279,7 +281,6 @@ class ProvisioningRoundTrip
void InjectFuzzedResponseData(const uint8_t* data, size_t size);
protected:
bool RequestHasNonce() override { return true; }
void VerifyRequestSignature(const vector<uint8_t>& data,
const vector<uint8_t>& generated_signature,
size_t core_message_length) override;
@@ -387,7 +388,6 @@ class LicenseRoundTrip
void SetKeyId(size_t index, const string& key_id);
protected:
bool RequestHasNonce() override { return true; }
void VerifyRequestSignature(const vector<uint8_t>& data,
const vector<uint8_t>& generated_signature,
size_t core_message_length) override;
@@ -451,7 +451,6 @@ class RenewalRoundTrip
void set_is_release(bool is_release) { is_release_ = is_release; }
protected:
bool RequestHasNonce() override { return false; }
void VerifyRequestSignature(const vector<uint8_t>& data,
const vector<uint8_t>& generated_signature,
size_t core_message_length) override;
@@ -470,26 +469,18 @@ class EntitledMessage {
: license_messages_(license_messages), num_keys_() {}
void FillKeyArray();
void MakeOneKey(size_t entitlement_key_index);
void SetEntitledKeySession(uint32_t key_session) {
entitled_key_session_ = key_session;
}
void LoadKeys(OEMCryptoResult expected_sts);
OEMCryptoResult LoadKeys(const vector<uint8_t>& message);
OEMCryptoResult LoadKeys();
void EncryptContentKey();
void LoadCasKeys(bool load_even, bool load_odd, OEMCryptoResult expected_sts);
void set_num_keys(uint32_t num_keys) { num_keys_ = num_keys; }
uint32_t num_keys() const { return num_keys_; }
void SetEntitlementKeyId(unsigned int index, const std::string& key_id);
void SetContentKeyId(unsigned int index, const std::string& key_id);
OEMCrypto_EntitledContentKeyObject* entitled_key_array();
// Returns entitled_key_data_ which is used as input message buffer to
// load entitled content keys API.
EntitledContentKeyData* entitled_key_data();
size_t entitled_key_data_size();
// Verify that key control blocks of the loaded keys.
void VerifyEntitlementTestKeys();
void VerifyEntitlementTestKey(size_t index);
private:
// Find the offset of the give pointer, relative to |entitled_key_data_|.
@@ -507,7 +498,6 @@ class EntitledMessage {
EntitledContentKeyData entitled_key_data_[kMaxNumKeys];
// Entitled key object. Pointers are backed by |entitled_key_data_|.
OEMCrypto_EntitledContentKeyObject entitled_key_array_[kMaxNumKeys];
uint32_t entitled_key_session_;
};
class Session {
@@ -518,8 +508,6 @@ class Session {
// Returns the most recently generated nonce.
// Valid after call to GenerateNonce.
uint32_t nonce() const { return nonce_; }
// The nonce can be overridden.
void set_nonce(uint32_t nonce) { nonce_ = nonce; }
// Valid after call to open().
uint32_t session_id() const { return (uint32_t)session_id_; }
// Call OEMCrypto_OpenSession, with GTest ASSERTs.
@@ -562,11 +550,6 @@ class Session {
// the default test key is loaded.
void PreparePublicKey(const uint8_t* rsa_key = nullptr,
size_t rsa_key_length = 0);
// Loads the specified RSA public key into public_rsa_.
void SetRsaPublicKey(const uint8_t* buffer, size_t length);
// Loads the specified EC public key into public_ec_.
void SetEcPublicKey(const uint8_t* buffer, size_t length);
// Verifies the given signature is from the given message and RSA key, pkey.
static bool VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
size_t message_length,
@@ -627,8 +610,8 @@ class Session {
string pst() const { return pst_; }
// Returns a pointer-like thing to the usage report generated by the previous
// call to GenerateReport.
wvutil::Unpacked_PST_Report pst_report() {
return wvutil::Unpacked_PST_Report(&pst_report_buffer_[0]);
wvcdm::Unpacked_PST_Report pst_report() {
return wvcdm::Unpacked_PST_Report(&pst_report_buffer_[0]);
}
// Verify the values in the PST report. The signature should have been
// verified in GenerateReport, above.
@@ -668,11 +651,9 @@ class Session {
OEMCrypto_SESSION session_id_;
KeyDeriver key_deriver_;
uint32_t nonce_;
// Only one of RSA or EC should be set.
RSA* public_rsa_ = nullptr;
EC_KEY* public_ec_ = nullptr;
RSA* public_rsa_;
vector<uint8_t> pst_report_buffer_;
MessageData license_ = {};
MessageData license_;
vector<uint8_t> encrypted_usage_entry_;
uint32_t usage_entry_number_;

View File

@@ -63,9 +63,6 @@ void SessionUtil::EnsureTestKeys() {
case DeviceFeatures::TEST_PROVISION_30:
// Can use oem certificate to install test rsa key.
break;
case wvoec::DeviceFeatures::TEST_PROVISION_40:
// OEM certificate is retrieved from the server.
break;
default:
FAIL() << "Cannot run test without test keybox or RSA key installed.";
}
@@ -74,33 +71,6 @@ void SessionUtil::EnsureTestKeys() {
// This makes sure that the derived keys (encryption key and two mac keys)
// are installed in OEMCrypto and in the test session.
void SessionUtil::InstallTestRSAKey(Session* s) {
if (global_features.provisioning_method == OEMCrypto_BootCertificateChain) {
const size_t buffer_size = 5000; // Make sure it is large enough.
std::vector<uint8_t> public_key(buffer_size);
size_t public_key_size = buffer_size;
std::vector<uint8_t> public_key_signature(buffer_size);
size_t public_key_signature_size = buffer_size;
std::vector<uint8_t> wrapped_private_key(buffer_size);
size_t wrapped_private_key_size = buffer_size;
OEMCrypto_PrivateKeyType key_type;
// Assume OEM cert has been loaded.
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_GenerateCertificateKeyPair(
s->session_id(), public_key.data(), &public_key_size,
public_key_signature.data(), &public_key_signature_size,
wrapped_private_key.data(), &wrapped_private_key_size, &key_type));
// Assume the public key has been verified by the server and the DRM cert is
// returned.
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_LoadDRMPrivateKey(s->session_id(), key_type,
wrapped_private_key.data(),
wrapped_private_key_size));
ASSERT_NO_FATAL_FAILURE(
s->SetRsaPublicKey(public_key.data(), public_key_size));
return;
}
if (global_features.loads_certificate) {
if (wrapped_rsa_key_.size() == 0) {
// If we don't have a wrapped key yet, create one.
@@ -113,5 +83,4 @@ void SessionUtil::InstallTestRSAKey(Session* s) {
// Test RSA key should be loaded.
ASSERT_NO_FATAL_FAILURE(s->PreparePublicKey());
}
} // namespace wvoec

File diff suppressed because it is too large Load Diff

View File

@@ -91,8 +91,9 @@ TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
// Android devices require L1 OEMCrypto.
TEST_F(OEMCryptoAndroidLMPTest, Level1Required) {
OEMCrypto_Security_Level security_level = OEMCrypto_SecurityLevel();
EXPECT_EQ(OEMCrypto_Level1, security_level)
const char* char_level = OEMCrypto_SecurityLevel();
std::string security_level(char_level ? char_level : "");
EXPECT_EQ("L1", security_level)
<< "The security level is " << security_level << ". but we expect L1.\n"
<< "If you are testing a device that should be L3 or L2, please\n"
<< "repeat the tests with the flag --gtest_filter=\"*-*Level1Required\"";

View File

@@ -41,10 +41,10 @@ int main(int argc, char** argv) {
filter_tests = false;
}
if (arg == "--fake_sleep") {
wvutil::TestSleep::set_real_sleep(false);
wvcdm::TestSleep::set_real_sleep(false);
}
}
wvutil::g_cutoff = static_cast<wvutil::LogPriority>(verbosity);
wvcdm::g_cutoff = static_cast<wvcdm::LogPriority>(verbosity);
wvoec::global_features.Initialize();
wvoec::global_features.set_cast_receiver(is_cast_receiver);
// Init GTest after device properties has been initialized.

View File

@@ -140,7 +140,7 @@ static const uint8_t TestKeyPKCS8[] = {
// then just use the string. Otherwise, convert to hex.
std::string MaybeHex(const uint8_t* data, size_t length) {
for (size_t i = 0; i < length; i++) {
if (!isprint(data[i])) return "0x" + wvutil::HexEncode(data, length);
if (!isprint(data[i])) return "0x" + wvcdm::HexEncode(data, length);
}
return std::string(reinterpret_cast<const char*>(data), length);
}
@@ -150,7 +150,7 @@ std::string MaybeHex(const std::vector<uint8_t>& data) {
std::vector<uint8_t> GetModelKey(const std::vector<uint8_t>& device_id) {
std::vector<uint8_t> keymint_key(
TestKeyPKCS8, TestKeyPKCS8 + wvutil::ArraySize(TestKeyPKCS8));
TestKeyPKCS8, TestKeyPKCS8 + wvcdm::ArraySize(TestKeyPKCS8));
keymint_key.insert(keymint_key.end(), device_id.begin(), device_id.end());
std::vector<uint8_t> key(SHA256_DIGEST_LENGTH);
SHA256(keymint_key.data(), keymint_key.size(), key.data());
@@ -251,7 +251,7 @@ TEST_F(OTAKeyboxProvisioningTest, BasicTest) {
std::copy(device_id.begin(), device_id.end(),
std::back_inserter(mac_context));
uint32_t bit_size = MAC_KEY_SIZE * 8 * 2;
std::string bit_size_string = wvutil::EncodeUint32(bit_size);
std::string bit_size_string = wvcdm::EncodeUint32(bit_size);
std::copy(bit_size_string.begin(), bit_size_string.end(),
std::back_inserter(mac_context));
std::string enc_label = "WV_ENCRYPT";
@@ -261,7 +261,7 @@ TEST_F(OTAKeyboxProvisioningTest, BasicTest) {
std::copy(device_id.begin(), device_id.end(),
std::back_inserter(enc_context));
bit_size = KEY_SIZE * 8;
bit_size_string = wvutil::EncodeUint32(bit_size);
bit_size_string = wvcdm::EncodeUint32(bit_size);
std::copy(bit_size_string.begin(), bit_size_string.end(),
std::back_inserter(enc_context));
KeyDeriver keys;