Files
oemcrypto/oemcrypto/odk/test/odk_test.cpp
Googler c56808c463 Automated update of OPK code
Included changes:

  - 92a0538dc60ad0c48866b5736fcec125f6493d8d Remove unused function by John "Juce" Bruce <juce@google.com>
  - 7235e2c89a94d6b6ed086aa83cd4b22b56bd8d65 Various static function fixes by John "Juce" Bruce <juce@google.com>
  - 908055030aa283ce74915fb68571b0ce3854e12e Fix duplicate & missing headers identified by clang-tidy by John "Juce" Bruce <juce@google.com>
  - 502b8b8caeb4654f294398039fff98ec641bda24 Updated `core_message_features.cpp` to use `odk_versions.h` by Alex Dale <sigquit@google.com>
  - 3163312183f5e0b8a08b97cfe171221861743cc5 Bump ODK max supported minor versions by Matt Feddersen <mattfedd@google.com>
  - c461df67a9003e738042716ae644dd96a66d2446 Updated ODK minor versions for 2025Q2 release. by Alex Dale <sigquit@google.com>
  - 56a43e881c31e4e2d3a2a7732bef00705a252a65 Added ODK_InitializeSessionValuesEx by Alex Dale <sigquit@google.com>

GitOrigin-RevId: 92a0538dc60ad0c48866b5736fcec125f6493d8d
2025-06-06 16:09:23 -07:00

1696 lines
76 KiB
C++

