Merge latest oemcrypto-v17 change
No-Typo-Check: Not related to this change. Bug: 161477208 Change-Id: I99e4780f6855b7045aa0cd5a49c13d2d0d51ed64
This commit is contained in:
committed by
Fred Gylys-Colwell
parent
c924960962
commit
642965c678
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "core_message_deserialize.h"
|
||||
#include "core_message_features.h"
|
||||
#include "core_message_serialize.h"
|
||||
#include "core_message_types.h"
|
||||
#include "gtest/gtest.h"
|
||||
@@ -27,12 +28,34 @@ using oemcrypto_core_message::deserialize::CoreLicenseRequestFromMessage;
|
||||
using oemcrypto_core_message::deserialize::CoreProvisioningRequestFromMessage;
|
||||
using oemcrypto_core_message::deserialize::CoreRenewalRequestFromMessage;
|
||||
|
||||
using oemcrypto_core_message::features::CoreMessageFeatures;
|
||||
|
||||
using oemcrypto_core_message::serialize::CreateCoreLicenseResponse;
|
||||
using oemcrypto_core_message::serialize::CreateCoreProvisioningResponse;
|
||||
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;
|
||||
}
|
||||
|
||||
template <typename T, typename F, typename G>
|
||||
void ValidateRequest(uint32_t message_type,
|
||||
const std::vector<ODK_Field>& extra_fields,
|
||||
@@ -111,12 +134,13 @@ void ValidateRequest(uint32_t message_type,
|
||||
* G: kdo serializer
|
||||
*/
|
||||
template <typename T, typename F, typename G>
|
||||
void ValidateResponse(ODK_CoreMessage* core_message,
|
||||
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_minor_version = core_message->nonce_values.api_minor_version;
|
||||
t.api_major_version = core_message->nonce_values.api_major_version;
|
||||
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;
|
||||
|
||||
@@ -130,12 +154,15 @@ void ValidateResponse(ODK_CoreMessage* core_message,
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, ODK_IterFields(ODK_READ, zero, buf_size,
|
||||
&bytes_read, extra_fields));
|
||||
|
||||
// parse buf with odk
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, odk_parse_func(buf, buf_size));
|
||||
// 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;
|
||||
ODK_IterFields(ODK_FieldMode::ODK_DUMP, buf, buf_size, &size_out,
|
||||
extra_fields);
|
||||
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;
|
||||
@@ -249,7 +276,6 @@ TEST(OdkTest, NullResponseTest) {
|
||||
constexpr size_t message_size = 64;
|
||||
uint8_t message[message_size] = {0};
|
||||
size_t core_message_length = message_size;
|
||||
uint8_t request_hash[ODK_SHA256_HASH_SIZE] = {0};
|
||||
ODK_TimerLimits timer_limits;
|
||||
ODK_ParsedLicense parsed_license;
|
||||
ODK_NonceValues nonce_values;
|
||||
@@ -258,30 +284,26 @@ TEST(OdkTest, NullResponseTest) {
|
||||
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, request_hash, &timer_limits, &clock_values,
|
||||
&nonce_values, nullptr));
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
||||
true, request_hash, &timer_limits, &clock_values,
|
||||
nullptr, &parsed_license));
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
||||
true, request_hash, &timer_limits, nullptr,
|
||||
&nonce_values, &parsed_license));
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
||||
true, request_hash, nullptr, &clock_values,
|
||||
&nonce_values, &parsed_license));
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true,
|
||||
true, nullptr, &timer_limits, &clock_values,
|
||||
&nonce_values, &parsed_license));
|
||||
EXPECT_EQ(
|
||||
ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||
&timer_limits, &clock_values, &nonce_values, nullptr));
|
||||
EXPECT_EQ(
|
||||
ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||
&timer_limits, &clock_values, nullptr, &parsed_license));
|
||||
EXPECT_EQ(
|
||||
ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||
&timer_limits, nullptr, &nonce_values, &parsed_license));
|
||||
EXPECT_EQ(
|
||||
ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(message, message_size, core_message_length, true, true,
|
||||
nullptr, &clock_values, &nonce_values, &parsed_license));
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE,
|
||||
ODK_ParseLicense(nullptr, message_size, core_message_length, true,
|
||||
true, request_hash, &timer_limits, &clock_values,
|
||||
&nonce_values, &parsed_license));
|
||||
true, &timer_limits, &clock_values, &nonce_values,
|
||||
&parsed_license));
|
||||
|
||||
constexpr uint64_t system_time = 0;
|
||||
uint64_t timer_value = 0;
|
||||
@@ -477,7 +499,7 @@ TEST(OdkTest, ProvisionRequestRoundtrip) {
|
||||
|
||||
TEST(OdkTest, ParseLicenseErrorNonce) {
|
||||
ODK_LicenseResponseParams params;
|
||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
||||
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
|
||||
uint8_t* buf = nullptr;
|
||||
uint32_t buf_size = 0;
|
||||
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||
@@ -486,7 +508,7 @@ TEST(OdkTest, ParseLicenseErrorNonce) {
|
||||
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, params.request_hash, &(params.timer_limits),
|
||||
params.usage_entry_present, &(params.timer_limits),
|
||||
&(params.clock_values), &(params.core_message.nonce_values),
|
||||
&(params.parsed_license));
|
||||
EXPECT_EQ(OEMCrypto_ERROR_INVALID_NONCE, err);
|
||||
@@ -495,7 +517,7 @@ TEST(OdkTest, ParseLicenseErrorNonce) {
|
||||
|
||||
TEST(OdkTest, ParseLicenseErrorUsageEntry) {
|
||||
ODK_LicenseResponseParams params;
|
||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
||||
ODK_SetDefaultLicenseResponseParams(¶ms, ODK_MAJOR_VERSION);
|
||||
uint8_t* buf = nullptr;
|
||||
uint32_t buf_size = 0;
|
||||
ODK_BuildMessageBuffer(&(params.core_message), params.extra_fields, &buf,
|
||||
@@ -503,25 +525,59 @@ TEST(OdkTest, ParseLicenseErrorUsageEntry) {
|
||||
params.usage_entry_present = false;
|
||||
OEMCryptoResult err = ODK_ParseLicense(
|
||||
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
||||
params.usage_entry_present, params.request_hash, &(params.timer_limits),
|
||||
params.usage_entry_present, &(params.timer_limits),
|
||||
&(params.clock_values), &(params.core_message.nonce_values),
|
||||
&(params.parsed_license));
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
TEST(OdkTest, ParseLicenseErrorRequestHash) {
|
||||
TEST(OdkTest, ParseLicenseNullSubstring) {
|
||||
ODK_LicenseResponseParams params;
|
||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
||||
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, &(params.timer_limits),
|
||||
&(params.clock_values), &(params.core_message.nonce_values),
|
||||
&(params.parsed_license));
|
||||
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);
|
||||
// temporarily mess up with request hash
|
||||
params.request_hash[0] = 0xff;
|
||||
OEMCryptoResult err = ODK_ParseLicense(
|
||||
buf, buf_size + kExtraPayloadSize, buf_size, params.initial_license_load,
|
||||
params.usage_entry_present, params.request_hash, &(params.timer_limits),
|
||||
params.usage_entry_present, &(params.timer_limits),
|
||||
&(params.clock_values), &(params.core_message.nonce_values),
|
||||
&(params.parsed_license));
|
||||
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, &(params.timer_limits),
|
||||
&(params.clock_values), &(params.core_message.nonce_values),
|
||||
&(params.parsed_license));
|
||||
EXPECT_EQ(ODK_ERROR_CORE_MESSAGE, err);
|
||||
@@ -560,17 +616,37 @@ TEST(OdkTest, ParsePrivisioningErrorDeviceId) {
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
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::DefaultFeatures(GetParam().maximum_major_version);
|
||||
}
|
||||
CoreMessageFeatures features_;
|
||||
};
|
||||
|
||||
// Serialize and de-serialize license response
|
||||
TEST(OdkTest, LicenseResponseRoundtrip) {
|
||||
TEST_P(OdkVersionTest, LicenseResponseRoundtrip) {
|
||||
ODK_LicenseResponseParams params;
|
||||
ODK_SetDefaultLicenseResponseParams(¶ms);
|
||||
// save a copy of params.request_hash as it will be zero out during the test
|
||||
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, request_hash_read, &(params.timer_limits),
|
||||
params.usage_entry_present, &(params.timer_limits),
|
||||
&(params.clock_values), &(params.core_message.nonce_values),
|
||||
&(params.parsed_license));
|
||||
};
|
||||
@@ -579,18 +655,19 @@ TEST(OdkTest, LicenseResponseRoundtrip) {
|
||||
sizeof(request_hash_read));
|
||||
auto kdo_prepare_func = [&](const ODK_LicenseRequest& core_request,
|
||||
std::string* oemcrypto_core_message) {
|
||||
return CreateCoreLicenseResponse(params.parsed_license, core_request,
|
||||
request_hash_string,
|
||||
return CreateCoreLicenseResponse(features_, params.parsed_license,
|
||||
core_request, request_hash_string,
|
||||
oemcrypto_core_message);
|
||||
};
|
||||
ValidateResponse<ODK_LicenseRequest>(&(params.core_message),
|
||||
ValidateResponse<ODK_LicenseRequest>(GetParam(), &(params.core_message),
|
||||
params.extra_fields, odk_parse_func,
|
||||
kdo_prepare_func);
|
||||
}
|
||||
|
||||
TEST(OdkTest, RenewalResponseRoundtrip) {
|
||||
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) {
|
||||
@@ -609,17 +686,18 @@ TEST(OdkTest, RenewalResponseRoundtrip) {
|
||||
auto kdo_prepare_func = [&](ODK_RenewalRequest& core_request,
|
||||
std::string* oemcrypto_core_message) {
|
||||
core_request.playback_time_seconds = playback_clock;
|
||||
return CreateCoreRenewalResponse(core_request, renewal_duration,
|
||||
return CreateCoreRenewalResponse(features_, core_request, renewal_duration,
|
||||
oemcrypto_core_message);
|
||||
};
|
||||
ValidateResponse<ODK_RenewalRequest>(&(params.core_message),
|
||||
ValidateResponse<ODK_RenewalRequest>(GetParam(), &(params.core_message),
|
||||
params.extra_fields, odk_parse_func,
|
||||
kdo_prepare_func);
|
||||
}
|
||||
|
||||
TEST(OdkTest, ProvisionResponseRoundtrip) {
|
||||
TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
|
||||
ODK_ProvisioningResponseParams params;
|
||||
ODK_SetDefaultProvisioningResponseParams(¶ms);
|
||||
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};
|
||||
@@ -635,14 +713,61 @@ TEST(OdkTest, ProvisionResponseRoundtrip) {
|
||||
std::string* oemcrypto_core_message) {
|
||||
core_request.device_id.assign(reinterpret_cast<char*>(device_id),
|
||||
device_id_length);
|
||||
return CreateCoreProvisioningResponse(params.parsed_provisioning,
|
||||
return CreateCoreProvisioningResponse(features_, params.parsed_provisioning,
|
||||
core_request, oemcrypto_core_message);
|
||||
};
|
||||
ValidateResponse<ODK_ProvisioningRequest>(&(params.core_message),
|
||||
ValidateResponse<ODK_ProvisioningRequest>(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.
|
||||
// TODO(b/163416999): Remove it in the future. This will be unecessarily
|
||||
// complicated after we upgrade to version 17.
|
||||
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<VersionParameters> TestCases() {
|
||||
std::vector<VersionParameters> 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
|
||||
{16, ODK_MAJOR_VERSION, ODK_MINOR_VERSION, 16, 5},
|
||||
// Here are some known good versions. Make extra sure they work.
|
||||
{16, 16, 3, 16, 3},
|
||||
{16, 16, 4, 16, 4},
|
||||
{16, 16, 5, 16, 5},
|
||||
{17, 16, 3, 16, 3},
|
||||
{17, 16, 4, 16, 4},
|
||||
{17, 16, 5, 16, 5},
|
||||
{17, 17, 0, 17, 0},
|
||||
};
|
||||
return test_cases;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(OdkVersionTests, OdkVersionTest,
|
||||
::testing::ValuesIn(TestCases()));
|
||||
|
||||
TEST(OdkSizeTest, LicenseRequest) {
|
||||
uint8_t* message = nullptr;
|
||||
size_t message_length = 0;
|
||||
|
||||
Reference in New Issue
Block a user