// 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 #include #include #include #include #include #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::CoreReleaseRequestFromMessage; 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 VersionParameters { uint32_t maximum_major_version; uint16_t request_major_version; uint16_t request_minor_version; uint16_t response_major_version; uint16_t response_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=v" << p.maximum_major_version << ", request = v" << p.request_major_version << "." << p.request_minor_version << ", response = v" << p.response_major_version << "." << p.response_minor_version; } 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 void ValidateRequest(uint32_t message_type, const std::vector& 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 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 uint8_t* buf = new uint8_t[message_size]{}; EXPECT_EQ(OEMCrypto_SUCCESS, odk_prepare_func(buf, &core_message_length, &nonce_values)); EXPECT_EQ(core_message_length, message_size); uint8_t* buf_expected = new uint8_t[message_size]{}; size_t buf_len_expected = 0; EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_WRITE, buf_expected, SIZE_MAX, &buf_len_expected, total_fields)); EXPECT_EQ(buf_len_expected, message_size); EXPECT_NO_FATAL_FAILURE( ODK_ExpectEqualBuf(buf_expected, buf, 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(buf), 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; uint8_t* buf2 = new uint8_t[message_size]{}; EXPECT_EQ(OEMCrypto_SUCCESS, odk_prepare_func(buf2, &core_message_length, &nonce_values)); EXPECT_EQ(core_message_length, message_size); EXPECT_NO_FATAL_FAILURE( ODK_ExpectEqualBuf(buf, buf2, message_size, total_fields)); delete[] buf; delete[] buf_expected; delete[] buf2; } /** * Template arguments: * T: kdo input struct * F: odk deserializer * G: kdo serializer */ template void ValidateResponse(const VersionParameters& versions, ODK_CoreMessage* core_message, const std::vector& 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; uint8_t* buf = nullptr; uint32_t buf_size = 0; ODK_BuildMessageBuffer(core_message, extra_fields, &buf, &buf_size); uint8_t* zero = new uint8_t[buf_size]{}; size_t bytes_read = 0; // zero-out input EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero, buf_size, &bytes_read, extra_fields)); // Parse buf with odk const OEMCryptoResult parse_result = odk_parse_func(buf, 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, buf_size, &size_out, extra_fields); } // serialize odk output to oemcrypto_core_message std::string oemcrypto_core_message; EXPECT_TRUE(kdo_prepare_func(t, &oemcrypto_core_message)); // verify round-trip works EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(buf, oemcrypto_core_message.data(), buf_size, extra_fields)); delete[] buf; delete[] zero; } 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 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 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 fields(n); std::srand(0); size_t total_size = 0; for (int i = 0; i < n; i++) { fields[i].type = static_cast( std::rand() % (static_cast(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); } uint8_t* buf = new uint8_t[total_size]{}; for (size_t i = 0; i < total_size; i++) { buf[i] = std::rand() & 0xff; } size_t bytes_read = 0, bytes_written = 0; uint8_t* buf2 = new uint8_t[total_size]{}; ODK_IterFields(ODK_READ, buf, total_size, &bytes_read, fields); EXPECT_EQ(bytes_read, total_size); ODK_IterFields(ODK_WRITE, buf2, total_size, &bytes_written, fields); EXPECT_EQ(bytes_written, total_size); EXPECT_NO_FATAL_FAILURE(ODK_ExpectEqualBuf(buf, buf2, total_size, fields)); // cleanup for (int i = 0; i < n; i++) { free(fields[i].value); } delete[] buf; delete[] buf2; } 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)); // Assert that nullptr does not cause a core dump. EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreLicenseRequest(nullptr, 0uL, nullptr, &nonce_values, &counter_info)); EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreLicenseRequest(nullptr, 0uL, &core_message_length, nullptr, &counter_info)); EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, ODK_PrepareCoreLicenseRequest(nullptr, 0uL, &core_message_length, &nonce_values, nullptr)); 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)); EXPECT_EQ(OEMCrypto_SUCCESS, ODK_PrepareCoreLicenseRequest( license_message, sizeof(license_message), &core_message_length, &nonce_values, &counter_info)); } 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)); // 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)); // 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)); } 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, 0xff, sizeof(counter_info.soc_vendor)); memset(counter_info.chipset_model, 0xdd, sizeof(counter_info.chipset_model)); memset(counter_info.extra, 0xee, sizeof(counter_info.extra)); std::vector extra_fields = { {ODK_MESSAGECOUNTER, &counter_info, "counter_info"}, }; 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); }; 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_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 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_Renewal_Request_Type, extra_fields, odk_prepare_func, kdo_parse_func); } TEST(OdkTest, ReleaseRequestRoundTrip) { const uint32_t clock_security_level = 1; const uint32_t status = 1; constexpr uint64_t system_time_seconds = 0xBADDCAFE000FF1CE; uint64_t playback_time = 0xCAFE00000000; const int64_t seconds_since_license_requested = 1; const int64_t seconds_since_first_decrypt = static_cast(system_time_seconds - playback_time); ODK_ClockValues clock_values; memset(&clock_values, 0, sizeof(clock_values)); clock_values.time_of_first_decrypt = seconds_since_first_decrypt; std::vector extra_fields = {}; auto odk_prepare_func = [&](uint8_t* const buf, size_t* size, ODK_NonceValues* nonce_values) { return ODK_PrepareCoreReleaseRequest( buf, SIZE_MAX, size, nonce_values, status, clock_security_level, seconds_since_license_requested, seconds_since_first_decrypt, &clock_values, system_time_seconds); }; auto kdo_parse_func = [&](const std::string& oemcrypto_core_message, ODK_ReleaseRequest* core_release_request) { bool ok = CoreReleaseRequestFromMessage(oemcrypto_core_message, core_release_request); return ok; }; ValidateRequest(ODK_Release_Request_Type, extra_fields, odk_prepare_func, kdo_parse_func); } 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, 0xff, sizeof(counter_info.soc_vendor)); memset(counter_info.chipset_model, 0xdd, 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 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_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, 0xff, sizeof(counter_info.soc_vendor)); memset(counter_info.chipset_model, 0xdd, sizeof(counter_info.chipset_model)); memset(counter_info.extra, 0xee, sizeof(counter_info.extra)); std::vector 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_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 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_Renewed_Provisioning_Request_Type, extra_fields, odk_prepare_func, kdo_parse_func); } TEST(OdkTest, ParseLicenseErrorNonce) { ODK_LicenseResponseParams params; ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION); uint8_t* buf = nullptr; uint32_t buf_size = 0; ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf, &buf_size); // temporarily mess up with nonce params.core_message.nonce_values.nonce = 0; OEMCryptoResult err = ODK_ParseLicense( buf, 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); delete[] buf; } TEST(OdkTest, ParseLicenseErrorUsageEntry) { ODK_LicenseResponseParams params; ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION); uint8_t* buf = nullptr; uint32_t buf_size = 0; ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf, &buf_size); params.usage_entry_present = false; OEMCryptoResult err = ODK_ParseLicense( buf, 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); delete[] buf; } TEST(OdkTest, ParseLicenseNullSubstring) { ODK_LicenseResponseParams params; ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION); params.parsed_license.srm_restriction_data.offset = 0; params.parsed_license.srm_restriction_data.length = 0; uint8_t* buf = nullptr; uint32_t buf_size = 0; ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf, &buf_size); OEMCryptoResult result = ODK_ParseLicense( buf, 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); delete[] buf; } TEST(OdkTest, ParseLicenseErrorSubstringOffset) { // offset out of range ODK_LicenseResponseParams params; ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION); params.parsed_license.enc_mac_keys_iv.offset = 1024; uint8_t* buf = nullptr; uint32_t buf_size = 0; ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf, &buf_size); OEMCryptoResult err = ODK_ParseLicense( buf, 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); delete[] buf; // offset + length out of range err = OEMCrypto_SUCCESS; ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION); params.parsed_license.enc_mac_keys_iv.length = buf_size; buf = nullptr; buf_size = 0; ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf, &buf_size); err = ODK_ParseLicense( buf, 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); delete[] buf; } TEST(OdkTest, ParseRenewalErrorTimer) { ODK_RenewalResponseParams params; ODK_SetDefaultRenewalResponseParams(¶ms); uint8_t* buf = nullptr; uint32_t buf_size = 0; ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf, &buf_size); // 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, 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); delete[] buf; } 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 = CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION); std::string oemcrypto_core_message; EXPECT_TRUE(CreateCoreProvisioningResponseFromProto( features, serialized_provisioning_resp, core_request, OEMCrypto_RSA_Private_Key, &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 = CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION); std::string oemcrypto_core_message; EXPECT_TRUE(CreateCoreProvisioningResponseFromProto( features, serialized_provisioning_resp, core_request, OEMCrypto_RSA_Private_Key, &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, 48u); 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 { protected: template 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; if (GetParam().maximum_major_version > 0) { features_ = CoreMessageFeatures::DefaultFeatures( GetParam().maximum_major_version); } else { features_ = CoreMessageFeatures::kDefaultFeatures; } } CoreMessageFeatures features_; }; // Serialize and de-serialize license response TEST_P(OdkVersionTest, LicenseResponseRoundtrip) { ODK_LicenseResponseParams params; ODK_SetDefaultLicenseResponseParams(¶ms, GetParam().response_major_version); SetRequestVersion(¶ms); // 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.key_array_length = params.parsed_license.key_array_length; std::vector key_array; 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(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(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) { ODK_LicenseResponseParams params; ODK_SetDefaultLicenseResponseParams(¶ms, GetParam().response_major_version); SetRequestVersion(¶ms); // 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)); uint8_t* buf = nullptr; uint32_t buf_size = 0; ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf, &buf_size); uint8_t* zero = new uint8_t[buf_size]{}; size_t bytes_read = 0; // zero-out input EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero, buf_size, &bytes_read, params.extra_fields)); // Parse buf with odk const OEMCryptoResult parse_result = ODK_ParseLicense( buf, 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, 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.key_array_length = ODK_MAX_NUM_KEYS + 1; std::vector key_array; for (size_t i = 0; i < ODK_MAX_NUM_KEYS + 1; i++) { OEMCrypto_KeyObject key = {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}; key_array.push_back(key); } parsed_license.key_array = key_array.data(); const std::string request_hash_string( reinterpret_cast(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_TRUE(result); delete[] buf; delete[] zero; } TEST_P(OdkVersionTest, RenewalResponseRoundtrip) { ODK_RenewalResponseParams params; ODK_SetDefaultRenewalResponseParams(¶ms); SetRequestVersion(¶ms); 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(GetParam(), &(params.core_message), params.extra_fields, odk_parse_func, kdo_prepare_func); } TEST_P(OdkVersionTest, ReleaseResponseRoundtrip) { ODK_ReleaseResponseParams params; ODK_SetDefaultReleaseResponseParams(¶ms); SetRequestVersion(¶ms); const int64_t seconds_since_license_requested = params.seconds_since_license_requested; const int64_t seconds_since_first_decrypt = params.seconds_since_first_decrypt; auto odk_parse_func = [&](const uint8_t* buf, size_t size) { OEMCryptoResult err = ODK_ParseRelease(buf, size, size, &(params.core_message.nonce_values)); return err; }; auto kdo_prepare_func = [&](ODK_ReleaseRequest& core_request, std::string* oemcrypto_core_message) { return CreateCoreReleaseResponse( features_, core_request, seconds_since_license_requested, seconds_since_first_decrypt, oemcrypto_core_message); }; ValidateResponse(GetParam(), &(params.core_message), params.extra_fields, odk_parse_func, kdo_prepare_func); } TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) { ODK_ProvisioningResponseParams params; ODK_SetDefaultProvisioningResponseParams(¶ms, GetParam().response_major_version); SetRequestVersion(¶ms); // 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) { OEMCryptoResult err = ODK_ParseProvisioning( buf, size + 16, 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(device_id), device_id_length); // use counter info for V18 memcpy(&core_request.counter_info, ¶ms.counter_info, sizeof(params.counter_info)); return CreateCoreProvisioningResponse(features_, params.parsed_provisioning, core_request, oemcrypto_core_message); }; ValidateResponse(GetParam(), &(params.core_message), params.extra_fields, odk_parse_func, kdo_prepare_func); } TEST_P(OdkVersionTest, Provision40ResponseRoundtrip) { ODK_Provisioning40ResponseParams params; ODK_SetDefaultProvisioning40ResponseParams(¶ms); SetRequestVersion(¶ms); 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( 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. const 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. const 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. const uint16_t kOldMajorMinor = ODK_MAJOR_VERSION > ODK_FIRST_VERSION ? 42 : 0; // List of major and minor versions to test. std::vector TestCases() { std::vector test_cases{ // Fields: maximum major version, // request major, request minor, response major, response minor, {ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, ODK_MAJOR_VERSION, ODK_MINOR_VERSION}, {ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, ODK_MINOR_VERSION + 1, ODK_MAJOR_VERSION, ODK_MINOR_VERSION}, {ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, kOldMinor, ODK_MAJOR_VERSION, kOldMinor}, {ODK_MAJOR_VERSION, ODK_MAJOR_VERSION, 0, ODK_MAJOR_VERSION, 0}, {ODK_MAJOR_VERSION, ODK_MAJOR_VERSION + 1, 42, ODK_MAJOR_VERSION, ODK_MINOR_VERSION}, {ODK_MAJOR_VERSION, kOldMajor, 0, kOldMajor, 0}, {ODK_MAJOR_VERSION, kOldMajor, kOldMajorMinor, kOldMajor, kOldMajorMinor}, // If the server is restricted to v16, then the response can be at // most 16.5 // These tests cases must be updated whenever we roll the minor version // number. {16, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 16, 5}, {17, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 17, 2}, {18, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 18, 4}, {19, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 19, 6}, // Here are some known good versions. Make extra sure they work. {ODK_MAJOR_VERSION, 16, 3, 16, 3}, {ODK_MAJOR_VERSION, 16, 4, 16, 4}, {ODK_MAJOR_VERSION, 16, 5, 16, 5}, {ODK_MAJOR_VERSION, 17, 1, 17, 1}, {ODK_MAJOR_VERSION, 17, 2, 17, 2}, {ODK_MAJOR_VERSION, 18, 1, 18, 1}, {ODK_MAJOR_VERSION, 18, 2, 18, 2}, {ODK_MAJOR_VERSION, 18, 3, 18, 3}, {ODK_MAJOR_VERSION, 19, 0, 19, 0}, {ODK_MAJOR_VERSION, 19, 1, 19, 1}, {ODK_MAJOR_VERSION, 19, 2, 19, 2}, {ODK_MAJOR_VERSION, 19, 3, 19, 3}, {ODK_MAJOR_VERSION, 19, 4, 19, 4}, {ODK_MAJOR_VERSION, 19, 5, 19, 5}, {ODK_MAJOR_VERSION, 19, 6, 19, 6}, {0, 16, 3, 16, 3}, {0, 16, 4, 16, 4}, {0, 16, 5, 16, 5}, {0, 17, 1, 17, 1}, {0, 17, 2, 17, 2}, {0, 18, 3, 18, 3}, {0, 18, 4, 18, 4}, {0, 19, 0, 19, 0}, {0, 19, 1, 19, 1}, {0, 19, 2, 19, 2}, {0, 19, 3, 19, 3}, {0, 19, 4, 19, 4}, {0, 19, 5, 19, 5}, {0, 19, 6, 19, 6}, }; 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)); 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)); // 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(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(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(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(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 mac_key(sizeof(kMacKey) + 24); std::vector 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(kMacKey, kMacKey + sizeof(kMacKey)), mac_key); EXPECT_EQ(std::vector(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