ODK unit tests for release request
PiperOrigin-RevId: 584427947 Change-Id: I7a131739c5ea0d27c2f9e9c5ecb7b138176ce049
This commit is contained in:
@@ -295,8 +295,6 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
* of the message. (in) size of buffer reserved for the core message, in
|
||||
* bytes. (out) actual length of the core message, in bytes.
|
||||
* @param[in] nonce_values: pointer to the session's nonce data.
|
||||
* @param[in] message_count_info: information used for server-side anomaly
|
||||
* detection
|
||||
* @param[in] status: the enumeration of OEMCrypto_Usage_Entry_Status
|
||||
* @param[in] clock_security_level: the enumeration of
|
||||
* OEMCryto_Clock_Security_Level
|
||||
@@ -304,6 +302,9 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
* being requested and the release being generated in seconds
|
||||
* @param[in] seconds_since_first_decrypt: The time since playback has started
|
||||
* in seconds
|
||||
* @param[in,out] clock_values: the session's clock values.
|
||||
* @param[in] system_time_seconds: the current time on OEMCrypto's clock, in
|
||||
* seconds.
|
||||
*
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval OEMCrypto_ERROR_SHORT_BUFFER: core_message_size is too small
|
||||
@@ -314,10 +315,10 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
*/
|
||||
OEMCryptoResult ODK_PrepareCoreReleaseRequest(
|
||||
uint8_t* message, size_t message_length, size_t* core_message_size,
|
||||
const ODK_NonceValues* nonce_values,
|
||||
const ODK_MessageCounterInfo* counter_info, uint32_t status,
|
||||
ODK_NonceValues* nonce_values, uint32_t status,
|
||||
uint32_t clock_security_level, int64_t seconds_since_license_requested,
|
||||
int64_t seconds_since_first_decrypt);
|
||||
int64_t seconds_since_first_decrypt, ODK_ClockValues* clock_values,
|
||||
uint64_t system_time_seconds);
|
||||
|
||||
/**
|
||||
* Modifies the message to include a core renewal request at the beginning of
|
||||
@@ -666,6 +667,7 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
* value is ODK_SET_TIMER. This must be non-null if OEMCrypto uses a
|
||||
* hardware timer.
|
||||
*
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there
|
||||
* were other incorrect values. An error should be returned to the CDM
|
||||
* layer.
|
||||
@@ -690,6 +692,39 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
ODK_ClockValues* clock_values,
|
||||
uint64_t* timer_value);
|
||||
|
||||
/**
|
||||
* The function ODK_ParseRelease will parse the message and verify its
|
||||
* header contents. If the message does not parse correctly, an error of
|
||||
* ODK_ERROR_CORE_MESSAGE is returned. This function is mostly a placeholder
|
||||
* function since there is no information needed in the release response.
|
||||
*
|
||||
* @param[in] message: pointer to the message buffer.
|
||||
* @param[in] message_length: length of the entire message buffer.
|
||||
* @param[in] core_message_size: length of the core message, at the beginning of
|
||||
* the message buffer.
|
||||
* @param[in,out] nonce_values: pointer to the session's nonce data. These might
|
||||
* be updated if the server returns a lower API version.
|
||||
* @param[in] seconds_since_license_requested: the time between the license
|
||||
* being requested and the release being generated in seconds.
|
||||
* @param[in] seconds_since_first_decrypt: The time since playback has started
|
||||
* in seconds.
|
||||
*
|
||||
* @retval OEMCrypto_SUCCESS
|
||||
* @retval ODK_ERROR_CORE_MESSAGE: the message did not parse correctly, or there
|
||||
* were other incorrect values. An error should be returned to the CDM
|
||||
* layer.
|
||||
* @retval ODK_UNSUPPORTED_API
|
||||
* @retval OEMCrypto_ERROR_INVALID_NONCE
|
||||
*
|
||||
* @version
|
||||
* This method is new in version 19 of the API.
|
||||
*/
|
||||
OEMCryptoResult ODK_ParseRelease(const uint8_t* message, size_t message_length,
|
||||
size_t core_message_length,
|
||||
ODK_NonceValues* nonce_values,
|
||||
int64_t seconds_since_license_requested,
|
||||
int64_t seconds_since_first_decrypt);
|
||||
|
||||
/**
|
||||
* The function ODK_ParseProvisioning will parse the message and verify the
|
||||
* nonce values match those in the license.
|
||||
|
||||
@@ -19,7 +19,7 @@ extern "C" {
|
||||
#define ODK_MINOR_VERSION 0
|
||||
|
||||
/* ODK Version string. Date changed automatically on each release. */
|
||||
#define ODK_RELEASE_DATE "ODK v19.0 2023-11-10"
|
||||
#define ODK_RELEASE_DATE "ODK v19.0 2023-11-21"
|
||||
|
||||
/* The lowest version number for an ODK message. */
|
||||
#define ODK_FIRST_VERSION 16
|
||||
|
||||
@@ -235,12 +235,12 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
|
||||
OEMCryptoResult ODK_PrepareCoreReleaseRequest(
|
||||
uint8_t* message, size_t message_length, size_t* core_message_size,
|
||||
const ODK_NonceValues* nonce_values,
|
||||
const ODK_MessageCounterInfo* counter_info, uint32_t status,
|
||||
ODK_NonceValues* nonce_values, uint32_t status,
|
||||
uint32_t clock_security_level, int64_t seconds_since_license_requested,
|
||||
int64_t seconds_since_first_decrypt) {
|
||||
int64_t seconds_since_first_decrypt, ODK_ClockValues* clock_values,
|
||||
uint64_t system_time_seconds) {
|
||||
if (core_message_size == NULL || nonce_values == NULL ||
|
||||
counter_info == NULL) {
|
||||
clock_values == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
if (nonce_values->api_major_version >= 19) {
|
||||
@@ -251,8 +251,9 @@ OEMCryptoResult ODK_PrepareCoreReleaseRequest(
|
||||
} else {
|
||||
// If the version is pre 19 when license release isn't supported, create a
|
||||
// license request.
|
||||
return ODK_PrepareCoreLicenseRequest(
|
||||
message, message_length, core_message_size, nonce_values, counter_info);
|
||||
return ODK_PrepareCoreRenewalRequest(message, message_length,
|
||||
core_message_size, nonce_values,
|
||||
clock_values, system_time_seconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,6 +522,35 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
timer_value);
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_ParseRelease(const uint8_t* message, size_t message_length,
|
||||
size_t core_message_length,
|
||||
ODK_NonceValues* nonce_values,
|
||||
int64_t seconds_since_license_requested,
|
||||
int64_t seconds_since_first_decrypt) {
|
||||
if (message == NULL || nonce_values == NULL) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
const OEMCryptoResult err =
|
||||
ODK_ParseCoreHeader(message, message_length, core_message_length,
|
||||
ODK_Release_Response_Type, nonce_values);
|
||||
if (err != OEMCrypto_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ODK_ReleaseResponse release_response = {0};
|
||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||
ODK_Message_SetSize(&msg, core_message_length);
|
||||
Unpack_ODK_ReleaseResponse(&msg, &release_response);
|
||||
|
||||
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||
ODK_Message_GetOffset(&msg) != core_message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult ODK_ParseProvisioning(
|
||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||
ODK_NonceValues* nonce_values, const uint8_t* device_id,
|
||||
|
||||
@@ -132,7 +132,7 @@ typedef struct {
|
||||
#define ODK_CORE_MESSAGE_SIZE 20u
|
||||
#define ODK_LICENSE_REQUEST_SIZE 90u
|
||||
#define ODK_LICENSE_REQUEST_SIZE_V17 20u
|
||||
#define ODK_RELEASE_REQUEST_SIZE 90u
|
||||
#define ODK_RELEASE_REQUEST_SIZE 20u
|
||||
#define ODK_RENEWAL_REQUEST_SIZE 28u
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE 94u
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE_V17 88u
|
||||
|
||||
@@ -32,12 +32,14 @@ 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;
|
||||
@@ -49,6 +51,7 @@ 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;
|
||||
@@ -686,6 +689,35 @@ TEST(OdkTest, RenewalRequestRoundtrip) {
|
||||
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<int64_t>(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<ODK_Field> 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_ReleaseRequest>(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;
|
||||
@@ -1131,6 +1163,32 @@ TEST_P(OdkVersionTest, RenewalResponseRoundtrip) {
|
||||
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),
|
||||
params.seconds_since_license_requested,
|
||||
params.seconds_since_first_decrypt);
|
||||
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<ODK_ReleaseRequest>(GetParam(), &(params.core_message),
|
||||
params.extra_fields, odk_parse_func,
|
||||
kdo_prepare_func);
|
||||
}
|
||||
|
||||
TEST_P(OdkVersionTest, ProvisionResponseRoundtrip) {
|
||||
ODK_ProvisioningResponseParams params;
|
||||
ODK_SetDefaultProvisioningResponseParams(¶ms,
|
||||
|
||||
@@ -358,6 +358,8 @@ size_t ODK_FieldLength(ODK_FieldType type) {
|
||||
return sizeof(uint32_t);
|
||||
case ODK_UINT64:
|
||||
return sizeof(uint64_t);
|
||||
case ODK_INT64:
|
||||
return sizeof(uint64_t);
|
||||
case ODK_BOOL: // Booleans are stored in the message as 32 bit ints.
|
||||
return sizeof(uint32_t);
|
||||
case ODK_SUBSTRING:
|
||||
@@ -414,6 +416,12 @@ OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field) {
|
||||
memcpy(buf, &u64, sizeof(u64));
|
||||
break;
|
||||
}
|
||||
case ODK_INT64: {
|
||||
const int64_t i64 =
|
||||
oemcrypto_htobe64(*static_cast<int64_t*>(field->value));
|
||||
memcpy(buf, &i64, sizeof(i64));
|
||||
break;
|
||||
}
|
||||
case ODK_BOOL: {
|
||||
const bool value = *static_cast<bool*>(field->value);
|
||||
const uint32_t u32 = oemcrypto_htobe32(value ? 1 : 0);
|
||||
@@ -493,6 +501,12 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf,
|
||||
*u64p = oemcrypto_be64toh(*u64p);
|
||||
break;
|
||||
}
|
||||
case ODK_INT64: {
|
||||
memcpy(field->value, buf, sizeof(int64_t));
|
||||
int64_t* i64p = static_cast<int64_t*>(field->value);
|
||||
*i64p = oemcrypto_be64toh(*i64p);
|
||||
break;
|
||||
}
|
||||
case ODK_BOOL: {
|
||||
uint32_t value;
|
||||
memcpy(&value, buf, sizeof(uint32_t));
|
||||
@@ -612,6 +626,14 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
||||
<< "\n";
|
||||
break;
|
||||
}
|
||||
case ODK_INT64: {
|
||||
int64_t val;
|
||||
memcpy(&val, buf, sizeof(int64_t));
|
||||
val = oemcrypto_be64toh(val);
|
||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||
<< "\n";
|
||||
break;
|
||||
}
|
||||
case ODK_SUBSTRING: {
|
||||
uint32_t off = 0;
|
||||
uint32_t len = 0;
|
||||
|
||||
@@ -19,6 +19,7 @@ enum ODK_FieldType {
|
||||
ODK_UINT16,
|
||||
ODK_UINT32,
|
||||
ODK_UINT64,
|
||||
ODK_INT64,
|
||||
ODK_SUBSTRING,
|
||||
ODK_DEVICEID,
|
||||
ODK_DEVICEINFO,
|
||||
@@ -98,8 +99,7 @@ void ODK_SetDefaultCoreFields(ODK_CoreMessage* core_message,
|
||||
ODK_MessageType message_type);
|
||||
void ODK_SetDefaultLicenseResponseParams(ODK_LicenseResponseParams* params,
|
||||
uint32_t odk_major_version);
|
||||
void ODK_SetDefaultReleaseResponseParams(ODK_ReleaseResponseParams* params,
|
||||
uint32_t odk_major_version);
|
||||
void ODK_SetDefaultReleaseResponseParams(ODK_ReleaseResponseParams* params);
|
||||
void ODK_SetDefaultRenewalResponseParams(ODK_RenewalResponseParams* params);
|
||||
void ODK_SetDefaultProvisioningResponseParams(
|
||||
ODK_ProvisioningResponseParams* params, uint32_t odk_major_version);
|
||||
|
||||
Reference in New Issue
Block a user