// Copyright 2019 Google LLC. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
#include "odk.h"
#include <sys/types.h>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <ostream>
#include <string>
#include <vector>
#include "OEMCryptoCENCCommon.h"
#include "core_message_deserialize.h"
#include "core_message_features.h"
#include "core_message_serialize.h"
#include "core_message_serialize_proto.h"
#include "core_message_types.h"
#include "gtest/gtest.h"
#include "license_protocol.pb.h"
#include "odk_overflow.h"
#include "odk_structs.h"
#include "odk_structs_priv.h"
#include "odk_target.h"
#include "odk_test_helper.h"
namespace wvodk_test {
namespace {
using oemcrypto_core_message::ODK_CommonRequest;
using oemcrypto_core_message::ODK_LicenseRequest;
using oemcrypto_core_message::ODK_MessageCounter;
using oemcrypto_core_message::ODK_Provisioning40Request;
using oemcrypto_core_message::ODK_ProvisioningRequest;
using oemcrypto_core_message::ODK_ReleaseRequest;
using oemcrypto_core_message::ODK_RenewalRequest;
using oemcrypto_core_message::deserialize::CoreCommonRequestFromMessage;
using oemcrypto_core_message::deserialize::CoreLicenseRequestFromMessage;
using oemcrypto_core_message::deserialize::CoreProvisioning40RequestFromMessage;
using oemcrypto_core_message::deserialize::CoreProvisioningRequestFromMessage;
using oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage;
using oemcrypto_core_message::deserialize::
CoreRenewedProvisioningRequestFromMessage;
using oemcrypto_core_message::features::CoreMessageFeatures;
using oemcrypto_core_message::serialize::CreateCoreLicenseResponse;
using oemcrypto_core_message::serialize::CreateCoreProvisioning40Response;
using oemcrypto_core_message::serialize::CreateCoreProvisioningResponse;
using oemcrypto_core_message::serialize::
CreateCoreProvisioningResponseFromProto;
using oemcrypto_core_message::serialize::CreateCoreReleaseResponse;
using oemcrypto_core_message::serialize::CreateCoreRenewalResponse;
constexpr uint32_t kExtraPayloadSize = 128u;
/* Used to parameterize tests by version number. The request is given one
* version number, and we will expect the response to have another version
* number. */
struct VersionPair {
uint16_t major_version;
uint16_t minor_version;
template <typename T, typename S>
VersionPair(T major, S minor)
: major_version(static_cast<uint16_t>(major)),
minor_version(static_cast<uint16_t>(minor)){};
};
struct VersionParameters {
VersionPair maximum; // The CoreMessageFeatures maximum version.
bool prerelease; // CoreMessageFeatures serve_prerelease_odk_messages.
VersionPair request;
VersionPair response;
bool should_accept_request;
};
std::ostream& operator<<(std::ostream& stream, const VersionPair& v) {
return stream << "v" << v.major_version << "." << v.minor_version;
}
// This function is called by GTest when a parameterized test fails in order
// to log the parameter used for the failing test.
void PrintTo(const VersionParameters& p, std::ostream* os) {
*os << "max=" << p.maximum << ", prerelease=" << p.prerelease
<< ", request=" << p.request << ", response=" << p.response
<< ", should_accept_request=" << p.should_accept_request;
}
void SetDefaultSerializedProvisioningResponse(std::string* serialized_message) {
// Create a dummy provisioning response
video_widevine::ProvisioningResponse provisioning_response;
provisioning_response.set_device_certificate("device_certificate");
provisioning_response.set_device_rsa_key("device_rsa_key");
provisioning_response.set_device_rsa_key_iv("device_rsa_key_iv");
if (!provisioning_response.SerializeToString(serialized_message)) {
FAIL();
}
}
bool CheckCounterInfoIsEqual(ODK_MessageCounterInfo* a, ODK_MessageCounter* b) {
if (!a || !b) return false;
EXPECT_EQ(a->master_generation_number, b->master_generation_number);
EXPECT_EQ(a->provisioning_count, b->provisioning_count);
EXPECT_EQ(a->license_count, b->license_count);
EXPECT_EQ(a->decrypt_count, b->decrypt_count);
EXPECT_EQ(a->major_version, b->major_version);
EXPECT_EQ(a->minor_version, b->minor_version);
EXPECT_EQ(a->patch_version, b->patch_version);
for (size_t i = 0; i < sizeof(a->soc_vendor); i++) {
EXPECT_EQ(a->soc_vendor[i], b->soc_vendor[i]);
}
for (size_t i = 0; i < sizeof(a->chipset_model); i++) {
EXPECT_EQ(a->chipset_model[i], b->chipset_model[i]);
}
for (size_t i = 0; i < sizeof(a->extra); i++) {
EXPECT_EQ(a->extra[i], b->extra[i]);
}
return true;
}
template <typename T, typename F, typename G>
void ValidateRequest(uint32_t message_type,
const std::vector<ODK_Field>& extra_fields,
const F& odk_prepare_func, const G& kdo_parse_func) {
uint32_t message_size = 0;
uint16_t api_major_version = ODK_MAJOR_VERSION;
uint16_t api_minor_version = ODK_MINOR_VERSION;
uint32_t nonce = 0xdeadbeef;
uint32_t session_id = 0xcafebabe;
ODK_NonceValues nonce_values{api_minor_version, api_major_version, nonce,
session_id};
std::vector<ODK_Field> total_fields = {
{ODK_UINT32, &message_type, "message_type"},
{ODK_UINT32, &message_size, "message_size"},
{ODK_UINT16, &api_minor_version, "api_minor_version"},
{ODK_UINT16, &api_major_version, "api_major_version"},
{ODK_UINT32, &nonce, "nonce"},
{ODK_UINT32, &session_id, "session_id"},
};
total_fields.insert(total_fields.end(), extra_fields.begin(),
extra_fields.end());
for (auto& field : total_fields) {
message_size += ODK_FieldLength(field.type);
}
// empty buf, expect core message length to be set correctly
size_t core_message_length = 0;
uint8_t* buf_empty = nullptr;
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
odk_prepare_func(buf_empty, &core_message_length, &nonce_values));
EXPECT_EQ(core_message_length, message_size);
// non-empty buf, expect core message length to be set correctly, and buf is
// filled with ODK_Field values appropriately
std::vector<uint8_t> buf(message_size, 0);
EXPECT_EQ(OEMCrypto_SUCCESS,
odk_prepare_func(buf.data(), &core_message_length, &nonce_values));
EXPECT_EQ(core_message_length, message_size);
std::vector<uint8_t> buf_expected(message_size, 0);
size_t buf_len_expected = 0;
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_IterFields(ODK_WRITE, buf_expected.data(), SIZE_MAX,
&buf_len_expected, total_fields));
EXPECT_EQ(buf_len_expected, message_size);
EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(buf_expected.data(), buf.data(),
message_size, total_fields));
// odk kdo round-trip: deserialize from buf, then serialize it to buf2
// expect them to be identical
T t = {};
std::string oemcrypto_core_message(reinterpret_cast<char*>(buf.data()),
message_size);
EXPECT_TRUE(kdo_parse_func(oemcrypto_core_message, &t));
nonce_values.api_minor_version = t.api_minor_version;
nonce_values.api_major_version = t.api_major_version;
nonce_values.nonce = t.nonce;
nonce_values.session_id = t.session_id;
std::vector<uint8_t> buf2(message_size, 0);
EXPECT_EQ(OEMCrypto_SUCCESS,
odk_prepare_func(buf2.data(), &core_message_length, &nonce_values));
EXPECT_EQ(core_message_length, message_size);
EXPECT_NO_FATAL_FAILURE(
ODK_ExpectEqualBuf(buf.data(), buf2.data(), message_size, total_fields));
}
/**
* Template arguments:
* T: kdo input struct
* F: odk deserializer
* G: kdo serializer
*/
template <typename T, typename F, typename G>
void ValidateResponse(const VersionParameters& versions,
ODK_CoreMessage* core_message,
const std::vector<ODK_Field>& extra_fields,
const F& odk_parse_func, const G& kdo_prepare_func) {
T t = {};
t.api_major_version = versions.request.major_version;
t.api_minor_version = versions.request.minor_version;
t.nonce = core_message->nonce_values.nonce;
t.session_id = core_message->nonce_values.session_id;
std::vector<uint8_t> buf;
ODK_BuildMessageBuffer(core_message, extra_fields, &buf);
std::vector<uint8_t> zero(buf.size(), 0);
size_t bytes_read = 0;
// zero-out input
EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero.data(), buf.size(),
&bytes_read, extra_fields));
// Parse buf with odk
const OEMCryptoResult parse_result = odk_parse_func(buf.data(), buf.size());
EXPECT_EQ(OEMCrypto_SUCCESS, parse_result);
size_t size_out = 0;
if (parse_result != OEMCrypto_SUCCESS) {
ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf.data(), buf.size(), &size_out,
extra_fields);
}
// serialize odk output to oemcrypto_core_message
std::string oemcrypto_core_message;
EXPECT_EQ(versions.should_accept_request,
kdo_prepare_func(t, &oemcrypto_core_message));
if (!versions.should_accept_request) return;
// verify round-trip works
EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(
buf.data(), oemcrypto_core_message.data(), buf.size(), extra_fields));
}
TEST(OdkTest, SerializeFields) {
uint32_t x[] = {0, 1, 2};
uint64_t y[] = {3LL << 32, 4LL << 32, 5LL << 32};
OEMCrypto_Substring s = {.offset = 6, .length = 7};
std::vector<ODK_Field> fields = {
{ODK_UINT32, &x[0], "x[0]"}, {ODK_UINT32, &x[1], "x[1]"},
{ODK_UINT32, &x[2], "x[2]"}, {ODK_UINT64, &y[0], "y[0]"},
{ODK_UINT64, &y[1], "y[1]"}, {ODK_UINT64, &y[2], "y[2]"},
{ODK_SUBSTRING, &s, "s"},
};
uint8_t buf[1024] = {0};
uint8_t buf2[1024] = {0};
size_t bytes_read = 0, bytes_written = 0;
ODK_IterFields(ODK_WRITE, buf, SIZE_MAX, &bytes_read, fields);
std::vector<ODK_Field> fields2(fields.size());
ODK_ResetOdkFields(&fields);
ODK_IterFields(ODK_READ, buf, bytes_read, &bytes_written, fields);
ODK_IterFields(ODK_WRITE, buf2, SIZE_MAX, &bytes_read, fields);
EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(buf, buf2, bytes_read, fields));
}
TEST(OdkTest, SerializeFieldsStress) {
const int n = 1024;
std::vector<ODK_Field> fields(n);
std::srand(0);
size_t total_size = 0;
for (int i = 0; i < n; i++) {
fields[i].type = static_cast<ODK_FieldType>(
std::rand() % (static_cast<int>(ODK_LAST_STRESSABLE_TYPE) + 1));
fields[i].value = malloc(ODK_AllocSize(fields[i].type));
fields[i].name = "stress";
total_size += ODK_FieldLength(fields[i].type);
}
std::vector<uint8_t> buf;
buf.reserve(total_size);
for (size_t i = 0; i < total_size; i++) {
buf.push_back(std::rand() & 0xff);
}
size_t bytes_read = 0, bytes_written = 0;
std::vector<uint8_t> buf2(total_size);
ODK_IterFields(ODK_READ, buf.data(), total_size, &bytes_read, fields);
EXPECT_EQ(bytes_read, total_size);
ODK_IterFields(ODK_WRITE, buf2.data(), total_size, &bytes_written, fields);
EXPECT_EQ(bytes_written, total_size);
EXPECT_NO_FATAL_FAILURE(
ODK_ExpectEqualBuf(buf.data(), buf2.data(), total_size, fields));
// cleanup
for (int i = 0; i < n; i++) {
free(fields[i].value);
}
}
TEST(OdkTest, NullRequestTest) {
size_t core_message_length = 0;
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
uint16_t decenc_mitigation_options_supported = 0;
// Assert that nullptr does not cause a core dump.
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(nullptr, 0uL, nullptr, &nonce_values,
&counter_info,
decenc_mitigation_options_supported));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(nullptr, 0uL, &core_message_length,
nullptr, &counter_info,
decenc_mitigation_options_supported));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(nullptr, 0uL, &core_message_length,
&nonce_values, nullptr,
decenc_mitigation_options_supported));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewalRequest(nullptr, 0uL, nullptr, &nonce_values,
&clock_values, 0uL));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewalRequest(nullptr, 0uL, &core_message_length,
nullptr, &clock_values, 0uL));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewalRequest(nullptr, 0uL, &core_message_length,
&nonce_values, nullptr, 0uL));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreProvisioningRequest(
nullptr, 0uL, &core_message_length, nullptr, &counter_info));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreProvisioningRequest(nullptr, 0uL, nullptr,
&nonce_values, &counter_info));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreProvisioningRequest(
nullptr, 0uL, &core_message_length, &nonce_values, nullptr));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreProvisioning40Request(
nullptr, 0uL, &core_message_length,
nullptr, nullptr, 0uL, &counter_info));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreProvisioning40Request(
nullptr, 0uL, nullptr, &nonce_values,
nullptr, 0uL, &counter_info));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreProvisioning40Request(
nullptr, 0uL, &core_message_length,
&nonce_values, nullptr, 0uL, nullptr));
// Null device id in provisioning request is ok
if (nonce_values.api_major_version > 17) {
uint8_t message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
core_message_length = ODK_PROVISIONING_REQUEST_SIZE;
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreProvisioningRequest(
message, ODK_PROVISIONING_REQUEST_SIZE, &core_message_length,
&nonce_values, &counter_info));
} else {
uint8_t message[ODK_PROVISIONING_REQUEST_SIZE_V17] = {0};
core_message_length = ODK_PROVISIONING_REQUEST_SIZE_V17;
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreProvisioningRequest(
message, ODK_PROVISIONING_REQUEST_SIZE_V17,
&core_message_length, &nonce_values, &counter_info));
}
// Null device info in provisioning 4.0 request is ok
uint8_t message_prov4[ODK_PROVISIONING40_REQUEST_SIZE] = {0};
core_message_length = ODK_PROVISIONING40_REQUEST_SIZE;
EXPECT_EQ(
OEMCrypto_SUCCESS,
ODK_PrepareCoreProvisioning40Request(
message_prov4, ODK_PROVISIONING40_REQUEST_SIZE, &core_message_length,
&nonce_values, nullptr, 0uL, &counter_info));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewedProvisioningRequest(
nullptr, 0uL, &core_message_length, nullptr, nullptr, 0uL,
OEMCrypto_RenewalACert, nullptr, 0uL));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewedProvisioningRequest(
nullptr, 0uL, nullptr, &nonce_values, nullptr, 0uL,
OEMCrypto_RenewalACert, nullptr, 0uL));
// Null device id in renewed provisioning request is ok
uint8_t renewed_message[ODK_RENEWED_PROVISIONING_REQUEST_SIZE] = {0};
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
uint32_t renewal_data_length = ODK_KEYBOX_RENEWAL_DATA_SIZE;
core_message_length = ODK_RENEWED_PROVISIONING_REQUEST_SIZE;
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreRenewedProvisioningRequest(
renewed_message, ODK_RENEWED_PROVISIONING_REQUEST_SIZE,
&core_message_length, &nonce_values, nullptr, 0uL,
OEMCrypto_RenewalACert, renewal_data, renewal_data_length));
// Null renewal data in renewed provisioning request is ok
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
uint32_t device_id_length = ODK_DEVICE_ID_LEN_MAX;
core_message_length = ODK_RENEWED_PROVISIONING_REQUEST_SIZE;
ODK_PrepareCoreRenewedProvisioningRequest(
renewed_message, ODK_RENEWED_PROVISIONING_REQUEST_SIZE,
&core_message_length, &nonce_values, device_id, device_id_length,
OEMCrypto_RenewalACert, nullptr, 0uL);
}
TEST(OdkTest, NullResponseTest) {
constexpr size_t message_size = 64;
uint8_t message[message_size] = {0};
size_t core_message_length = message_size;
ODK_TimerLimits timer_limits;
ODK_ParsedLicense parsed_license;
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
// Assert that nullptr does not cause a core dump.
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseLicense(message, message_size, core_message_length, true,
true, 0, &timer_limits, &clock_values,
&nonce_values, nullptr, nullptr));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseLicense(message, message_size, core_message_length, true,
true, 0, &timer_limits, &clock_values, nullptr,
&parsed_license, nullptr));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseLicense(message, message_size, core_message_length, true,
true, 0, &timer_limits, nullptr, &nonce_values,
&parsed_license, nullptr));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseLicense(message, message_size, core_message_length, true,
true, 0, nullptr, &clock_values, &nonce_values,
&parsed_license, nullptr));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseLicense(nullptr, message_size, core_message_length, true,
true, 0, &timer_limits, &clock_values,
&nonce_values, &parsed_license, nullptr));
constexpr uint64_t system_time = 0;
uint64_t timer_value = 0;
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseRenewal(message, message_size, core_message_length,
&nonce_values, system_time, &timer_limits, nullptr,
&timer_value));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseRenewal(message, message_size, core_message_length,
&nonce_values, system_time, nullptr, &clock_values,
&timer_value));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseRenewal(message, message_size, core_message_length,
nullptr, system_time, &timer_limits, &clock_values,
&timer_value));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseRenewal(nullptr, message_size, core_message_length,
&nonce_values, system_time, &timer_limits,
&clock_values, &timer_value));
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
ODK_ParsedProvisioning parsed_response;
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseProvisioning(message, message_size, core_message_length,
&nonce_values, device_id,
ODK_DEVICE_ID_LEN_MAX, nullptr));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseProvisioning(message, message_size, core_message_length,
&nonce_values, nullptr, 0, &parsed_response));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseProvisioning(message, message_size, core_message_length,
nullptr, device_id, ODK_DEVICE_ID_LEN_MAX,
&parsed_response));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseProvisioning(nullptr, message_size, core_message_length,
&nonce_values, device_id,
ODK_DEVICE_ID_LEN_MAX, &parsed_response));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseProvisioning40(message, message_size, core_message_length,
nullptr));
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_ParseProvisioning40(nullptr, message_size, core_message_length,
&nonce_values));
}
TEST(OdkTest, PrepareCoreLicenseRequest) {
uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(license_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
uint16_t decenc_mitigation_options_supported = 0;
EXPECT_EQ(
OEMCrypto_SUCCESS,
ODK_PrepareCoreLicenseRequest(
license_message, sizeof(license_message), &core_message_length,
&nonce_values, &counter_info, decenc_mitigation_options_supported));
}
TEST(OdkTest, PrepareCoreLicenseRequestSize) {
uint8_t license_message[ODK_LICENSE_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(license_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
uint16_t decenc_mitigation_options_supported = 0;
// message length smaller than core message length
size_t core_message_length_invalid = core_message_length + 1;
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreLicenseRequest(
license_message, sizeof(license_message),
&core_message_length_invalid, &nonce_values, &counter_info,
decenc_mitigation_options_supported));
// message length larger than core message length
uint8_t license_message_large[ODK_LICENSE_REQUEST_SIZE * 2] = {0};
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreLicenseRequest(
license_message_large, sizeof(license_message_large),
&core_message_length, &nonce_values, &counter_info,
decenc_mitigation_options_supported));
}
TEST(OdkTest, PrepareCoreRenewalRequest) {
uint8_t renewal_message[ODK_RENEWAL_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(renewal_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
constexpr uint64_t system_time_seconds = 10;
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreRenewalRequest(
renewal_message, sizeof(renewal_message), &core_message_length,
&nonce_values, &clock_values, system_time_seconds));
}
TEST(OdkTest, PrepareCoreRenewalRequestTimer) {
uint8_t renewal_message[ODK_RENEWAL_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(renewal_message);
ODK_NonceValues nonce_values{2, 16, 0, 0};
constexpr uint64_t system_time_seconds = 10;
ODK_ClockValues clock_values_updated;
memset(&clock_values_updated, 0, sizeof(clock_values_updated));
// system time smaller than first decrypt time
clock_values_updated.time_of_first_decrypt = system_time_seconds + 1;
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewalRequest(
renewal_message, sizeof(renewal_message), &core_message_length,
&nonce_values, &clock_values_updated, system_time_seconds));
clock_values_updated.time_of_first_decrypt = system_time_seconds - 1;
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreRenewalRequest(
renewal_message, sizeof(renewal_message), &core_message_length,
&nonce_values, &clock_values_updated, system_time_seconds));
// clock_values.time_of_renewal_request should get updated
EXPECT_EQ(system_time_seconds - clock_values_updated.time_of_first_decrypt,
clock_values_updated.time_of_renewal_request);
}
TEST(OdkTest, PrepareCoreProvisioningRequest) {
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreProvisioningRequest(
provisioning_message, sizeof(provisioning_message),
&core_message_length, &nonce_values, &counter_info));
}
TEST(OdkTest, PrepareCoreProvisioning40Request) {
uint8_t provisioning_message[ODK_PROVISIONING40_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
uint8_t device_info[ODK_DEVICE_INFO_LEN_MAX] = {0};
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreProvisioning40Request(
provisioning_message, sizeof(provisioning_message),
&core_message_length, &nonce_values, device_info,
sizeof(device_info), &counter_info));
}
TEST(OdkTest, PrepareCoreRenewedProvisioningRequest) {
uint8_t provisioning_message[ODK_RENEWED_PROVISIONING_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
EXPECT_EQ(
OEMCrypto_SUCCESS,
ODK_PrepareCoreRenewedProvisioningRequest(
provisioning_message, sizeof(provisioning_message),
&core_message_length, &nonce_values, device_id, sizeof(device_id),
OEMCrypto_RenewalACert, renewal_data, sizeof(renewal_data)));
}
TEST(OdkTest, PrepareCoreProvisioning40RequestDeviceInfo) {
uint8_t provisioning_message[ODK_PROVISIONING40_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
uint8_t device_info_invalid[ODK_DEVICE_INFO_LEN_MAX + 1] = {0};
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreProvisioning40Request(
provisioning_message, sizeof(provisioning_message),
&core_message_length, &nonce_values, device_info_invalid,
sizeof(device_info_invalid), &counter_info));
}
TEST(OdkTest, PrepareCoreRenewedProvisioningRequestDeviceId) {
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
uint8_t device_id_invalid[ODK_DEVICE_ID_LEN_MAX + 1] = {0};
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewedProvisioningRequest(
provisioning_message, sizeof(provisioning_message),
&core_message_length, &nonce_values, device_id_invalid,
sizeof(device_id_invalid), OEMCrypto_RenewalACert, renewal_data,
sizeof(renewal_data)));
}
TEST(OdkTest, PrepareCoreRenewedProvisioningRequestRenewalDataInvalid) {
uint8_t provisioning_message[ODK_PROVISIONING_REQUEST_SIZE] = {0};
size_t core_message_length = sizeof(provisioning_message);
ODK_NonceValues nonce_values;
memset(&nonce_values, 0, sizeof(nonce_values));
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
uint8_t renewal_data_invalid[ODK_KEYBOX_RENEWAL_DATA_SIZE + 1] = {0};
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
ODK_PrepareCoreRenewedProvisioningRequest(
provisioning_message, sizeof(provisioning_message),
&core_message_length, &nonce_values, device_id,
sizeof(device_id), OEMCrypto_RenewalACert, renewal_data_invalid,
sizeof(renewal_data_invalid)));
}
// Serialize and de-serialize license request
TEST(OdkTest, LicenseRequestRoundtrip) {
ODK_MessageCounterInfo counter_info;
counter_info.master_generation_number = 0x12345678abcdffff;
counter_info.provisioning_count = 12;
counter_info.license_count = 50;
counter_info.decrypt_count = 340;
counter_info.major_version = ODK_MAJOR_VERSION;
counter_info.minor_version = ODK_MINOR_VERSION;
counter_info.patch_version = 4;
memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
uint16_t decenc_mitigation_options_supported = 0;
std::vector<ODK_Field> extra_fields = {
{ODK_MESSAGECOUNTER, &counter_info, "counter_info"},
{ODK_UINT16, &decenc_mitigation_options_supported,
"decenc_mitigation_options_supported"},
};
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreLicenseRequest(buf, SIZE_MAX, size, nonce_values,
&counter_info,
decenc_mitigation_options_supported);
};
auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
ODK_LicenseRequest* core_license_request) {
bool ok = CoreLicenseRequestFromMessage(oemcrypto_core_message,
core_license_request);
if (!ok) return false;
ok = CheckCounterInfoIsEqual(&counter_info,
&core_license_request->counter_info);
return ok;
};
ValidateRequest<ODK_LicenseRequest>(ODK_License_Request_Type, extra_fields,
odk_prepare_func, kdo_parse_func);
}
// Serialize and de-serialize license request that has decenc mitigation
// non-zero value.
TEST(OdkTest, LicenseRequestRoundtripDecencMitigation) {
ODK_MessageCounterInfo counter_info;
counter_info.master_generation_number = 0x12345678abcdffff;
counter_info.provisioning_count = 12;
counter_info.license_count = 50;
counter_info.decrypt_count = 340;
counter_info.major_version = ODK_MAJOR_VERSION;
counter_info.minor_version = ODK_MINOR_VERSION;
counter_info.patch_version = 4;
memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
uint16_t decenc_mitigation_options_supported = 1;
std::vector<ODK_Field> extra_fields = {
{ODK_MESSAGECOUNTER, &counter_info, "counter_info"},
{ODK_UINT16, &decenc_mitigation_options_supported,
"decenc_mitigation_options_supported"},
};
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreLicenseRequest(buf, SIZE_MAX, size, nonce_values,
&counter_info,
decenc_mitigation_options_supported);
};
auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
ODK_LicenseRequest* core_license_request) {
bool ok = CoreLicenseRequestFromMessage(oemcrypto_core_message,
core_license_request);
if (!ok) return false;
ok = CheckCounterInfoIsEqual(&counter_info,
&core_license_request->counter_info);
return ok;
};
ValidateRequest<ODK_LicenseRequest>(ODK_License_Request_Type, extra_fields,
odk_prepare_func, kdo_parse_func);
}
TEST(OdkTest, RenewalRequestRoundtrip) {
constexpr uint64_t system_time_seconds = 0xBADDCAFE000FF1CE;
uint64_t playback_time = 0xCAFE00000000;
const uint64_t playback_start = system_time_seconds - playback_time;
const std::vector<ODK_Field> extra_fields = {
{ODK_UINT64, &playback_time, "playback_time"},
};
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
clock_values.time_of_first_decrypt = playback_start;
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreRenewalRequest(buf, SIZE_MAX, size, nonce_values,
&clock_values, system_time_seconds);
};
auto kdo_parse_func = [&](const std::string& oemcrypto_core_message,
ODK_RenewalRequest* core_renewal_request) {
bool ok = CoreRenewalRequestFromMessage(oemcrypto_core_message,
core_renewal_request);
return ok;
};
ValidateRequest<ODK_RenewalRequest>(ODK_Renewal_Request_Type, extra_fields,
odk_prepare_func, kdo_parse_func);
}
TEST(OdkTest, ReleaseRequestRoundTrip) {
OEMCrypto_UsageEntryStatus usage_entry_status = OEMCrypto_Active;
uint32_t clock_security_level = 1;
// constexpr uint64_t system_time_seconds = 0xBADDCAFE000FF1CE;
uint64_t seconds_since_license_requested = 0;
uint64_t seconds_since_first_decrypt = 0;
uint32_t pst_length = 1;
uint8_t pst[ODK_PST_LEN_MAX];
pst[0] = 0xff;
// uint8_t* pst_ptr = pst;
ODK_ClockValues clock_values;
memset(&clock_values, 0, sizeof(clock_values));
clock_values.time_of_first_decrypt = seconds_since_first_decrypt;
std::vector<ODK_Field> extra_fields = {
{ODK_UINT32, &usage_entry_status, "usage_entry_status"},
{ODK_UINT32, &clock_security_level, "clock_security_level"},
{ODK_UINT64, &seconds_since_license_requested,
"seconds_since_license_requested"},
{ODK_UINT64, &seconds_since_first_decrypt, "seconds_since_first_decrypt"},
{ODK_UINT32, &pst_length, "pst_length"},
{ODK_UINT8, &pst[0], "pst"},
};
// TODO(vickymin): Restore the rest of this test after test framework is
// updated and fixed. Some variables above are commented out because they
// aren't used in the test as of now. This will be updated.
}
TEST(OdkTest, ProvisionRequestRoundtrip) {
ODK_MessageCounterInfo counter_info;
counter_info.master_generation_number = 0x12345678abcdffff;
counter_info.provisioning_count = 12;
counter_info.license_count = 50;
counter_info.decrypt_count = 340;
counter_info.major_version = ODK_MAJOR_VERSION;
counter_info.minor_version = ODK_MINOR_VERSION;
counter_info.patch_version = 4;
memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
// Fake device_id_length for older servers, since we removed device id from
// the v18 request
uint32_t fake_device_id_length = 64;
std::vector<ODK_Field> extra_fields = {
{ODK_UINT32, &(fake_device_id_length), "fake_device_id_length"},
{ODK_MESSAGECOUNTER, &counter_info, "counter_info"},
};
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
const ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreProvisioningRequest(buf, SIZE_MAX, size, nonce_values,
&counter_info);
};
auto kdo_parse_func =
[&](const std::string& oemcrypto_core_message,
ODK_ProvisioningRequest* core_provisioning_request) {
bool ok = CoreProvisioningRequestFromMessage(oemcrypto_core_message,
core_provisioning_request);
if (!ok) return false;
ok = CheckCounterInfoIsEqual(&counter_info,
&core_provisioning_request->counter_info);
return ok;
};
ValidateRequest<ODK_ProvisioningRequest>(ODK_Provisioning_Request_Type,
extra_fields, odk_prepare_func,
kdo_parse_func);
}
TEST(OdkTest, ProvisionRequest40Roundtrip) {
uint32_t device_info_length = ODK_DEVICE_INFO_LEN_MAX / 2;
uint8_t device_info[ODK_DEVICE_INFO_LEN_MAX] = {0};
memset(device_info, 0xaa, device_info_length);
ODK_MessageCounterInfo counter_info;
counter_info.master_generation_number = 0x12345678abcdffff;
counter_info.provisioning_count = 12;
counter_info.license_count = 50;
counter_info.decrypt_count = 340;
counter_info.major_version = ODK_MAJOR_VERSION;
counter_info.minor_version = ODK_MINOR_VERSION;
counter_info.patch_version = 4;
memset(counter_info.soc_vendor, 'S', sizeof(counter_info.soc_vendor));
memset(counter_info.chipset_model, 'C', sizeof(counter_info.chipset_model));
memset(counter_info.extra, 0xee, sizeof(counter_info.extra));
std::vector<ODK_Field> extra_fields = {
{ODK_UINT32, &device_info_length, "device_info_length"},
{ODK_DEVICEINFO, device_info, "device_info"},
{ODK_MESSAGECOUNTER, &counter_info, "counter_info"},
};
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
const ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreProvisioning40Request(
buf, SIZE_MAX, size, nonce_values, device_info, device_info_length,
&counter_info);
};
auto kdo_parse_func =
[&](const std::string& oemcrypto_core_message,
ODK_Provisioning40Request* core_provisioning_request) {
bool ok = CoreProvisioning40RequestFromMessage(
oemcrypto_core_message, core_provisioning_request);
if (!ok) return false;
ok = CheckCounterInfoIsEqual(&counter_info,
&core_provisioning_request->counter_info);
return ok;
};
ValidateRequest<ODK_Provisioning40Request>(ODK_Provisioning40_Request_Type,
extra_fields, odk_prepare_func,
kdo_parse_func);
}
TEST(OdkTest, RenewedProvisionRequestRoundtrip) {
uint32_t device_id_length = ODK_DEVICE_ID_LEN_MAX / 2;
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
memset(device_id, 0xff, device_id_length);
uint16_t renewal_type = OEMCrypto_RenewalACert;
uint32_t renewal_data_length = ODK_KEYBOX_RENEWAL_DATA_SIZE / 2;
uint8_t renewal_data[ODK_KEYBOX_RENEWAL_DATA_SIZE] = {0};
memset(renewal_data, 0xff, renewal_data_length);
std::vector<ODK_Field> extra_fields = {
{ODK_UINT32, &device_id_length, "device_id_length"},
{ODK_DEVICEID, device_id, "device_id"},
{ODK_UINT16, &renewal_type, "renewal_type"},
{ODK_UINT32, &renewal_data_length, "renewal_data_length"},
{ODK_RENEWALDATA, renewal_data, "renewal_data"},
};
auto odk_prepare_func = [&](uint8_t* const buf, size_t* size,
const ODK_NonceValues* nonce_values) {
return ODK_PrepareCoreRenewedProvisioningRequest(
buf, SIZE_MAX, size, nonce_values, device_id, device_id_length,
renewal_type, renewal_data, renewal_data_length);
};
auto kdo_parse_func =
[&](const std::string& oemcrypto_core_message,
ODK_ProvisioningRequest* core_provisioning_request) {
bool ok = CoreRenewedProvisioningRequestFromMessage(
oemcrypto_core_message, core_provisioning_request);
return ok;
};
ValidateRequest<ODK_ProvisioningRequest>(
ODK_Renewed_Provisioning_Request_Type, extra_fields, odk_prepare_func,
kdo_parse_func);
}
TEST(OdkTest, ParseLicenseErrorNonce) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(&params, ODK_MAJOR_VERSION);
std::vector<uint8_t> buf;
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
// temporarily mess up with nonce
params.core_message.nonce_values.nonce = 0;
OEMCryptoResult err = ODK_ParseLicense(
buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
params.initial_license_load, params.usage_entry_present, 0,
&(params.timer_limits), &(params.clock_values),
&(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(OEMCrypto_ERROR_INVALID_NONCE, err);
}
TEST(OdkTest, ParseLicenseErrorUsageEntry) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(&params, ODK_MAJOR_VERSION);
std::vector<uint8_t> buf;
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
params.usage_entry_present = false;
OEMCryptoResult err = ODK_ParseLicense(
buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
params.initial_license_load, params.usage_entry_present, 0,
&(params.timer_limits), &(params.clock_values),
&(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
}
TEST(OdkTest, ParseLicenseNullSubstring) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(&params, ODK_MAJOR_VERSION);
params.parsed_license.srm_restriction_data.offset = 0;
params.parsed_license.srm_restriction_data.length = 0;
std::vector<uint8_t> buf;
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
OEMCryptoResult result = ODK_ParseLicense(
buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
params.initial_license_load, params.usage_entry_present, 0,
&(params.timer_limits), &(params.clock_values),
&(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(OEMCrypto_SUCCESS, result);
}
TEST(OdkTest, ParseLicenseErrorSubstringOffset) {
// offset out of range
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(&params, ODK_MAJOR_VERSION);
params.parsed_license.enc_mac_keys_iv.offset = 1024;
std::vector<uint8_t> buf;
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
OEMCryptoResult err = ODK_ParseLicense(
buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
params.initial_license_load, params.usage_entry_present, 0,
&(params.timer_limits), &(params.clock_values),
&(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
// offset + length out of range
err = OEMCrypto_SUCCESS;
ODK_SetDefaultLicenseResponseParams(&params, ODK_MAJOR_VERSION);
params.parsed_license.enc_mac_keys_iv.length = buf.size();
buf.clear();
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
err = ODK_ParseLicense(
buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
params.initial_license_load, params.usage_entry_present, 0,
&(params.timer_limits), &(params.clock_values),
&(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
}
TEST(OdkTest, ParseRenewalErrorTimer) {
ODK_RenewalResponseParams params;
ODK_SetDefaultRenewalResponseParams(&params);
std::vector<uint8_t> buf;
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
// Set the time for the last renewal request, as seen in clock_values, to be
// after the time in the request.
// TODO: b/290249855 - This is reversed. It should be +5.
params.clock_values.time_of_renewal_request = params.playback_clock - 5;
OEMCryptoResult err = ODK_ParseRenewal(
buf.data(), buf.size(), buf.size(), &(params.core_message.nonce_values),
params.system_time, &(params.timer_limits), &(params.clock_values),
&(params.playback_timer));
EXPECT_EQ(ODK_STALE_RENEWAL, err);
}
TEST(OdkTest, ProvisionResponseFromProto) {
std::string serialized_provisioning_resp;
EXPECT_NO_FATAL_FAILURE(
SetDefaultSerializedProvisioningResponse(&serialized_provisioning_resp));
ODK_ProvisioningRequest core_request = {
.api_minor_version = ODK_MINOR_VERSION,
.api_major_version = ODK_MAJOR_VERSION,
.nonce = 0xdeadbeef,
.session_id = 0xcafebabe,
};
const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
std::string oemcrypto_core_message;
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, serialized_provisioning_resp, core_request,
OEMCrypto_RSAPrivateKey, &oemcrypto_core_message));
}
// Verify de-serialize common request.
TEST(OdkTest, ParseCoreCommonRequestFromMessage) {
std::string serialized_provisioning_resp;
EXPECT_NO_FATAL_FAILURE(
SetDefaultSerializedProvisioningResponse(&serialized_provisioning_resp));
ODK_ProvisioningRequest core_request = {
.api_minor_version = ODK_MINOR_VERSION,
.api_major_version = ODK_MAJOR_VERSION,
.nonce = 0xdeadbeef,
.session_id = 0xcafebabe,
};
const CoreMessageFeatures features(/*prerelease_odk_messages=*/true);
std::string oemcrypto_core_message;
EXPECT_TRUE(CreateCoreProvisioningResponseFromProto(
features, serialized_provisioning_resp, core_request,
OEMCrypto_RSAPrivateKey, &oemcrypto_core_message));
ODK_CommonRequest odk_common_request;
ASSERT_TRUE(CoreCommonRequestFromMessage(oemcrypto_core_message,
&odk_common_request));
EXPECT_EQ(odk_common_request.message_type, 6u);
EXPECT_EQ(odk_common_request.message_length, 60u);
EXPECT_EQ(odk_common_request.api_minor_version, ODK_MINOR_VERSION);
EXPECT_EQ(odk_common_request.api_major_version, ODK_MAJOR_VERSION);
EXPECT_EQ(odk_common_request.nonce, 0xdeadbeef);
EXPECT_EQ(odk_common_request.session_id, 0xcafebabe);
}
class OdkVersionTest : public ::testing::Test,
public ::testing::WithParamInterface<VersionParameters> {
protected:
template <typename P>
void SetRequestVersion(P* params) {
params->core_message.nonce_values.api_major_version =
GetParam().response.major_version;
params->core_message.nonce_values.api_minor_version =
GetParam().response.minor_version;
features_ = CoreMessageFeatures(GetParam().prerelease);
features_.maximum_major_version =
static_cast<uint32_t>(GetParam().maximum.major_version);
features_.maximum_minor_version =
static_cast<uint32_t>(GetParam().maximum.minor_version);
}
CoreMessageFeatures features_;
};
// Serialize and de-serialize license response
TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(&params,
GetParam().response.major_version);
SetRequestVersion(&params);
// For v17, we do not use the hash to verify the request. However, the server
// needs to be backwards compatible, so it still needs to pass the hash into
// CreateCoreLiceseseResponse below. Save a copy of params.request_hash as it
// will be zero out during the test
uint8_t request_hash_read[ODK_SHA256_HASH_SIZE];
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
return ODK_ParseLicense(
buf, size + kExtraPayloadSize, size, params.initial_license_load,
params.usage_entry_present, 0, &(params.timer_limits),
&(params.clock_values), &(params.core_message.nonce_values),
&(params.parsed_license), nullptr);
};
ODK_Packing_ParsedLicense parsed_license;
parsed_license.enc_mac_keys_iv = params.parsed_license.enc_mac_keys_iv;
parsed_license.enc_mac_keys = params.parsed_license.enc_mac_keys;
parsed_license.pst = params.parsed_license.pst;
parsed_license.srm_restriction_data =
params.parsed_license.srm_restriction_data;
parsed_license.license_type = params.parsed_license.license_type;
parsed_license.nonce_required = params.parsed_license.nonce_required;
parsed_license.timer_limits = params.parsed_license.timer_limits;
parsed_license.watermarking = params.parsed_license.watermarking;
parsed_license.dtcp2_required = params.parsed_license.dtcp2_required;
parsed_license.renewal_delay_base = params.parsed_license.renewal_delay_base;
parsed_license.decenc_mitigation_option_used =
params.parsed_license.decenc_mitigation_option_used;
parsed_license.key_array_length = params.parsed_license.key_array_length;
std::vector<OEMCrypto_KeyObjectV2> key_array;
key_array.reserve(params.parsed_license.key_array_length);
for (size_t i = 0; i < params.parsed_license.key_array_length; i++) {
key_array.push_back(params.parsed_license.key_array[i]);
}
parsed_license.key_array = key_array.data();
const std::string request_hash_string(
reinterpret_cast<const char*>(request_hash_read),
sizeof(request_hash_read));
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
std::string* oemcrypto_core_message) {
return CreateCoreLicenseResponse(features_, parsed_license, core_request,
request_hash_string,
oemcrypto_core_message);
};
ValidateResponse<ODK_LicenseRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func,
kdo_prepare_func);
}
// Serialize and de-serialize license response with more keys than
// ODK_MAX_NUM_KEYS.
TEST_P(OdkVersionTest, LicenseResponseRoundtripMoreThanMaxKeys) {
if (!GetParam().should_accept_request) {
GTEST_SKIP() << "Skipping response check because request would be refused.";
}
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParams(&params,
GetParam().response.major_version);
SetRequestVersion(&params);
// For v17, we do not use the hash to verify the request. However, the server
// needs to be backwards compatible, so it still needs to pass the hash into
// CreateCoreLiceseseResponse below. Save a copy of params.request_hash as it
// will be zero out during the test
uint8_t request_hash_read[ODK_SHA256_HASH_SIZE];
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
std::vector<uint8_t> buf;
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf);
std::vector<uint8_t> zero(buf.size(), 0);
size_t bytes_read = 0;
// zero-out input
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_IterFields(ODK_READ, zero.data(), buf.size(), &bytes_read,
params.extra_fields));
// Parse buf with odk
const OEMCryptoResult parse_result = ODK_ParseLicense(
buf.data(), buf.size() + kExtraPayloadSize, buf.size(),
params.initial_license_load, params.usage_entry_present, 0,
&(params.timer_limits), &(params.clock_values),
&(params.core_message.nonce_values), &(params.parsed_license), nullptr);
EXPECT_EQ(OEMCrypto_SUCCESS, parse_result);
size_t size_out = 0;
if (parse_result != OEMCrypto_SUCCESS) {
ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf.data(), buf.size(), &size_out,
params.extra_fields);
}
ODK_Packing_ParsedLicense parsed_license;
parsed_license.enc_mac_keys_iv = params.parsed_license.enc_mac_keys_iv;
parsed_license.enc_mac_keys = params.parsed_license.enc_mac_keys;
parsed_license.pst = params.parsed_license.pst;
parsed_license.srm_restriction_data =
params.parsed_license.srm_restriction_data;
parsed_license.license_type = params.parsed_license.license_type;
parsed_license.nonce_required = params.parsed_license.nonce_required;
parsed_license.timer_limits = params.parsed_license.timer_limits;
parsed_license.watermarking = params.parsed_license.watermarking;
parsed_license.dtcp2_required = params.parsed_license.dtcp2_required;
parsed_license.renewal_delay_base = params.parsed_license.renewal_delay_base;
parsed_license.decenc_mitigation_option_used =
params.parsed_license.decenc_mitigation_option_used;
parsed_license.key_array_length = ODK_MAX_NUM_KEYS + 1;
std::vector<OEMCrypto_KeyObjectV2> key_array;
for (size_t i = 0; i < ODK_MAX_NUM_KEYS + 1; i++) {
OEMCrypto_KeyObjectV2 key = {
{0, 0}, {0, 0},
{0, 0}, {0, 0},
{0, 0}, {OEMCrypto_DeCENC_Mitigation_Option_None, {{{0, 0}, {0, 0}}}}};
key_array.push_back(key);
}
parsed_license.key_array = key_array.data();
const std::string request_hash_string(
reinterpret_cast<const char*>(request_hash_read),
sizeof(request_hash_read));
// serialize odk output to oemcrypto_core_message
std::string oemcrypto_core_message;
ODK_LicenseRequest core_request = {};
core_request.api_major_version = GetParam().request.major_version;
core_request.api_minor_version = GetParam().request.minor_version;
core_request.nonce = params.core_message.nonce_values.nonce;
core_request.session_id = params.core_message.nonce_values.session_id;
bool result =
CreateCoreLicenseResponse(features_, parsed_license, core_request,
request_hash_string, &oemcrypto_core_message);
EXPECT_EQ(GetParam().should_accept_request, result);
}
// Serialize and de-serialize license response
TEST_P(OdkVersionTest, LicenseResponseRoundtripDecencMitigation) {
ODK_LicenseResponseParams params;
ODK_SetDefaultLicenseResponseParamsDecencMitigation(
&params, GetParam().response.major_version,
GetParam().response.minor_version);
SetRequestVersion(&params);
// For v17, we do not use the hash to verify the request. However, the server
// needs to be backwards compatible, so it still needs to pass the hash into
// CreateCoreLiceseseResponse below. Save a copy of params.request_hash as it
// will be zero out during the test
uint8_t request_hash_read[ODK_SHA256_HASH_SIZE];
memcpy(request_hash_read, params.request_hash, sizeof(request_hash_read));
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
return ODK_ParseLicense(
buf, size + kExtraPayloadSize, size, params.initial_license_load,
params.usage_entry_present, 0, &(params.timer_limits),
&(params.clock_values), &(params.core_message.nonce_values),
&(params.parsed_license), nullptr);
};
ODK_Packing_ParsedLicense parsed_license;
parsed_license.enc_mac_keys_iv = params.parsed_license.enc_mac_keys_iv;
parsed_license.enc_mac_keys = params.parsed_license.enc_mac_keys;
parsed_license.pst = params.parsed_license.pst;
parsed_license.srm_restriction_data =
params.parsed_license.srm_restriction_data;
parsed_license.license_type = params.parsed_license.license_type;
parsed_license.nonce_required = params.parsed_license.nonce_required;
parsed_license.timer_limits = params.parsed_license.timer_limits;
parsed_license.watermarking = params.parsed_license.watermarking;
parsed_license.dtcp2_required = params.parsed_license.dtcp2_required;
parsed_license.renewal_delay_base = params.parsed_license.renewal_delay_base;
parsed_license.decenc_mitigation_option_used =
params.parsed_license.decenc_mitigation_option_used;
parsed_license.key_array_length = params.parsed_license.key_array_length;
std::vector<OEMCrypto_KeyObjectV2> key_array;
key_array.reserve(params.parsed_license.key_array_length);
for (size_t i = 0; i < params.parsed_license.key_array_length; i++) {
key_array.push_back(params.parsed_license.key_array[i]);
}
parsed_license.key_array = key_array.data();
const std::string request_hash_string(
reinterpret_cast<const char*>(request_hash_read),
sizeof(request_hash_read));
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
std::string* oemcrypto_core_message) {
return CreateCoreLicenseResponse(features_, parsed_license, core_request,
request_hash_string,
oemcrypto_core_message);
};
ValidateResponse<ODK_LicenseRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func,
kdo_prepare_func);
}
TEST_P(OdkVersionTest, RenewalResponseRoundtrip) {
if (!GetParam().should_accept_request) {
GTEST_SKIP() << "Skipping renewal test because request would be refused.";
}
ODK_RenewalResponseParams params;
ODK_SetDefaultRenewalResponseParams(&params);
SetRequestVersion(&params);
const uint64_t playback_clock = params.playback_clock;
const uint64_t renewal_duration = params.renewal_duration;
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
OEMCryptoResult err =
ODK_ParseRenewal(buf, size, size, &(params.core_message.nonce_values),
params.system_time, &(params.timer_limits),
&(params.clock_values), &(params.playback_timer));
EXPECT_EQ(ODK_SET_TIMER, err);
EXPECT_EQ(renewal_duration, params.playback_timer);
EXPECT_EQ(params.clock_values.time_when_timer_expires,
params.system_time + params.playback_timer);
return OEMCrypto_SUCCESS;
};
auto kdo_prepare_func = [&](ODK_RenewalRequest& core_request,
std::string* oemcrypto_core_message) {
core_request.playback_time_seconds = playback_clock;
return CreateCoreRenewalResponse(features_, core_request, renewal_duration,
oemcrypto_core_message);
};
ValidateResponse<ODK_RenewalRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func,
kdo_prepare_func);
}
TEST_P(OdkVersionTest, ReleaseResponseRoundtrip) {
if (!GetParam().should_accept_request) {
GTEST_SKIP() << "Skipping release test because request would be refused.";
}
ODK_ReleaseResponseParams params;
ODK_SetDefaultReleaseResponseParams(&params);
SetRequestVersion(&params);
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
return ODK_ParseRelease(buf, size, size,
&(params.core_message.nonce_values));
};
auto kdo_prepare_func = [&](ODK_ReleaseRequest& core_request,
std::string* oemcrypto_core_message) {
return CreateCoreReleaseResponse(features_, core_request,
oemcrypto_core_message);
};
ValidateResponse<ODK_ReleaseRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func,
kdo_prepare_func);
}
TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
ODK_ProvisioningResponseParams params;
ODK_SetDefaultProvisioningResponseParams(&params,
GetParam().response.major_version);
SetRequestVersion(&params);
// save a copy of params.device_id as it will be zero out during the test
const uint32_t device_id_length = params.device_id_length;
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX] = {0};
memcpy(device_id, params.device_id, device_id_length);
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
// This constant represents the additional space needed for the message
// length on top of the core message size.
constexpr size_t kProvResponsePayloadSize = 18;
OEMCryptoResult err =
ODK_ParseProvisioning(buf, size + kProvResponsePayloadSize, size,
&(params.core_message.nonce_values), device_id,
device_id_length, &(params.parsed_provisioning));
return err;
};
auto kdo_prepare_func = [&](ODK_ProvisioningRequest& core_request,
std::string* oemcrypto_core_message) {
// use device_id for V17 and V16
core_request.device_id.assign(reinterpret_cast<char*>(device_id),
device_id_length);
// use counter info for V18
memcpy(&core_request.counter_info, &params.counter_info,
sizeof(params.counter_info));
return CreateCoreProvisioningResponse(features_, params.parsed_provisioning,
core_request, oemcrypto_core_message);
};
ValidateResponse<ODK_ProvisioningRequest>(GetParam(), &(params.core_message),
params.extra_fields, odk_parse_func,
kdo_prepare_func);
}
TEST_P(OdkVersionTest, Provision40ResponseRoundtrip) {
ODK_Provisioning40ResponseParams params;
ODK_SetDefaultProvisioning40ResponseParams(&params);
SetRequestVersion(&params);
auto odk_parse_func = [&](const uint8_t* buf, size_t size) {
OEMCryptoResult err = ODK_ParseProvisioning40(
buf, size + 16, size, &(params.core_message.nonce_values));
return err;
};
auto kdo_prepare_func = [&](ODK_Provisioning40Request& core_request,
std::string* oemcrypto_core_message) {
return CreateCoreProvisioning40Response(features_, core_request,
oemcrypto_core_message);
};
ValidateResponse<ODK_Provisioning40Request>(
GetParam(), &(params.core_message), params.extra_fields, odk_parse_func,
kdo_prepare_func);
}
// If the minor version is positive, we can test an older minor version.
constexpr uint16_t kOldMinor =
ODK_MINOR_VERSION > 0 ? ODK_MINOR_VERSION - 1 : 0;
// Similarly, if this isn't the first major version, we can test an older major
// version.
constexpr uint16_t kOldMajor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION
? ODK_MAJOR_VERSION - 1
: ODK_FIRST_VERSION;
// If there is an older major, then we should accept any minor version.
// Otherwise, this test won't make sense and we should just use a minor of 0.
constexpr uint16_t kOldMajorMinor =
ODK_MAJOR_VERSION > ODK_FIRST_VERSION ? 42 : 0;
// List of major and minor versions to test. This list is a little bit fragile,
// everytime we release a new version the list has to be updated.
std::vector<VersionParameters> TestCases() {
const VersionPair latest(ODK_MAJOR_VERSION, ODK_MINOR_VERSION);
const VersionPair previous(ODK_MAJOR_VERSION, kOldMinor);
const VersionPair next_minor(ODK_MAJOR_VERSION, ODK_MINOR_VERSION + 1);
// The next major release with minor=0 is a prerelease.
const VersionPair next_major_prerelease(ODK_MAJOR_VERSION + 1, 0);
// The next major release with minor>0 is a release.
const VersionPair next_major_release(ODK_MAJOR_VERSION + 1, 42);
const VersionPair previous_major(kOldMajor, kOldMajorMinor);
const VersionPair latest_prerelease(ODK_MAJOR_VERSION, 0);
const VersionPair previous_prerelease(kOldMajor, 0);
const VersionPair latest_released(
CoreMessageFeatures::kDefaultFeatures.maximum_major_version,
CoreMessageFeatures::kDefaultFeatures.maximum_minor_version);
const VersionPair v16(16, 5);
const VersionPair v17(17, 8);
const VersionPair v18(18, 10);
const VersionPair v19(19, 6);
const VersionPair v20_prerelease(20, 0);
const VersionPair v20(20, 1);
std::vector<VersionParameters> test_cases{
// Fields: maximum, prerelease, request, response, should_accept_request.
{latest, true, latest, latest, true},
{latest, true, next_minor, latest, true},
{latest, true, previous, previous, true},
{latest, true, previous_major, previous_major, true},
{latest, true, next_minor, latest, true},
{latest, true, next_major_prerelease, latest, true},
{latest, true, next_major_release, latest, true},
{latest, true, latest_prerelease, latest_prerelease, true},
{latest, true, previous_prerelease, previous_prerelease, true},
{v16, true, latest, v16, true},
{v17, true, latest, v17, true},
{v18, true, latest, v18, true},
{v19, true, latest, v19, true},
{latest, true, v16, v16, true},
{latest, true, v17, v17, true},
{latest, true, v18, v18, true},
{latest, true, v19, v19, true},
{latest, true, v20_prerelease, v20_prerelease, true},
{latest, true, v20, latest, true}, // Change this when v20.1 is released.
// From here on, the serve is restricted to the released version.
{latest_released, false, v16, v16, true},
{latest_released, false, v17, v17, true},
{latest_released, false, v18, v18, true},
{latest_released, false, v19, v19, true},
// TODO(b/403381396): change the response version to v20 after v20 has
// been released.
{latest_released, false, v20, latest_released, true},
{latest_released, false, next_minor, latest_released, true},
// Prerelease requests should not be accepted.
{latest_released, false, v20_prerelease, v20_prerelease, false},
{latest_released, false, latest_prerelease, latest_prerelease, false},
// Future pre-release and release are OK, for back compat testing.
{latest_released, false, next_major_prerelease, latest_released, true},
{latest_released, false, next_major_release, latest_released, true},
};
return test_cases;
}
INSTANTIATE_TEST_SUITE_P(OdkVersionTests, OdkVersionTest,
::testing::ValuesIn(TestCases()));
TEST(OdkSizeTest, LicenseRequest) {
uint8_t* message = nullptr;
size_t message_length = 0;
size_t core_message_length = 0;
uint16_t api_minor_version = ODK_MINOR_VERSION;
uint16_t api_major_version = 0;
uint32_t nonce = 0;
uint32_t session_id = 0;
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
uint16_t decenc_mitigation_options_supported = 0;
ODK_NonceValues nonce_values{api_minor_version, api_major_version, nonce,
session_id};
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_PrepareCoreLicenseRequest(
message, message_length, &core_message_length, &nonce_values,
&counter_info, decenc_mitigation_options_supported));
// the core_message_length should be appropriately set
if (nonce_values.api_major_version > 17) {
EXPECT_EQ(ODK_LICENSE_REQUEST_SIZE, core_message_length);
} else {
EXPECT_EQ(ODK_LICENSE_REQUEST_SIZE_V17, core_message_length);
}
}
TEST(OdkSizeTest, RenewalRequest) {
uint8_t* message = nullptr;
size_t message_length = 0;
size_t core_message_length = 0;
uint16_t api_minor_version = ODK_MINOR_VERSION;
uint16_t api_major_version = ODK_MAJOR_VERSION;
uint32_t nonce = 0;
uint32_t session_id = 0;
ODK_ClockValues clock_values = {};
clock_values.time_of_first_decrypt = 10;
clock_values.timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED;
uint64_t system_time_seconds = 15;
ODK_NonceValues nonce_values{api_minor_version, api_major_version, nonce,
session_id};
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_PrepareCoreRenewalRequest(message, message_length,
&core_message_length, &nonce_values,
&clock_values, system_time_seconds));
// the core_message_length should be appropriately set
EXPECT_EQ(ODK_RENEWAL_REQUEST_SIZE, core_message_length);
}
TEST(OdkSizeTest, ReleaseRequest) {
uint8_t* message = nullptr;
size_t message_length = 0;
size_t core_message_length = 0;
uint16_t api_minor_version = ODK_MINOR_VERSION;
uint16_t api_major_version = 0;
uint32_t nonce = 0;
uint32_t session_id = 0;
ODK_ClockValues clock_values = {};
clock_values.time_of_first_decrypt = 10;
clock_values.timer_status = ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE;
uint64_t system_time_seconds = 15;
ODK_NonceValues nonce_values{api_minor_version, api_major_version, nonce,
session_id};
EXPECT_EQ(OEMCrypto_SUCCESS,
ODK_PrepareCoreRenewalRequest(message, message_length,
&core_message_length, &nonce_values,
&clock_values, system_time_seconds));
// Release requests do not have a core message.
EXPECT_GE(core_message_length, 0u);
}
TEST(OdkSizeTest, ProvisioningRequest) {
uint8_t* message = nullptr;
size_t message_length = 0;
size_t core_message_length = 0;
uint16_t api_minor_version = ODK_MINOR_VERSION;
uint16_t api_major_version = 0;
uint32_t nonce = 0;
uint32_t session_id = 0;
ODK_MessageCounterInfo counter_info;
memset(&counter_info, 0, sizeof(counter_info));
ODK_NonceValues nonce_values{api_minor_version, api_major_version, nonce,
session_id};
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_PrepareCoreProvisioningRequest(message, message_length,
&core_message_length,
&nonce_values, &counter_info));
// the core_message_length should be appropriately set
if (nonce_values.api_major_version > 17) {
EXPECT_EQ(ODK_PROVISIONING_REQUEST_SIZE, core_message_length);
} else {
EXPECT_EQ(ODK_PROVISIONING_REQUEST_SIZE_V17, core_message_length);
}
}
// Verify the version string contains the right version numbers.
TEST(OdkTest, CheckReleaseVersion) {
// Here are the version numbers.
std::string expected_version = std::to_string(ODK_MAJOR_VERSION) + "." +
std::to_string(ODK_MINOR_VERSION);
// Here is the version string.
EXPECT_NE(std::string(ODK_RELEASE_DATE).find(expected_version),
std::string::npos)
<< "Version mismatch in odk_structs.h";
}
TEST(OdkOverflowTest, SubtractU64) {
uint64_t result = 0;
EXPECT_FALSE(odk_sub_overflow_u64(10, 5, &result));
EXPECT_EQ(result, static_cast<uint64_t>(10 - 5));
EXPECT_TRUE(odk_sub_overflow_u64(5, 10, &result));
}
TEST(OdkOverflowTest, AddU64) {
uint64_t result = 0;
EXPECT_FALSE(odk_add_overflow_u64(2, 2, &result));
EXPECT_EQ(result, static_cast<uint64_t>(2 + 2));
EXPECT_TRUE(odk_add_overflow_u64(0xffffffffffffffff, 1, &result));
EXPECT_TRUE(odk_add_overflow_u64(1, 0xffffffffffffffff, &result));
}
TEST(OdkOverflowTest, AddUX) {
size_t result = 0;
EXPECT_FALSE(odk_add_overflow_ux(2, 2, &result));
EXPECT_EQ(result, static_cast<uint64_t>(2 + 2));
EXPECT_TRUE(odk_add_overflow_ux(SIZE_MAX, 1, &result));
EXPECT_TRUE(odk_add_overflow_ux(1, SIZE_MAX, &result));
}
TEST(OdkOverflowTest, MultiplyUX) {
size_t result = 0;
EXPECT_FALSE(odk_mul_overflow_ux(2, 7, &result));
EXPECT_EQ(result, static_cast<uint64_t>(2 * 7));
EXPECT_TRUE(odk_mul_overflow_ux(SIZE_MAX >> 1, 4, &result));
EXPECT_TRUE(odk_mul_overflow_ux(4, SIZE_MAX >> 1, &result));
}
TEST(OdkTest, GenerateKeyContexts_Success) {
const uint8_t kContext[] = {
0x0a, 0x4c, 0x08, 0x00, 0x12, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x10, 0x19, 0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1, 0x22, 0x67,
0x80, 0x53, 0x36, 0x21, 0x36, 0xbd, 0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4,
0xc2, 0xd8, 0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64, 0x6e, 0x58,
0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8, 0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a,
0x14, 0xa8, 0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64, 0x0b, 0xd2,
0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39, 0x12, 0x25, 0x0a, 0x23, 0x0a, 0x14,
0x08, 0x01, 0x12, 0x10, 0x09, 0x15, 0x00, 0x7c, 0xaa, 0x9b, 0x59, 0x31,
0xb7, 0x6a, 0x3a, 0x85, 0xf0, 0x46, 0x52, 0x3e, 0x10, 0x01, 0x1a, 0x09,
0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x18, 0x01, 0x20,
0x00, 0x2a, 0x0c, 0x31, 0x38, 0x38, 0x36, 0x37, 0x38, 0x37, 0x34, 0x30,
0x35, 0x00, 0x00,
};
const uint8_t kMacKey[] = {
0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x49,
0x4f, 0x4e, 0x00, 0x0a, 0x4c, 0x08, 0x00, 0x12, 0x48, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x10, 0x19, 0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95,
0xc1, 0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd, 0xf8, 0x40, 0x8f,
0x82, 0x76, 0xe4, 0xc2, 0xd8, 0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f,
0x64, 0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8, 0x99, 0xb3, 0xe4,
0x64, 0x18, 0x9a, 0x14, 0xa8, 0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70,
0x64, 0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39, 0x12, 0x25, 0x0a,
0x23, 0x0a, 0x14, 0x08, 0x01, 0x12, 0x10, 0x09, 0x15, 0x00, 0x7c, 0xaa,
0x9b, 0x59, 0x31, 0xb7, 0x6a, 0x3a, 0x85, 0xf0, 0x46, 0x52, 0x3e, 0x10,
0x01, 0x1a, 0x09, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
0x18, 0x01, 0x20, 0x00, 0x2a, 0x0c, 0x31, 0x38, 0x38, 0x36, 0x37, 0x38,
0x37, 0x34, 0x30, 0x35, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
};
const uint8_t kEncKey[] = {
0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x0a,
0x4c, 0x08, 0x00, 0x12, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10,
0x19, 0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1, 0x22, 0x67, 0x80,
0x53, 0x36, 0x21, 0x36, 0xbd, 0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2,
0xd8, 0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64, 0x6e, 0x58, 0x73,
0x49, 0x30, 0xac, 0xeb, 0xe8, 0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14,
0xa8, 0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64, 0x0b, 0xd2, 0x2e,
0xf4, 0x4b, 0x2d, 0x7e, 0x39, 0x12, 0x25, 0x0a, 0x23, 0x0a, 0x14, 0x08,
0x01, 0x12, 0x10, 0x09, 0x15, 0x00, 0x7c, 0xaa, 0x9b, 0x59, 0x31, 0xb7,
0x6a, 0x3a, 0x85, 0xf0, 0x46, 0x52, 0x3e, 0x10, 0x01, 0x1a, 0x09, 0x39,
0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x18, 0x01, 0x20, 0x00,
0x2a, 0x0c, 0x31, 0x38, 0x38, 0x36, 0x37, 0x38, 0x37, 0x34, 0x30, 0x35,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
};
std::vector<uint8_t> mac_key(sizeof(kMacKey) + 24);
std::vector<uint8_t> enc_key(sizeof(kEncKey) + 24);
size_t mac_key_size = mac_key.size();
size_t enc_key_size = enc_key.size();
ASSERT_EQ(OEMCrypto_SUCCESS,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), &mac_key[0],
&mac_key_size, &enc_key[0], &enc_key_size));
ASSERT_EQ(mac_key_size, sizeof(kMacKey));
ASSERT_EQ(enc_key_size, sizeof(kEncKey));
mac_key.resize(mac_key_size);
enc_key.resize(enc_key_size);
EXPECT_EQ(std::vector<uint8_t>(kMacKey, kMacKey + sizeof(kMacKey)), mac_key);
EXPECT_EQ(std::vector<uint8_t>(kEncKey, kEncKey + sizeof(kEncKey)), enc_key);
}
TEST(OdkTest, GenerateKeyContexts_ShortBuffer) {
const uint8_t kContext[] = {1, 2, 3};
size_t mac_key_size = 0;
size_t enc_key_size = 0;
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), nullptr,
&mac_key_size, nullptr, &enc_key_size));
EXPECT_EQ(mac_key_size, sizeof(kContext) + 19);
EXPECT_EQ(enc_key_size, sizeof(kContext) + 15);
}
TEST(OdkTest, GenerateKeyContexts_ShortBufferMacOnly) {
const uint8_t kContext[] = {1, 2, 3};
uint8_t buffer[128];
size_t mac_key_size = 0;
size_t enc_key_size = sizeof(buffer);
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), nullptr,
&mac_key_size, buffer, &enc_key_size));
EXPECT_EQ(mac_key_size, sizeof(kContext) + 19);
EXPECT_EQ(enc_key_size, sizeof(kContext) + 15);
}
TEST(OdkTest, GenerateKeyContexts_ShortBufferEncOnly) {
const uint8_t kContext[] = {1, 2, 3};
uint8_t buffer[128];
size_t mac_key_size = sizeof(buffer);
size_t enc_key_size = 0;
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer,
&mac_key_size, buffer, &enc_key_size));
EXPECT_EQ(mac_key_size, sizeof(kContext) + 19);
EXPECT_EQ(enc_key_size, sizeof(kContext) + 15);
}
TEST(OdkTest, GenerateKeyContexts_NullArgs) {
const uint8_t kContext[] = {1, 2, 3};
uint8_t buffer[24];
size_t buffer_size = sizeof(buffer);
size_t buffer_size2 = sizeof(buffer);
EXPECT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT,
ODK_GenerateKeyContexts(nullptr, sizeof(kContext), buffer,
&buffer_size, buffer, &buffer_size2));
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), nullptr,
&buffer_size, buffer, &buffer_size2));
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
EXPECT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer, nullptr,
buffer, &buffer_size2));
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer,
&buffer_size, nullptr, &buffer_size2));
buffer_size = buffer_size2 = sizeof(buffer); // Update to avoid short buffer.
EXPECT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT,
ODK_GenerateKeyContexts(kContext, sizeof(kContext), buffer,
&buffer_size, buffer, nullptr));
}
} // namespace
} // namespace wvodk_test