Update ODK library for OPK compatibility
This is a merge from http://go/wvgerrit of several changes to the ODK library that allow it to be used in the same compilation unit as the OPK serialization/deserialization code. Merge of: http://go/wvgerrit/104403 http://go/wvgerrit/105663 http://go/wvgerrit/106004 http://go/wvgerrit/107903 http://go/wvgerrit/107985 http://go/wvgerrit/110167 http://go/wvgerrit/110403 http://go/wvgerrit/110423 http://go/wvgerrit/110663 http://go/wvgerrit/110703 http://go/wvgerrit/110985 http://go/wvgerrit/111703 http://go/wvgerrit/112563 http://go/wvgerrit/113243 http://go/wvgerrit/115204 http://go/wvgerrit/117803 http://go/wvgerrit/121949 bug: 174518179 bug: 175920940 bug: 175126254 Change-Id: I433459182043ca43a040cdbc16d04f2b8215067a
This commit is contained in:
@@ -27,6 +27,7 @@ cc_library_static {
|
|||||||
|
|
||||||
srcs: [
|
srcs: [
|
||||||
"src/odk.c",
|
"src/odk.c",
|
||||||
|
"src/odk_message.c",
|
||||||
"src/odk_overflow.c",
|
"src/odk_overflow.c",
|
||||||
"src/odk_serialize.c",
|
"src/odk_serialize.c",
|
||||||
"src/odk_timer.c",
|
"src/odk_timer.c",
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
This ODK Library is used to generate and parse core OEMCrypto messages for
|
This ODK Library is used to generate and parse core OEMCrypto messages for
|
||||||
OEMCrypto v16 and above.
|
OEMCrypto v16 and above. This library is used by both OEMCrypto on a device
|
||||||
|
and by Widevine license and provisioning servers.
|
||||||
This library is used by both OEMCrypto on a device, and by Widevine license and
|
|
||||||
provisioning servers.
|
|
||||||
|
|
||||||
The source of truth for these files is in the server code base on piper. Do not
|
The source of truth for these files is in the server code base on piper. Do not
|
||||||
edit these files in the Android directory tree or in the Widevine Git
|
edit these files in the Android directory tree or in the Widevine Git
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ typedef enum OEMCryptoResult {
|
|||||||
OEMCrypto_ERROR_LICENSE_RELOAD = 57,
|
OEMCrypto_ERROR_LICENSE_RELOAD = 57,
|
||||||
OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
|
OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES = 58,
|
||||||
OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
|
OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION = 59,
|
||||||
|
OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION = 60,
|
||||||
/* ODK return values */
|
/* ODK return values */
|
||||||
ODK_ERROR_BASE = 1000,
|
ODK_ERROR_BASE = 1000,
|
||||||
ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
|
ODK_ERROR_CORE_MESSAGE = ODK_ERROR_BASE,
|
||||||
|
|||||||
143
libwvdrmengine/oemcrypto/odk/include/odk_message.h
Normal file
143
libwvdrmengine/oemcrypto/odk/include/odk_message.h
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||||
|
* source code may only be used and distributed under the Widevine Master
|
||||||
|
* License Agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
|
||||||
|
#define WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ODK_Message is the structure that defines the serialized messages passed
|
||||||
|
* between the REE and TEE. ODK_Message is an abstract data type that represents
|
||||||
|
* the concept of a message without disclosing the implementation details. By
|
||||||
|
* hiding the internal structure, modification of the message fields by code
|
||||||
|
* that is not privy to the message definition can be prevented. If the message
|
||||||
|
* definition was exposed, there could be serious yet subtle errors in message
|
||||||
|
* manipulation anywhere in the code base. By restricting message modification
|
||||||
|
* it is possible to enforce validity and integrity with a small set of
|
||||||
|
* primitives that can be carefully reviewed. Checks can be added to verify that
|
||||||
|
* a message's fields are internally consistent before every operation. As an
|
||||||
|
* example, it can be guaranteed that the message status will be checked prior
|
||||||
|
* to accessing any field so parsing will be stopped when the message status is
|
||||||
|
* set after any parse error is detected. This also makes development easier
|
||||||
|
* since any access to the message structure can be tracked through a single
|
||||||
|
* point so, for example, it becomes possible to add trace statements globally
|
||||||
|
* to all message operations by only changing the field accessors. Finally it
|
||||||
|
* simplifies maintenance by localizing changes to the message structure to a
|
||||||
|
* few files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
# define ALIGNED __attribute__((aligned))
|
||||||
|
#else
|
||||||
|
# define ALIGNED
|
||||||
|
# error ODK_Message must be aligned to the maximum useful alignment of the \
|
||||||
|
machine you are compiling for. Define the ALIGNED macro accordingly.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
#define SIZE_OF_ODK_MESSAGE_IMPL 64
|
||||||
|
uint8_t opaque_data[SIZE_OF_ODK_MESSAGE_IMPL];
|
||||||
|
} ALIGNED ODK_Message;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MESSAGE_STATUS_OK = 0xe937fcf7,
|
||||||
|
MESSAGE_STATUS_UNKNOWN_ERROR = 0xe06c1190,
|
||||||
|
MESSAGE_STATUS_OVERFLOW_ERROR = 0xc43ae4bc,
|
||||||
|
MESSAGE_STATUS_UNDERFLOW_ERROR = 0x7123cd0b,
|
||||||
|
MESSAGE_STATUS_PARSE_ERROR = 0x0b9f6189,
|
||||||
|
MESSAGE_STATUS_NULL_POINTER_ERROR = 0x2d66837a,
|
||||||
|
MESSAGE_STATUS_API_VALUE_ERROR = 0x6ba34f47,
|
||||||
|
MESSAGE_STATUS_END_OF_MESSAGE_ERROR = 0x998db72a,
|
||||||
|
MESSAGE_STATUS_INVALID_ENUM_VALUE = 0xedb88197,
|
||||||
|
MESSAGE_STATUS_INVALID_TAG_ERROR = 0x14dce06a,
|
||||||
|
MESSAGE_STATUS_NOT_INITIALIZED = 0x2990b6c6,
|
||||||
|
MESSAGE_STATUS_OUT_OF_MEMORY = 0xfc5c64cc,
|
||||||
|
MESSAGE_STATUS_MAP_SHARED_MEMORY_FAILED = 0xfafecacf,
|
||||||
|
MESSAGE_STATUS_SECURE_BUFFER_ERROR = 0x78f0e873
|
||||||
|
} ODK_MessageStatus;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a message structure that references a separate data buffer. An
|
||||||
|
* initialized message is returned. The caller is responsible for ensuring that
|
||||||
|
* the buffer remains allocated for the lifetime of the message. If |buffer|
|
||||||
|
* is NULL or |capacity| is zero, the message is invalid and the status
|
||||||
|
* will be set to MESSAGE_STATUS_NOT_INITIALIZED.
|
||||||
|
*/
|
||||||
|
ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Erase the contents of the message, set it to an empty state by setting the
|
||||||
|
* message size and read offset to 0, effectively erasing the contents of the
|
||||||
|
* message. The message data buffer pointer remains unchanged, i.e. the message
|
||||||
|
* retains ownership of the buffer. The message status is reset to
|
||||||
|
* MESSAGE_STATUS_OK.
|
||||||
|
*/
|
||||||
|
void ODK_Message_Clear(ODK_Message* message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset read pointer to the beginning of the message and clear status
|
||||||
|
* so that parsing of the message will restart at the beginning of the
|
||||||
|
* message. The message status is reset to MESSAGE_STATUS_OK.
|
||||||
|
*/
|
||||||
|
void ODK_Message_Reset(ODK_Message* message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a pointer to the message data buffer, i.e. the message payload.
|
||||||
|
* This is the buffer address that was passed into ODK_Message_Create.
|
||||||
|
*/
|
||||||
|
uint8_t* ODK_Message_GetBase(ODK_Message* message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the maximum number of bytes the message can hold.
|
||||||
|
*/
|
||||||
|
size_t ODK_Message_GetCapacity(ODK_Message* message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of bytes currently in the message
|
||||||
|
*/
|
||||||
|
size_t ODK_Message_GetSize(ODK_Message* message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the offset of where the next bytes will be read from the message data
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
size_t ODK_Message_GetOffset(ODK_Message* message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the status of the message
|
||||||
|
*/
|
||||||
|
ODK_MessageStatus ODK_Message_GetStatus(ODK_Message* message);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the message status to a specific value
|
||||||
|
*/
|
||||||
|
void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the size of the message to a value. This may be needed after writing data
|
||||||
|
* into the message data buffer.
|
||||||
|
*/
|
||||||
|
void ODK_Message_SetSize(ODK_Message* message, size_t size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if the integrity of a message. This means that the status must be
|
||||||
|
* MESSAGE_STATUS_OK and that the internal fields of the message are
|
||||||
|
* within the range of valid values.
|
||||||
|
*/
|
||||||
|
bool ODK_Message_IsValid(ODK_Message* message);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_H_
|
||||||
@@ -12,10 +12,14 @@
|
|||||||
|
|
||||||
/* The version of this library. */
|
/* The version of this library. */
|
||||||
#define ODK_MAJOR_VERSION 16
|
#define ODK_MAJOR_VERSION 16
|
||||||
#define ODK_MINOR_VERSION 3
|
// TODO(b/163416999): Do not change minor version to 16.5 on master branch. The
|
||||||
|
// version 16.5 is reserved for Alcatraz, iOS, and other L3 platforms using
|
||||||
|
// third-party obfuscation tools. The version should not be used for CE CDM or
|
||||||
|
// Android CDM. We should jump straight to 17.0.
|
||||||
|
#define ODK_MINOR_VERSION 4
|
||||||
|
|
||||||
/* ODK Version string. Date changed automatically on each release. */
|
/* ODK Version string. Date changed automatically on each release. */
|
||||||
#define ODK_RELEASE_DATE "ODK v16.3 2020-08-18"
|
#define ODK_RELEASE_DATE "ODK v16.4 2020-10-23"
|
||||||
|
|
||||||
/* The lowest version number for an ODK message. */
|
/* The lowest version number for an ODK message. */
|
||||||
#define ODK_FIRST_VERSION 16
|
#define ODK_FIRST_VERSION 16
|
||||||
|
|||||||
@@ -39,13 +39,11 @@ bool ParseRequest(uint32_t message_type,
|
|||||||
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
|
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
|
||||||
const size_t buf_length = oemcrypto_core_message.size();
|
const size_t buf_length = oemcrypto_core_message.size();
|
||||||
|
|
||||||
uint8_t blk[SIZE_OF_MESSAGE_STRUCT];
|
ODK_Message msg = ODK_Message_Create(const_cast<uint8_t*>(buf), buf_length);
|
||||||
Message* msg = reinterpret_cast<Message*>(blk);
|
ODK_Message_SetSize(&msg, buf_length);
|
||||||
InitMessage(msg, const_cast<uint8_t*>(buf), buf_length);
|
|
||||||
SetSize(msg, buf_length);
|
|
||||||
|
|
||||||
unpacker(msg, prepared);
|
unpacker(&msg, prepared);
|
||||||
if (!ValidMessage(msg)) {
|
if (!ODK_Message_IsValid(&msg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +78,7 @@ bool ParseRequest(uint32_t message_type,
|
|||||||
// than the total message size. We allow the total message size to be larger
|
// than the total message size. We allow the total message size to be larger
|
||||||
// for forward compatibility because future messages might have extra fields
|
// for forward compatibility because future messages might have extra fields
|
||||||
// that we can ignore.
|
// that we can ignore.
|
||||||
if (core_message.message_length < GetOffset(msg)) return false;
|
if (core_message.message_length < ODK_Message_GetOffset(&msg)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,18 +50,16 @@ bool CreateResponse(uint32_t message_type, const S& core_request,
|
|||||||
|
|
||||||
static constexpr size_t BUF_CAPACITY = 2048;
|
static constexpr size_t BUF_CAPACITY = 2048;
|
||||||
std::vector<uint8_t> buf(BUF_CAPACITY, 0);
|
std::vector<uint8_t> buf(BUF_CAPACITY, 0);
|
||||||
uint8_t blk[SIZE_OF_MESSAGE_STRUCT];
|
ODK_Message msg = ODK_Message_Create(buf.data(), buf.capacity());
|
||||||
Message* msg = reinterpret_cast<Message*>(blk);
|
packer(&msg, &response);
|
||||||
InitMessage(msg, buf.data(), buf.capacity());
|
if (!ODK_Message_IsValid(&msg)) {
|
||||||
packer(msg, &response);
|
|
||||||
if (!ValidMessage(msg)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t message_length = GetSize(msg);
|
uint32_t message_length = ODK_Message_GetSize(&msg);
|
||||||
InitMessage(msg, buf.data() + sizeof(header->message_type),
|
msg = ODK_Message_Create(buf.data() + sizeof(header->message_type),
|
||||||
sizeof(header->message_length));
|
sizeof(header->message_length));
|
||||||
Pack_uint32_t(msg, &message_length);
|
Pack_uint32_t(&msg, &message_length);
|
||||||
oemcrypto_core_message->assign(reinterpret_cast<const char*>(buf.data()),
|
oemcrypto_core_message->assign(reinterpret_cast<const char*>(buf.data()),
|
||||||
message_length);
|
message_length);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t blk[SIZE_OF_MESSAGE_STRUCT];
|
ODK_Message msg = ODK_Message_Create(message, *core_message_length);
|
||||||
Message* msg = (Message*)blk;
|
|
||||||
InitMessage(msg, message, *core_message_length);
|
|
||||||
|
|
||||||
/* The core message should be at the beginning of the buffer, and with a
|
/* The core message should be at the beginning of the buffer, and with a
|
||||||
* shorter length. */
|
* shorter length. */
|
||||||
@@ -52,7 +50,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
Pack_ODK_PreparedLicenseRequest(
|
Pack_ODK_PreparedLicenseRequest(
|
||||||
msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
&msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_Renewal_Request_Type: {
|
case ODK_Renewal_Request_Type: {
|
||||||
@@ -61,7 +59,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
Pack_ODK_PreparedRenewalRequest(
|
Pack_ODK_PreparedRenewalRequest(
|
||||||
msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
|
&msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_Provisioning_Request_Type: {
|
case ODK_Provisioning_Request_Type: {
|
||||||
@@ -71,7 +69,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
Pack_ODK_PreparedProvisioningRequest(
|
Pack_ODK_PreparedProvisioningRequest(
|
||||||
msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -80,13 +78,13 @@ static OEMCryptoResult ODK_PrepareRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*core_message_length = core_message->message_length;
|
*core_message_length = core_message->message_length;
|
||||||
if (GetStatus(msg) != MESSAGE_STATUS_OK) {
|
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK) {
|
||||||
/* This is to indicate the caller that the core_message_length has been
|
/* This is to indicate the caller that the core_message_length has been
|
||||||
* appropriately set, but the message buffer is either empty or too small,
|
* appropriately set, but the message buffer is either empty or too small,
|
||||||
* which needs to be initialized and filled in the subsequent call. */
|
* which needs to be initialized and filled in the subsequent call. */
|
||||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||||
}
|
}
|
||||||
if (GetSize(msg) != *core_message_length) {
|
if (ODK_Message_GetSize(&msg) != *core_message_length) {
|
||||||
/* This should not happen. Something is wrong. */
|
/* This should not happen. Something is wrong. */
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
@@ -102,20 +100,11 @@ static OEMCryptoResult ODK_ParseResponse(
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t blk[SIZE_OF_MESSAGE_STRUCT];
|
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||||
Message* msg = (Message*)blk;
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
|
||||||
/* We initialize the message buffer with a size of the entire message
|
|
||||||
* length. */
|
|
||||||
/* TODO(b/164486737): Fix the cast-qual warning */
|
|
||||||
InitMessage(msg, (uint8_t*)message, message_length);
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
/* The core message should be at the beginning of the buffer, and with a
|
/* The core message should be at the beginning of the buffer, and with a
|
||||||
* shorter length. The core message is the part we are parsing. */
|
* shorter length. The core message is the part we are parsing. */
|
||||||
SetSize(msg, core_message_length);
|
ODK_Message_SetSize(&msg, core_message_length);
|
||||||
|
|
||||||
/* Parse message and unpack it into response buffer. */
|
/* Parse message and unpack it into response buffer. */
|
||||||
switch (message_type) {
|
switch (message_type) {
|
||||||
@@ -123,14 +112,14 @@ static OEMCryptoResult ODK_ParseResponse(
|
|||||||
if (sizeof(ODK_LicenseResponse) > response_buffer_length) {
|
if (sizeof(ODK_LicenseResponse) > response_buffer_length) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
Unpack_ODK_LicenseResponse(msg, (ODK_LicenseResponse*)response_buffer);
|
Unpack_ODK_LicenseResponse(&msg, (ODK_LicenseResponse*)response_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_Renewal_Response_Type: {
|
case ODK_Renewal_Response_Type: {
|
||||||
if (sizeof(ODK_RenewalResponse) > response_buffer_length) {
|
if (sizeof(ODK_RenewalResponse) > response_buffer_length) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
Unpack_ODK_RenewalResponse(msg, (ODK_RenewalResponse*)response_buffer);
|
Unpack_ODK_RenewalResponse(&msg, (ODK_RenewalResponse*)response_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_Provisioning_Response_Type: {
|
case ODK_Provisioning_Response_Type: {
|
||||||
@@ -138,7 +127,7 @@ static OEMCryptoResult ODK_ParseResponse(
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
Unpack_ODK_ProvisioningResponse(
|
Unpack_ODK_ProvisioningResponse(
|
||||||
msg, (ODK_ProvisioningResponse*)response_buffer);
|
&msg, (ODK_ProvisioningResponse*)response_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -147,9 +136,9 @@ static OEMCryptoResult ODK_ParseResponse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ODK_CoreMessage* core_message = (ODK_CoreMessage*)response_buffer;
|
ODK_CoreMessage* core_message = (ODK_CoreMessage*)response_buffer;
|
||||||
if (GetStatus(msg) != MESSAGE_STATUS_OK ||
|
if (ODK_Message_GetStatus(&msg) != MESSAGE_STATUS_OK ||
|
||||||
message_type != core_message->message_type ||
|
message_type != core_message->message_type ||
|
||||||
GetOffset(msg) != core_message->message_length) {
|
ODK_Message_GetOffset(&msg) != core_message->message_length) {
|
||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,20 +296,24 @@ OEMCryptoResult ODK_ParseLicense(
|
|||||||
return ODK_ERROR_CORE_MESSAGE;
|
return ODK_ERROR_CORE_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsed_license->nonce_required) {
|
/* If this is the first time we load this license, then we verify that the
|
||||||
if (initial_license_load) {
|
* nonce values are the correct, otherwise we copy the nonce values. If the
|
||||||
if (nonce_values->nonce !=
|
* nonce values are not required to be correct, then we don't know if this is
|
||||||
license_response.request.core_message.nonce_values.nonce ||
|
* an initial load or not. In that case, we also copy the values so that we
|
||||||
nonce_values->session_id !=
|
* can use the nonce values later for a renewal.
|
||||||
license_response.request.core_message.nonce_values.session_id) {
|
*/
|
||||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
if (parsed_license->nonce_required && initial_license_load) {
|
||||||
}
|
if (nonce_values->nonce !=
|
||||||
} else { /* !initial_license_load */
|
license_response.request.core_message.nonce_values.nonce ||
|
||||||
nonce_values->nonce =
|
nonce_values->session_id !=
|
||||||
license_response.request.core_message.nonce_values.nonce;
|
license_response.request.core_message.nonce_values.session_id) {
|
||||||
nonce_values->session_id =
|
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||||
license_response.request.core_message.nonce_values.session_id;
|
|
||||||
}
|
}
|
||||||
|
} else { /* !initial_license_load, or can't tell if initial. */
|
||||||
|
nonce_values->nonce =
|
||||||
|
license_response.request.core_message.nonce_values.nonce;
|
||||||
|
nonce_values->session_id =
|
||||||
|
license_response.request.core_message.nonce_values.session_id;
|
||||||
}
|
}
|
||||||
/* For v16, in order to be backwards compatible with a v15 license server,
|
/* For v16, in order to be backwards compatible with a v15 license server,
|
||||||
* OEMCrypto stores a hash of the core license request and only signs the
|
* OEMCrypto stores a hash of the core license request and only signs the
|
||||||
@@ -367,9 +360,12 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
|||||||
*/
|
*/
|
||||||
/* If a renewal request is lost in transit, we should throw it out and create
|
/* If a renewal request is lost in transit, we should throw it out and create
|
||||||
* a new one. We use the timestamp to make sure we have the latest request.
|
* a new one. We use the timestamp to make sure we have the latest request.
|
||||||
|
* We only do this if playback has already started. This allows us to reload
|
||||||
|
* an offline license and also reload a renewal before starting playback.
|
||||||
*/
|
*/
|
||||||
if (clock_values->time_of_renewal_request <
|
if (clock_values->timer_status != ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED &&
|
||||||
renewal_response.request.playback_time) {
|
clock_values->time_of_renewal_request <
|
||||||
|
renewal_response.request.playback_time) {
|
||||||
return ODK_STALE_RENEWAL;
|
return ODK_STALE_RENEWAL;
|
||||||
}
|
}
|
||||||
return ODK_ComputeRenewalDuration(timer_limits, clock_values, system_time,
|
return ODK_ComputeRenewalDuration(timer_limits, clock_values, system_time,
|
||||||
|
|||||||
@@ -11,11 +11,23 @@ extern "C" {
|
|||||||
|
|
||||||
#if defined(__linux__) || defined(__ANDROID__)
|
#if defined(__linux__) || defined(__ANDROID__)
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
#define oemcrypto_htobe16 htobe16
|
||||||
|
#define oemcrypto_be16toh be16toh
|
||||||
#define oemcrypto_htobe32 htobe32
|
#define oemcrypto_htobe32 htobe32
|
||||||
#define oemcrypto_be32toh be32toh
|
#define oemcrypto_be32toh be32toh
|
||||||
#define oemcrypto_htobe64 htobe64
|
#define oemcrypto_htobe64 htobe64
|
||||||
#define oemcrypto_be64toh be64toh
|
#define oemcrypto_be64toh be64toh
|
||||||
#else /* defined(__linux__) || defined(__ANDROID__) */
|
#elif defined(__APPLE__)
|
||||||
|
#include <libkern/OSByteOrder.h>
|
||||||
|
#define oemcrypto_htobe16 OSSwapHostToBigInt16
|
||||||
|
#define oemcrypto_be16toh OSSwapBigToHostInt16
|
||||||
|
#define oemcrypto_htobe32 OSSwapHostToBigInt32
|
||||||
|
#define oemcrypto_be32toh OSSwapBigToHostInt32
|
||||||
|
#define oemcrypto_htobe64 OSSwapHostToBigInt64
|
||||||
|
#define oemcrypto_be64toh OSSwapBigToHostInt64
|
||||||
|
#else /* defined(__linux__) || defined(__ANDROID__) */
|
||||||
|
uint32_t oemcrypto_htobe16(uint16_t u16);
|
||||||
|
uint32_t oemcrypto_be16toh(uint16_t u16);
|
||||||
uint32_t oemcrypto_htobe32(uint32_t u32);
|
uint32_t oemcrypto_htobe32(uint32_t u32);
|
||||||
uint32_t oemcrypto_be32toh(uint32_t u32);
|
uint32_t oemcrypto_be32toh(uint32_t u32);
|
||||||
uint64_t oemcrypto_htobe64(uint64_t u64);
|
uint64_t oemcrypto_htobe64(uint64_t u64);
|
||||||
|
|||||||
171
libwvdrmengine/oemcrypto/odk/src/odk_message.c
Normal file
171
libwvdrmengine/oemcrypto/odk/src/odk_message.c
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||||
|
* source code may only be used and distributed under the Widevine Master
|
||||||
|
* License Agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "odk_message.h"
|
||||||
|
#include "odk_message_priv.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* C11 defines static_assert in assert.h. If it is available, force a compile
|
||||||
|
* time error if the abstract ODK_Message struct size does not match its
|
||||||
|
* implementation. If static_assert is not available, the runtime assert in
|
||||||
|
* InitMessage will catch the mismatch at the time a message is initialized.
|
||||||
|
*/
|
||||||
|
#ifdef static_assert
|
||||||
|
static_assert(
|
||||||
|
sizeof(ODK_Message) >= sizeof(ODK_Message_Impl),
|
||||||
|
"sizeof(ODK_Message) is too small. You can increase "
|
||||||
|
"SIZE_OF_ODK_MESSAGE_IMPL in odk_message.h to make it large enough.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a message structure that references a separate data buffer. An
|
||||||
|
* initialized message is returned. The caller is responsible for ensuring that
|
||||||
|
* the buffer remains allocated for the lifetime of the message. |buffer| may be
|
||||||
|
* NULL. Serialization into a message with a NULL buffer will cause the message
|
||||||
|
* size to be incremented, but no data will be written into the message
|
||||||
|
* buffer. This is useful for calculating the amount of space a message will
|
||||||
|
* need, prior to doing the actual serialization. The buffer contents are
|
||||||
|
* unchanged by this function.
|
||||||
|
*/
|
||||||
|
ODK_Message ODK_Message_Create(uint8_t* buffer, size_t capacity) {
|
||||||
|
assert(sizeof(ODK_Message) >= sizeof(ODK_Message_Impl));
|
||||||
|
ODK_Message message;
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)&message;
|
||||||
|
message_impl->base = buffer;
|
||||||
|
message_impl->capacity = capacity;
|
||||||
|
message_impl->size = 0;
|
||||||
|
message_impl->read_offset = 0;
|
||||||
|
message_impl->status = MESSAGE_STATUS_OK;
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Erase the contents of the message, set it to an empty state by setting the
|
||||||
|
* message size and read offset to 0, effectively erasing the contents of the
|
||||||
|
* message. The message data buffer pointer remains unchanged, i.e. the message
|
||||||
|
* retains ownership of the buffer. The message buffer is zero-filled. The
|
||||||
|
* message status is reset to MESSAGE_STATUS_OK.
|
||||||
|
*/
|
||||||
|
void ODK_Message_Clear(ODK_Message* message) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
message_impl->read_offset = 0;
|
||||||
|
message_impl->size = 0;
|
||||||
|
message_impl->status = MESSAGE_STATUS_OK;
|
||||||
|
if (message_impl->base) {
|
||||||
|
memset(message_impl->base, 0, message_impl->capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset read pointer to the beginning of the message and clear status
|
||||||
|
* so that parsing of the message will restart at the beginning of the
|
||||||
|
* message. The message status is reset to MESSAGE_STATUS_OK.
|
||||||
|
*/
|
||||||
|
void ODK_Message_Reset(ODK_Message* message) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
message_impl->read_offset = 0;
|
||||||
|
message_impl->status = MESSAGE_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a pointer to the message data buffer, i.e. the message payload.
|
||||||
|
* This is the buffer address that was passed into ODK_Message_Create.
|
||||||
|
*/
|
||||||
|
uint8_t* ODK_Message_GetBase(ODK_Message* message) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
return message_impl->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the maximum number of bytes the message can hold.
|
||||||
|
*/
|
||||||
|
size_t ODK_Message_GetCapacity(ODK_Message* message) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
return message_impl->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of bytes currently in the message
|
||||||
|
*/
|
||||||
|
size_t ODK_Message_GetSize(ODK_Message* message) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
return message_impl->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the offset of where the next bytes will be read from the message data
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
size_t ODK_Message_GetOffset(ODK_Message* message) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
return message_impl->read_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the status of the message
|
||||||
|
*/
|
||||||
|
ODK_MessageStatus ODK_Message_GetStatus(ODK_Message* message) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
return message_impl->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the message status to a specific value
|
||||||
|
*/
|
||||||
|
void ODK_Message_SetStatus(ODK_Message* message, ODK_MessageStatus status) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
/* preserve the first error */
|
||||||
|
if (message_impl->status == MESSAGE_STATUS_OK) {
|
||||||
|
message_impl->status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the size of the message to a value. This may be needed after writing data
|
||||||
|
* into the message data buffer.
|
||||||
|
*/
|
||||||
|
void ODK_Message_SetSize(ODK_Message* message, size_t size) {
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
assert(message_impl != NULL);
|
||||||
|
assert(size <= message_impl->capacity);
|
||||||
|
message_impl->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if the integrity of a message. This means that the status must be
|
||||||
|
* MESSAGE_STATUS_OK and that the base, read_offset, size and capacity of the
|
||||||
|
* message are within the range of valid values. The message's base pointer
|
||||||
|
* may be NULL if the buffer has not been assigned yet, that is not invalid.
|
||||||
|
*/
|
||||||
|
bool ODK_Message_IsValid(ODK_Message* message) {
|
||||||
|
assert(message);
|
||||||
|
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||||
|
if (message_impl == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (message_impl->status != MESSAGE_STATUS_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (message_impl->read_offset > message_impl->capacity ||
|
||||||
|
message_impl->size > message_impl->capacity ||
|
||||||
|
message_impl->read_offset > message_impl->size) {
|
||||||
|
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
41
libwvdrmengine/oemcrypto/odk/src/odk_message_priv.h
Normal file
41
libwvdrmengine/oemcrypto/odk/src/odk_message_priv.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||||
|
* source code may only be used and distributed under the Widevine Master
|
||||||
|
* License Agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_PRIV_H_
|
||||||
|
#define WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_PRIV_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file must only be included by odk_message.c and serialization_base.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the implementation of a message. This structure is private, i.e. it
|
||||||
|
* should only be included by files that are allowed to modify the internals of
|
||||||
|
* a message, that being odk_message.c and serialization_base.c. To ensure
|
||||||
|
* proper alignment and message size, an ODK_Message_Impl should never be
|
||||||
|
* allocated directly, instead allocate ODK_Message and cast to ODK_Message_Impl
|
||||||
|
* because ODK_Message_Impl may be smaller than ODK_Message.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* base;
|
||||||
|
size_t capacity;
|
||||||
|
size_t size;
|
||||||
|
size_t read_offset;
|
||||||
|
ODK_MessageStatus status;
|
||||||
|
} ODK_Message_Impl;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WIDEVINE_ODK_INCLUDE_ODK_MESSAGE_PRIV_H_
|
||||||
@@ -34,3 +34,13 @@ int odk_add_overflow_ux(size_t a, size_t b, size_t* c) {
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int odk_mul_overflow_ux(size_t a, size_t b, size_t* c) {
|
||||||
|
if (b > 0 && a > SIZE_MAX / b) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (c) {
|
||||||
|
*c = a * b;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ extern "C" {
|
|||||||
int odk_sub_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
int odk_sub_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
||||||
int odk_add_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
int odk_add_overflow_u64(uint64_t a, uint64_t b, uint64_t* c);
|
||||||
int odk_add_overflow_ux(size_t a, size_t b, size_t* c);
|
int odk_add_overflow_ux(size_t a, size_t b, size_t* c);
|
||||||
|
int odk_mul_overflow_ux(size_t a, size_t b, size_t* c);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,20 +13,20 @@
|
|||||||
|
|
||||||
/* @@ private serialize */
|
/* @@ private serialize */
|
||||||
|
|
||||||
static void Pack_ODK_NonceValues(Message* msg, ODK_NonceValues const* obj) {
|
static void Pack_ODK_NonceValues(ODK_Message* msg, ODK_NonceValues const* obj) {
|
||||||
Pack_uint16_t(msg, &obj->api_minor_version);
|
Pack_uint16_t(msg, &obj->api_minor_version);
|
||||||
Pack_uint16_t(msg, &obj->api_major_version);
|
Pack_uint16_t(msg, &obj->api_major_version);
|
||||||
Pack_uint32_t(msg, &obj->nonce);
|
Pack_uint32_t(msg, &obj->nonce);
|
||||||
Pack_uint32_t(msg, &obj->session_id);
|
Pack_uint32_t(msg, &obj->session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Pack_ODK_CoreMessage(Message* msg, ODK_CoreMessage const* obj) {
|
static void Pack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage const* obj) {
|
||||||
Pack_uint32_t(msg, &obj->message_type);
|
Pack_uint32_t(msg, &obj->message_type);
|
||||||
Pack_uint32_t(msg, &obj->message_length);
|
Pack_uint32_t(msg, &obj->message_length);
|
||||||
Pack_ODK_NonceValues(msg, &obj->nonce_values);
|
Pack_ODK_NonceValues(msg, &obj->nonce_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Pack_OEMCrypto_KeyObject(Message* msg,
|
static void Pack_OEMCrypto_KeyObject(ODK_Message* msg,
|
||||||
OEMCrypto_KeyObject const* obj) {
|
OEMCrypto_KeyObject const* obj) {
|
||||||
Pack_OEMCrypto_Substring(msg, &obj->key_id);
|
Pack_OEMCrypto_Substring(msg, &obj->key_id);
|
||||||
Pack_OEMCrypto_Substring(msg, &obj->key_data_iv);
|
Pack_OEMCrypto_Substring(msg, &obj->key_data_iv);
|
||||||
@@ -35,7 +35,7 @@ static void Pack_OEMCrypto_KeyObject(Message* msg,
|
|||||||
Pack_OEMCrypto_Substring(msg, &obj->key_control);
|
Pack_OEMCrypto_Substring(msg, &obj->key_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Pack_ODK_TimerLimits(Message* msg, ODK_TimerLimits const* obj) {
|
static void Pack_ODK_TimerLimits(ODK_Message* msg, ODK_TimerLimits const* obj) {
|
||||||
Pack_bool(msg, &obj->soft_enforce_rental_duration);
|
Pack_bool(msg, &obj->soft_enforce_rental_duration);
|
||||||
Pack_bool(msg, &obj->soft_enforce_playback_duration);
|
Pack_bool(msg, &obj->soft_enforce_playback_duration);
|
||||||
Pack_uint64_t(msg, &obj->earliest_playback_start_seconds);
|
Pack_uint64_t(msg, &obj->earliest_playback_start_seconds);
|
||||||
@@ -44,10 +44,11 @@ static void Pack_ODK_TimerLimits(Message* msg, ODK_TimerLimits const* obj) {
|
|||||||
Pack_uint64_t(msg, &obj->initial_renewal_duration_seconds);
|
Pack_uint64_t(msg, &obj->initial_renewal_duration_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Pack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense const* obj) {
|
static void Pack_ODK_ParsedLicense(ODK_Message* msg,
|
||||||
|
ODK_ParsedLicense const* obj) {
|
||||||
/* hand-coded */
|
/* hand-coded */
|
||||||
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||||
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
|
Pack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
|
||||||
@@ -64,7 +65,7 @@ static void Pack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense const* obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Pack_ODK_ParsedProvisioning(Message* msg,
|
static void Pack_ODK_ParsedProvisioning(ODK_Message* msg,
|
||||||
ODK_ParsedProvisioning const* obj) {
|
ODK_ParsedProvisioning const* obj) {
|
||||||
Pack_enum(msg, obj->key_type);
|
Pack_enum(msg, obj->key_type);
|
||||||
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
||||||
@@ -74,19 +75,19 @@ static void Pack_ODK_ParsedProvisioning(Message* msg,
|
|||||||
|
|
||||||
/* @@ odk serialize */
|
/* @@ odk serialize */
|
||||||
|
|
||||||
void Pack_ODK_PreparedLicenseRequest(Message* msg,
|
void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||||
ODK_PreparedLicenseRequest const* obj) {
|
ODK_PreparedLicenseRequest const* obj) {
|
||||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_ODK_PreparedRenewalRequest(Message* msg,
|
void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||||
ODK_PreparedRenewalRequest const* obj) {
|
ODK_PreparedRenewalRequest const* obj) {
|
||||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
Pack_uint64_t(msg, &obj->playback_time);
|
Pack_uint64_t(msg, &obj->playback_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_ODK_PreparedProvisioningRequest(
|
void Pack_ODK_PreparedProvisioningRequest(
|
||||||
Message* msg, ODK_PreparedProvisioningRequest const* obj) {
|
ODK_Message* msg, ODK_PreparedProvisioningRequest const* obj) {
|
||||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
Pack_uint32_t(msg, &obj->device_id_length);
|
Pack_uint32_t(msg, &obj->device_id_length);
|
||||||
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||||
@@ -94,18 +95,20 @@ void Pack_ODK_PreparedProvisioningRequest(
|
|||||||
|
|
||||||
/* @@ kdo serialize */
|
/* @@ kdo serialize */
|
||||||
|
|
||||||
void Pack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse const* obj) {
|
void Pack_ODK_LicenseResponse(ODK_Message* msg,
|
||||||
|
ODK_LicenseResponse const* obj) {
|
||||||
Pack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
Pack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
||||||
Pack_ODK_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
|
Pack_ODK_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
|
||||||
PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
PackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse const* obj) {
|
void Pack_ODK_RenewalResponse(ODK_Message* msg,
|
||||||
|
ODK_RenewalResponse const* obj) {
|
||||||
Pack_ODK_PreparedRenewalRequest(msg, &obj->request);
|
Pack_ODK_PreparedRenewalRequest(msg, &obj->request);
|
||||||
Pack_uint64_t(msg, &obj->renewal_duration_seconds);
|
Pack_uint64_t(msg, &obj->renewal_duration_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_ODK_ProvisioningResponse(Message* msg,
|
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||||
ODK_ProvisioningResponse const* obj) {
|
ODK_ProvisioningResponse const* obj) {
|
||||||
Pack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
Pack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
||||||
Pack_ODK_ParsedProvisioning(
|
Pack_ODK_ParsedProvisioning(
|
||||||
@@ -116,20 +119,21 @@ void Pack_ODK_ProvisioningResponse(Message* msg,
|
|||||||
|
|
||||||
/* @@ private deserialize */
|
/* @@ private deserialize */
|
||||||
|
|
||||||
static void Unpack_ODK_NonceValues(Message* msg, ODK_NonceValues* obj) {
|
static void Unpack_ODK_NonceValues(ODK_Message* msg, ODK_NonceValues* obj) {
|
||||||
Unpack_uint16_t(msg, &obj->api_minor_version);
|
Unpack_uint16_t(msg, &obj->api_minor_version);
|
||||||
Unpack_uint16_t(msg, &obj->api_major_version);
|
Unpack_uint16_t(msg, &obj->api_major_version);
|
||||||
Unpack_uint32_t(msg, &obj->nonce);
|
Unpack_uint32_t(msg, &obj->nonce);
|
||||||
Unpack_uint32_t(msg, &obj->session_id);
|
Unpack_uint32_t(msg, &obj->session_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Unpack_ODK_CoreMessage(Message* msg, ODK_CoreMessage* obj) {
|
static void Unpack_ODK_CoreMessage(ODK_Message* msg, ODK_CoreMessage* obj) {
|
||||||
Unpack_uint32_t(msg, &obj->message_type);
|
Unpack_uint32_t(msg, &obj->message_type);
|
||||||
Unpack_uint32_t(msg, &obj->message_length);
|
Unpack_uint32_t(msg, &obj->message_length);
|
||||||
Unpack_ODK_NonceValues(msg, &obj->nonce_values);
|
Unpack_ODK_NonceValues(msg, &obj->nonce_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Unpack_OEMCrypto_KeyObject(Message* msg, OEMCrypto_KeyObject* obj) {
|
static void Unpack_OEMCrypto_KeyObject(ODK_Message* msg,
|
||||||
|
OEMCrypto_KeyObject* obj) {
|
||||||
Unpack_OEMCrypto_Substring(msg, &obj->key_id);
|
Unpack_OEMCrypto_Substring(msg, &obj->key_id);
|
||||||
Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv);
|
Unpack_OEMCrypto_Substring(msg, &obj->key_data_iv);
|
||||||
Unpack_OEMCrypto_Substring(msg, &obj->key_data);
|
Unpack_OEMCrypto_Substring(msg, &obj->key_data);
|
||||||
@@ -137,7 +141,7 @@ static void Unpack_OEMCrypto_KeyObject(Message* msg, OEMCrypto_KeyObject* obj) {
|
|||||||
Unpack_OEMCrypto_Substring(msg, &obj->key_control);
|
Unpack_OEMCrypto_Substring(msg, &obj->key_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Unpack_ODK_TimerLimits(Message* msg, ODK_TimerLimits* obj) {
|
static void Unpack_ODK_TimerLimits(ODK_Message* msg, ODK_TimerLimits* obj) {
|
||||||
Unpack_bool(msg, &obj->soft_enforce_rental_duration);
|
Unpack_bool(msg, &obj->soft_enforce_rental_duration);
|
||||||
Unpack_bool(msg, &obj->soft_enforce_playback_duration);
|
Unpack_bool(msg, &obj->soft_enforce_playback_duration);
|
||||||
Unpack_uint64_t(msg, &obj->earliest_playback_start_seconds);
|
Unpack_uint64_t(msg, &obj->earliest_playback_start_seconds);
|
||||||
@@ -146,7 +150,7 @@ static void Unpack_ODK_TimerLimits(Message* msg, ODK_TimerLimits* obj) {
|
|||||||
Unpack_uint64_t(msg, &obj->initial_renewal_duration_seconds);
|
Unpack_uint64_t(msg, &obj->initial_renewal_duration_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Unpack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense* obj) {
|
static void Unpack_ODK_ParsedLicense(ODK_Message* msg, ODK_ParsedLicense* obj) {
|
||||||
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
|
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys_iv);
|
||||||
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys);
|
Unpack_OEMCrypto_Substring(msg, &obj->enc_mac_keys);
|
||||||
Unpack_OEMCrypto_Substring(msg, &obj->pst);
|
Unpack_OEMCrypto_Substring(msg, &obj->pst);
|
||||||
@@ -156,7 +160,7 @@ static void Unpack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense* obj) {
|
|||||||
Unpack_ODK_TimerLimits(msg, &obj->timer_limits);
|
Unpack_ODK_TimerLimits(msg, &obj->timer_limits);
|
||||||
Unpack_uint32_t(msg, &obj->key_array_length);
|
Unpack_uint32_t(msg, &obj->key_array_length);
|
||||||
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||||
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@@ -165,7 +169,7 @@ static void Unpack_ODK_ParsedLicense(Message* msg, ODK_ParsedLicense* obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Unpack_ODK_ParsedProvisioning(Message* msg,
|
static void Unpack_ODK_ParsedProvisioning(ODK_Message* msg,
|
||||||
ODK_ParsedProvisioning* obj) {
|
ODK_ParsedProvisioning* obj) {
|
||||||
obj->key_type = (OEMCrypto_PrivateKeyType)Unpack_enum(msg);
|
obj->key_type = (OEMCrypto_PrivateKeyType)Unpack_enum(msg);
|
||||||
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
||||||
@@ -175,42 +179,42 @@ static void Unpack_ODK_ParsedProvisioning(Message* msg,
|
|||||||
|
|
||||||
/* @ kdo deserialize */
|
/* @ kdo deserialize */
|
||||||
|
|
||||||
void Unpack_ODK_PreparedLicenseRequest(Message* msg,
|
void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||||
ODK_PreparedLicenseRequest* obj) {
|
ODK_PreparedLicenseRequest* obj) {
|
||||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_ODK_PreparedRenewalRequest(Message* msg,
|
void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||||
ODK_PreparedRenewalRequest* obj) {
|
ODK_PreparedRenewalRequest* obj) {
|
||||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
Unpack_uint64_t(msg, &obj->playback_time);
|
Unpack_uint64_t(msg, &obj->playback_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_ODK_PreparedProvisioningRequest(
|
void Unpack_ODK_PreparedProvisioningRequest(
|
||||||
Message* msg, ODK_PreparedProvisioningRequest* obj) {
|
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj) {
|
||||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
Unpack_uint32_t(msg, &obj->device_id_length);
|
Unpack_uint32_t(msg, &obj->device_id_length);
|
||||||
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_ODK_PreparedCommonRequest(Message* msg,
|
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
||||||
ODK_PreparedCommonRequest* obj) {
|
ODK_PreparedCommonRequest* obj) {
|
||||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||||
}
|
}
|
||||||
/* @@ odk deserialize */
|
/* @@ odk deserialize */
|
||||||
|
|
||||||
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj) {
|
void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj) {
|
||||||
Unpack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
Unpack_ODK_PreparedLicenseRequest(msg, &obj->request);
|
||||||
Unpack_ODK_ParsedLicense(msg, obj->parsed_license);
|
Unpack_ODK_ParsedLicense(msg, obj->parsed_license);
|
||||||
UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
UnpackArray(msg, &obj->request_hash[0], sizeof(obj->request_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse* obj) {
|
void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj) {
|
||||||
Unpack_ODK_PreparedRenewalRequest(msg, &obj->request);
|
Unpack_ODK_PreparedRenewalRequest(msg, &obj->request);
|
||||||
Unpack_uint64_t(msg, &obj->renewal_duration_seconds);
|
Unpack_uint64_t(msg, &obj->renewal_duration_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_ODK_ProvisioningResponse(Message* msg,
|
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||||
ODK_ProvisioningResponse* obj) {
|
ODK_ProvisioningResponse* obj) {
|
||||||
Unpack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
Unpack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
||||||
Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);
|
Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);
|
||||||
|
|||||||
@@ -16,34 +16,34 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* odk pack */
|
/* odk pack */
|
||||||
void Pack_ODK_PreparedLicenseRequest(Message* msg,
|
void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||||
const ODK_PreparedLicenseRequest* obj);
|
const ODK_PreparedLicenseRequest* obj);
|
||||||
void Pack_ODK_PreparedRenewalRequest(Message* msg,
|
void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||||
const ODK_PreparedRenewalRequest* obj);
|
const ODK_PreparedRenewalRequest* obj);
|
||||||
void Pack_ODK_PreparedProvisioningRequest(
|
void Pack_ODK_PreparedProvisioningRequest(
|
||||||
Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
ODK_Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
||||||
|
|
||||||
/* odk unpack */
|
/* odk unpack */
|
||||||
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj);
|
void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj);
|
||||||
void Unpack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse* obj);
|
void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj);
|
||||||
void Unpack_ODK_ProvisioningResponse(Message* msg,
|
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||||
ODK_ProvisioningResponse* obj);
|
ODK_ProvisioningResponse* obj);
|
||||||
|
|
||||||
/* kdo pack */
|
/* kdo pack */
|
||||||
void Pack_ODK_LicenseResponse(Message* msg, const ODK_LicenseResponse* obj);
|
void Pack_ODK_LicenseResponse(ODK_Message* msg, const ODK_LicenseResponse* obj);
|
||||||
void Pack_ODK_RenewalResponse(Message* msg, const ODK_RenewalResponse* obj);
|
void Pack_ODK_RenewalResponse(ODK_Message* msg, const ODK_RenewalResponse* obj);
|
||||||
void Pack_ODK_ProvisioningResponse(Message* msg,
|
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||||
const ODK_ProvisioningResponse* obj);
|
const ODK_ProvisioningResponse* obj);
|
||||||
|
|
||||||
/* kdo unpack */
|
/* kdo unpack */
|
||||||
void Unpack_ODK_PreparedLicenseRequest(Message* msg,
|
void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||||
ODK_PreparedLicenseRequest* obj);
|
ODK_PreparedLicenseRequest* obj);
|
||||||
void Unpack_ODK_PreparedRenewalRequest(Message* msg,
|
void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||||
ODK_PreparedRenewalRequest* obj);
|
ODK_PreparedRenewalRequest* obj);
|
||||||
void Unpack_ODK_PreparedProvisioningRequest(
|
void Unpack_ODK_PreparedProvisioningRequest(
|
||||||
Message* msg, ODK_PreparedProvisioningRequest* obj);
|
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj);
|
||||||
|
|
||||||
void Unpack_ODK_PreparedCommonRequest(Message* msg,
|
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
||||||
ODK_PreparedCommonRequest* obj);
|
ODK_PreparedCommonRequest* obj);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -4,71 +4,61 @@
|
|||||||
|
|
||||||
#include "serialization_base.h"
|
#include "serialization_base.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "OEMCryptoCENCCommon.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
|
#include "odk_message.h"
|
||||||
|
#include "odk_message_priv.h"
|
||||||
#include "odk_overflow.h"
|
#include "odk_overflow.h"
|
||||||
|
|
||||||
struct _Message {
|
/*
|
||||||
uint8_t* base;
|
* An ODK_Message_Impl pointer must only be obtained by calling GetMessageImpl.
|
||||||
size_t capacity;
|
* This forces any message to pass the validity check before being operated on,
|
||||||
size_t size; /* bytes written */
|
* which means that no function can modify or access the internals of a message
|
||||||
size_t read_offset; /* bytes read */
|
* without having it be validated first.
|
||||||
MessageStatus status;
|
*/
|
||||||
};
|
static ODK_Message_Impl* GetMessageImpl(ODK_Message* message) {
|
||||||
|
if (!ODK_Message_IsValid(message)) return NULL;
|
||||||
bool ValidMessage(Message* message) {
|
return (ODK_Message_Impl*)message;
|
||||||
if (message == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (message->status != MESSAGE_STATUS_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (message->base == NULL) {
|
|
||||||
message->status = MESSAGE_STATUS_NULL_POINTER_ERROR;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (message->size > message->capacity ||
|
|
||||||
message->read_offset > message->size) {
|
|
||||||
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PackBytes(Message* message, const uint8_t* ptr, size_t count) {
|
static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
|
||||||
if (count <= message->capacity - message->size) {
|
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||||
memcpy((void*)(message->base + message->size), (void*)ptr, count);
|
if (!message_impl) return;
|
||||||
message->size += count;
|
if (count <= message_impl->capacity - message_impl->size) {
|
||||||
|
memcpy((void*)(message_impl->base + message_impl->size), (const void*)ptr,
|
||||||
|
count);
|
||||||
|
message_impl->size += count;
|
||||||
} else {
|
} else {
|
||||||
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_enum(Message* message, int value) {
|
void Pack_enum(ODK_Message* message, int value) {
|
||||||
uint32_t v32 = value;
|
uint32_t v32 = value;
|
||||||
Pack_uint32_t(message, &v32);
|
Pack_uint32_t(message, &v32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_bool(Message* message, const bool* value) {
|
void Pack_bool(ODK_Message* message, const bool* value) {
|
||||||
if (!ValidMessage(message)) return;
|
assert(value);
|
||||||
uint8_t data[4] = {0};
|
uint8_t data[4] = {0};
|
||||||
data[3] = *value ? 1 : 0;
|
data[3] = *value ? 1 : 0;
|
||||||
PackBytes(message, data, sizeof(data));
|
PackBytes(message, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_uint16_t(Message* message, const uint16_t* value) {
|
void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
|
||||||
if (!ValidMessage(message)) return;
|
assert(value);
|
||||||
uint8_t data[2] = {0};
|
uint8_t data[2] = {0};
|
||||||
data[0] = *value >> 8;
|
data[0] = *value >> 8;
|
||||||
data[1] = *value >> 0;
|
data[1] = *value >> 0;
|
||||||
PackBytes(message, data, sizeof(data));
|
PackBytes(message, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_uint32_t(Message* message, const uint32_t* value) {
|
void Pack_uint32_t(ODK_Message* message, const uint32_t* value) {
|
||||||
if (!ValidMessage(message)) return;
|
assert(value);
|
||||||
uint8_t data[4] = {0};
|
uint8_t data[4] = {0};
|
||||||
data[0] = *value >> 24;
|
data[0] = *value >> 24;
|
||||||
data[1] = *value >> 16;
|
data[1] = *value >> 16;
|
||||||
@@ -77,160 +67,112 @@ void Pack_uint32_t(Message* message, const uint32_t* value) {
|
|||||||
PackBytes(message, data, sizeof(data));
|
PackBytes(message, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_uint64_t(Message* message, const uint64_t* value) {
|
void Pack_uint64_t(ODK_Message* message, const uint64_t* value) {
|
||||||
if (!ValidMessage(message)) return;
|
assert(value);
|
||||||
uint32_t hi = *value >> 32;
|
uint32_t hi = *value >> 32;
|
||||||
uint32_t lo = *value;
|
uint32_t lo = *value;
|
||||||
Pack_uint32_t(message, &hi);
|
Pack_uint32_t(message, &hi);
|
||||||
Pack_uint32_t(message, &lo);
|
Pack_uint32_t(message, &lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackArray(Message* message, const uint8_t* base, size_t size) {
|
void PackArray(ODK_Message* message, const uint8_t* base, size_t size) {
|
||||||
if (!ValidMessage(message)) return;
|
|
||||||
PackBytes(message, base, size);
|
PackBytes(message, base, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj) {
|
void Pack_OEMCrypto_Substring(ODK_Message* message,
|
||||||
|
const OEMCrypto_Substring* obj) {
|
||||||
|
assert(obj);
|
||||||
uint32_t offset = (uint32_t)obj->offset;
|
uint32_t offset = (uint32_t)obj->offset;
|
||||||
uint32_t length = (uint32_t)obj->length;
|
uint32_t length = (uint32_t)obj->length;
|
||||||
Pack_uint32_t(msg, &offset);
|
Pack_uint32_t(message, &offset);
|
||||||
Pack_uint32_t(msg, &length);
|
Pack_uint32_t(message, &length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UnpackBytes(Message* message, uint8_t* ptr, size_t count) {
|
static void UnpackBytes(ODK_Message* message, uint8_t* ptr, size_t count) {
|
||||||
if (count <= message->size - message->read_offset) {
|
assert(ptr);
|
||||||
memcpy((void*)ptr, (void*)(message->base + message->read_offset), count);
|
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||||
message->read_offset += count;
|
if (!message_impl) return;
|
||||||
|
if (count <= message_impl->size - message_impl->read_offset) {
|
||||||
|
memcpy((void*)ptr, (void*)(message_impl->base + message_impl->read_offset),
|
||||||
|
count);
|
||||||
|
message_impl->read_offset += count;
|
||||||
} else {
|
} else {
|
||||||
message->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
|
message_impl->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Unpack_enum(Message* message) {
|
int Unpack_enum(ODK_Message* message) {
|
||||||
uint32_t v32;
|
uint32_t v32;
|
||||||
Unpack_uint32_t(message, &v32);
|
Unpack_uint32_t(message, &v32);
|
||||||
return v32;
|
return v32;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_bool(Message* message, bool* value) {
|
void Unpack_bool(ODK_Message* message, bool* value) {
|
||||||
if (!ValidMessage(message)) return;
|
|
||||||
uint8_t data[4] = {0};
|
uint8_t data[4] = {0};
|
||||||
UnpackBytes(message, data, sizeof(data));
|
UnpackBytes(message, data, sizeof(data));
|
||||||
|
assert(value);
|
||||||
*value = (0 != data[3]);
|
*value = (0 != data[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_uint16_t(Message* message, uint16_t* value) {
|
void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
|
||||||
if (!ValidMessage(message)) return;
|
assert(value);
|
||||||
uint8_t data[2] = {0};
|
uint8_t data[2] = {0};
|
||||||
UnpackBytes(message, data, sizeof(data));
|
UnpackBytes(message, data, sizeof(data));
|
||||||
*value = data[0];
|
*value = data[0];
|
||||||
*value = *value << 8 | data[1];
|
*value = *value << 8 | data[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_uint32_t(Message* message, uint32_t* value) {
|
void Unpack_uint32_t(ODK_Message* message, uint32_t* value) {
|
||||||
if (!ValidMessage(message)) return;
|
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||||
|
if (!message_impl) return;
|
||||||
uint8_t data[4] = {0};
|
uint8_t data[4] = {0};
|
||||||
UnpackBytes(message, data, sizeof(data));
|
UnpackBytes(message, data, sizeof(data));
|
||||||
|
assert(value);
|
||||||
*value = data[0];
|
*value = data[0];
|
||||||
*value = *value << 8 | data[1];
|
*value = *value << 8 | data[1];
|
||||||
*value = *value << 8 | data[2];
|
*value = *value << 8 | data[2];
|
||||||
*value = *value << 8 | data[3];
|
*value = *value << 8 | data[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_uint64_t(Message* message, uint64_t* value) {
|
void Unpack_uint64_t(ODK_Message* message, uint64_t* value) {
|
||||||
if (!ValidMessage(message)) return;
|
|
||||||
uint32_t hi = 0;
|
uint32_t hi = 0;
|
||||||
uint32_t lo = 0;
|
uint32_t lo = 0;
|
||||||
Unpack_uint32_t(message, &hi);
|
Unpack_uint32_t(message, &hi);
|
||||||
Unpack_uint32_t(message, &lo);
|
Unpack_uint32_t(message, &lo);
|
||||||
|
assert(value);
|
||||||
*value = hi;
|
*value = hi;
|
||||||
*value = *value << 32 | lo;
|
*value = *value << 32 | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj) {
|
void Unpack_OEMCrypto_Substring(ODK_Message* message,
|
||||||
|
OEMCrypto_Substring* obj) {
|
||||||
uint32_t offset = 0, length = 0;
|
uint32_t offset = 0, length = 0;
|
||||||
Unpack_uint32_t(msg, &offset);
|
Unpack_uint32_t(message, &offset);
|
||||||
Unpack_uint32_t(msg, &length);
|
Unpack_uint32_t(message, &length);
|
||||||
if (!ValidMessage(msg)) return;
|
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||||
|
if (!message_impl) return;
|
||||||
|
|
||||||
/* Each substring should be contained within the message body, which is in the
|
/* Each substring should be contained within the message body, which is in the
|
||||||
* total message, just after the core message. The offset of a substring is
|
* total message, just after the core message. The offset of a substring is
|
||||||
* relative to the message body. So we need to verify:
|
* relative to the message body. So we need to verify:
|
||||||
* 0 < offset and offset + length < message->capacity - message->size
|
* 0 < offset and offset + length < message_impl->capacity -
|
||||||
* or offset + length + message->size < message->capacity
|
* message_impl->size or offset + length + message_impl->size <
|
||||||
|
* message_impl->capacity
|
||||||
*/
|
*/
|
||||||
size_t substring_end = 0; /* = offset + length; */
|
size_t substring_end = 0; /* = offset + length; */
|
||||||
size_t end = 0; /* = substring_end + message->size; */
|
size_t end = 0; /* = substring_end + message_impl->size; */
|
||||||
if (odk_add_overflow_ux(offset, length, &substring_end) ||
|
if (odk_add_overflow_ux(offset, length, &substring_end) ||
|
||||||
odk_add_overflow_ux(substring_end, msg->size, &end) ||
|
odk_add_overflow_ux(substring_end, message_impl->size, &end) ||
|
||||||
end > msg->capacity) {
|
end > message_impl->capacity) {
|
||||||
msg->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
assert(obj);
|
||||||
obj->offset = offset;
|
obj->offset = offset;
|
||||||
obj->length = length;
|
obj->length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy out */
|
/* copy out */
|
||||||
void UnpackArray(Message* message, uint8_t* address, size_t size) {
|
void UnpackArray(ODK_Message* message, uint8_t* address, size_t size) {
|
||||||
if (!ValidMessage(message)) return;
|
|
||||||
UnpackBytes(message, address, size);
|
UnpackBytes(message, address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The message structure, which is separate from the buffer,
|
|
||||||
* is initialized to reference the buffer
|
|
||||||
*/
|
|
||||||
void InitMessage(Message* message, uint8_t* buffer, size_t capacity) {
|
|
||||||
if (message == NULL) return;
|
|
||||||
memset(message, 0, sizeof(Message));
|
|
||||||
message->base = buffer;
|
|
||||||
message->capacity = capacity;
|
|
||||||
message->size = 0;
|
|
||||||
message->read_offset = 0;
|
|
||||||
message->status = MESSAGE_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the message to an empty state
|
|
||||||
*/
|
|
||||||
void ResetMessage(Message* message) {
|
|
||||||
message->size = 0;
|
|
||||||
message->read_offset = 0;
|
|
||||||
message->status = MESSAGE_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* GetBase(Message* message) {
|
|
||||||
if (message == NULL) return NULL;
|
|
||||||
return message->base;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GetCapacity(Message* message) {
|
|
||||||
if (message == NULL) return 0;
|
|
||||||
return message->capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GetSize(Message* message) {
|
|
||||||
if (message == NULL) return 0;
|
|
||||||
return message->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSize(Message* message, size_t size) {
|
|
||||||
if (message == NULL) return;
|
|
||||||
if (size > message->capacity)
|
|
||||||
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
|
||||||
else
|
|
||||||
message->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageStatus GetStatus(Message* message) { return message->status; }
|
|
||||||
|
|
||||||
void SetStatus(Message* message, MessageStatus status) {
|
|
||||||
message->status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GetOffset(Message* message) {
|
|
||||||
if (message == NULL) return 0;
|
|
||||||
return message->read_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t SizeOfMessageStruct() { return sizeof(Message); }
|
|
||||||
|
|||||||
@@ -13,74 +13,24 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "OEMCryptoCENCCommon.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
|
#include "odk_message.h"
|
||||||
|
|
||||||
#define SIZE_OF_MESSAGE_STRUCT 64
|
void Pack_enum(ODK_Message* message, int value);
|
||||||
|
void Pack_bool(ODK_Message* message, const bool* value);
|
||||||
|
void Pack_uint16_t(ODK_Message* message, const uint16_t* value);
|
||||||
|
void Pack_uint32_t(ODK_Message* message, const uint32_t* value);
|
||||||
|
void Pack_uint64_t(ODK_Message* message, const uint64_t* value);
|
||||||
|
void PackArray(ODK_Message* message, const uint8_t* base, size_t size);
|
||||||
|
void Pack_OEMCrypto_Substring(ODK_Message* msg, const OEMCrypto_Substring* obj);
|
||||||
|
|
||||||
/*
|
int Unpack_enum(ODK_Message* message);
|
||||||
* Description:
|
void Unpack_bool(ODK_Message* message, bool* value);
|
||||||
* Point |msg| to stack-array |blk|.
|
void Unpack_uint16_t(ODK_Message* message, uint16_t* value);
|
||||||
* |blk| is guaranteed large enough to hold a |Message| struct.
|
void Unpack_uint32_t(ODK_Message* message, uint32_t* value);
|
||||||
* |blk| cannot be used in the same scope as a variable name.
|
void Unpack_uint64_t(ODK_Message* message, uint64_t* value);
|
||||||
* |msg| points to valid memory in the same scope |AllocateMessage| is used.
|
void UnpackArray(ODK_Message* message, uint8_t* address,
|
||||||
* Parameters:
|
|
||||||
* msg: pointer to pointer to |Message| struct
|
|
||||||
* blk: variable name for stack-array
|
|
||||||
*/
|
|
||||||
#define AllocateMessage(msg, blk) \
|
|
||||||
uint8_t blk[SIZE_OF_MESSAGE_STRUCT]; \
|
|
||||||
*(msg) = (Message*)(blk)
|
|
||||||
|
|
||||||
typedef struct _Message Message;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
MESSAGE_STATUS_OK,
|
|
||||||
MESSAGE_STATUS_UNKNOWN_ERROR,
|
|
||||||
MESSAGE_STATUS_OVERFLOW_ERROR,
|
|
||||||
MESSAGE_STATUS_UNDERFLOW_ERROR,
|
|
||||||
MESSAGE_STATUS_PARSE_ERROR,
|
|
||||||
MESSAGE_STATUS_NULL_POINTER_ERROR,
|
|
||||||
MESSAGE_STATUS_API_VALUE_ERROR
|
|
||||||
} MessageStatus;
|
|
||||||
|
|
||||||
bool ValidMessage(Message* message);
|
|
||||||
|
|
||||||
void Pack_enum(Message* message, int value);
|
|
||||||
void Pack_bool(Message* message, const bool* value);
|
|
||||||
void Pack_uint16_t(Message* message, const uint16_t* value);
|
|
||||||
void Pack_uint32_t(Message* message, const uint32_t* value);
|
|
||||||
void Pack_uint64_t(Message* message, const uint64_t* value);
|
|
||||||
void PackArray(Message* message, const uint8_t* base, size_t size);
|
|
||||||
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj);
|
|
||||||
|
|
||||||
int Unpack_enum(Message* message);
|
|
||||||
void Unpack_bool(Message* message, bool* value);
|
|
||||||
void Unpack_uint16_t(Message* message, uint16_t* value);
|
|
||||||
void Unpack_uint32_t(Message* message, uint32_t* value);
|
|
||||||
void Unpack_uint64_t(Message* message, uint64_t* value);
|
|
||||||
void UnpackArray(Message* message, uint8_t* address,
|
|
||||||
size_t size); /* copy out */
|
size_t size); /* copy out */
|
||||||
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj);
|
void Unpack_OEMCrypto_Substring(ODK_Message* msg, OEMCrypto_Substring* obj);
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize a message structure to reference a separate buffer. The caller
|
|
||||||
* is responsible for ensuring that the buffer remains allocated for the
|
|
||||||
* lifetime of the message.
|
|
||||||
*/
|
|
||||||
void InitMessage(Message* message, uint8_t* buffer, size_t capacity);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset an existing the message to an empty state
|
|
||||||
*/
|
|
||||||
void ResetMessage(Message* message);
|
|
||||||
uint8_t* GetBase(Message* message);
|
|
||||||
size_t GetCapacity(Message* message);
|
|
||||||
size_t GetSize(Message* message);
|
|
||||||
void SetSize(Message* message, size_t size);
|
|
||||||
MessageStatus GetStatus(Message* message);
|
|
||||||
void SetStatus(Message* message, MessageStatus status);
|
|
||||||
size_t GetOffset(Message* message);
|
|
||||||
|
|
||||||
size_t SizeOfMessageStruct();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -99,11 +99,9 @@ OEMCryptoResult odk_deserialize_RenewalResponse(
|
|||||||
// odk_kdo method, we call Unpack_ODK_PreparedRenewalRequest private method.
|
// odk_kdo method, we call Unpack_ODK_PreparedRenewalRequest private method.
|
||||||
// playback_time cannot be captured from publicly exposed API
|
// playback_time cannot be captured from publicly exposed API
|
||||||
// ODK_ParseRenewal.
|
// ODK_ParseRenewal.
|
||||||
uint8_t blk[SIZE_OF_MESSAGE_STRUCT];
|
ODK_Message msg = ODK_Message_Create(const_cast<uint8_t*>(buf), len);
|
||||||
Message* msg = reinterpret_cast<Message*>(blk);
|
ODK_Message_SetSize(&msg, len);
|
||||||
InitMessage(msg, const_cast<uint8_t*>(buf), len);
|
Unpack_ODK_PreparedRenewalRequest(&msg, renewal_msg);
|
||||||
SetSize(msg, len);
|
|
||||||
Unpack_ODK_PreparedRenewalRequest(msg, renewal_msg);
|
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,13 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "fuzzing/odk_fuzz_helper.h"
|
#include "fuzzing/odk_fuzz_helper.h"
|
||||||
#include "odk_attributes.h"
|
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
|
|
||||||
// The custom mutator: Ensure that each input can be deserialized properly
|
// The custom mutator: Ensure that each input can be deserialized properly
|
||||||
// by ODK function after mutation.
|
// by ODK function after mutation.
|
||||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||||
size_t max_size,
|
size_t max_size, unsigned int seed) {
|
||||||
unsigned int seed UNUSED) {
|
|
||||||
const size_t kProvisioningResponseArgsSize =
|
const size_t kProvisioningResponseArgsSize =
|
||||||
sizeof(ODK_ParseProvisioning_Args);
|
sizeof(ODK_ParseProvisioning_Args);
|
||||||
if (size < kProvisioningResponseArgsSize) {
|
if (size < kProvisioningResponseArgsSize) {
|
||||||
|
|||||||
@@ -6,15 +6,13 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "fuzzing/odk_fuzz_helper.h"
|
#include "fuzzing/odk_fuzz_helper.h"
|
||||||
#include "odk_attributes.h"
|
|
||||||
|
|
||||||
namespace oemcrypto_core_message {
|
namespace oemcrypto_core_message {
|
||||||
|
|
||||||
// The custom mutator: Ensure that each input can be deserialized properly
|
// The custom mutator: Ensure that each input can be deserialized properly
|
||||||
// by ODK function after mutation.
|
// by ODK function after mutation.
|
||||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||||
size_t max_size,
|
size_t max_size, unsigned int seed) {
|
||||||
unsigned int seed UNUSED) {
|
|
||||||
const size_t kRenewalResponseArgsSize = sizeof(ODK_ParseRenewal_Args);
|
const size_t kRenewalResponseArgsSize = sizeof(ODK_ParseRenewal_Args);
|
||||||
if (size < kRenewalResponseArgsSize) {
|
if (size < kRenewalResponseArgsSize) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#include "odk.h"
|
#include "odk.h"
|
||||||
|
|
||||||
#include <endian.h> // TODO(b/147944591): use this one? Or odk_endian.h?
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#include "odk_test_helper.h"
|
#include "odk_test_helper.h"
|
||||||
|
|
||||||
#include <endian.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -15,6 +13,7 @@
|
|||||||
|
|
||||||
#include "OEMCryptoCENCCommon.h"
|
#include "OEMCryptoCENCCommon.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "odk_endian.h"
|
||||||
#include "odk_structs.h"
|
#include "odk_structs.h"
|
||||||
#include "odk_structs_priv.h"
|
#include "odk_structs_priv.h"
|
||||||
|
|
||||||
@@ -226,24 +225,27 @@ OEMCryptoResult ODK_WriteSingleField(uint8_t* buf, const ODK_Field* field) {
|
|||||||
}
|
}
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case ODK_UINT16: {
|
case ODK_UINT16: {
|
||||||
const uint16_t u16 = htobe16(*static_cast<uint16_t*>(field->value));
|
const uint16_t u16 =
|
||||||
|
oemcrypto_htobe16(*static_cast<uint16_t*>(field->value));
|
||||||
memcpy(buf, &u16, sizeof(u16));
|
memcpy(buf, &u16, sizeof(u16));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT32: {
|
case ODK_UINT32: {
|
||||||
const uint32_t u32 = htobe32(*static_cast<uint32_t*>(field->value));
|
const uint32_t u32 =
|
||||||
|
oemcrypto_htobe32(*static_cast<uint32_t*>(field->value));
|
||||||
memcpy(buf, &u32, sizeof(u32));
|
memcpy(buf, &u32, sizeof(u32));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT64: {
|
case ODK_UINT64: {
|
||||||
const uint64_t u64 = htobe64(*static_cast<uint64_t*>(field->value));
|
const uint64_t u64 =
|
||||||
|
oemcrypto_htobe64(*static_cast<uint64_t*>(field->value));
|
||||||
memcpy(buf, &u64, sizeof(u64));
|
memcpy(buf, &u64, sizeof(u64));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_SUBSTRING: {
|
case ODK_SUBSTRING: {
|
||||||
OEMCrypto_Substring* s = static_cast<OEMCrypto_Substring*>(field->value);
|
OEMCrypto_Substring* s = static_cast<OEMCrypto_Substring*>(field->value);
|
||||||
const uint32_t off = htobe32(s->offset);
|
const uint32_t off = oemcrypto_htobe32(s->offset);
|
||||||
const uint32_t len = htobe32(s->length);
|
const uint32_t len = oemcrypto_htobe32(s->length);
|
||||||
memcpy(buf, &off, sizeof(off));
|
memcpy(buf, &off, sizeof(off));
|
||||||
memcpy(buf + sizeof(off), &len, sizeof(len));
|
memcpy(buf + sizeof(off), &len, sizeof(len));
|
||||||
break;
|
break;
|
||||||
@@ -271,19 +273,19 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf,
|
|||||||
case ODK_UINT16: {
|
case ODK_UINT16: {
|
||||||
memcpy(field->value, buf, sizeof(uint16_t));
|
memcpy(field->value, buf, sizeof(uint16_t));
|
||||||
uint16_t* u16p = static_cast<uint16_t*>(field->value);
|
uint16_t* u16p = static_cast<uint16_t*>(field->value);
|
||||||
*u16p = be16toh(*u16p);
|
*u16p = oemcrypto_be16toh(*u16p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT32: {
|
case ODK_UINT32: {
|
||||||
memcpy(field->value, buf, sizeof(uint32_t));
|
memcpy(field->value, buf, sizeof(uint32_t));
|
||||||
uint32_t* u32p = static_cast<uint32_t*>(field->value);
|
uint32_t* u32p = static_cast<uint32_t*>(field->value);
|
||||||
*u32p = be32toh(*u32p);
|
*u32p = oemcrypto_be32toh(*u32p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_UINT64: {
|
case ODK_UINT64: {
|
||||||
memcpy(field->value, buf, sizeof(uint64_t));
|
memcpy(field->value, buf, sizeof(uint64_t));
|
||||||
uint64_t* u64p = static_cast<uint64_t*>(field->value);
|
uint64_t* u64p = static_cast<uint64_t*>(field->value);
|
||||||
*u64p = be64toh(*u64p);
|
*u64p = oemcrypto_be64toh(*u64p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_SUBSTRING: {
|
case ODK_SUBSTRING: {
|
||||||
@@ -292,8 +294,8 @@ OEMCryptoResult ODK_ReadSingleField(const uint8_t* buf,
|
|||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
memcpy(&off, buf, sizeof(off));
|
memcpy(&off, buf, sizeof(off));
|
||||||
memcpy(&len, buf + sizeof(off), sizeof(len));
|
memcpy(&len, buf + sizeof(off), sizeof(len));
|
||||||
s->offset = be32toh(off);
|
s->offset = oemcrypto_be32toh(off);
|
||||||
s->length = be32toh(len);
|
s->length = oemcrypto_be32toh(len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ODK_DEVICEID:
|
case ODK_DEVICEID:
|
||||||
@@ -318,7 +320,7 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
|||||||
case ODK_UINT16: {
|
case ODK_UINT16: {
|
||||||
uint16_t val;
|
uint16_t val;
|
||||||
memcpy(&val, buf, sizeof(uint16_t));
|
memcpy(&val, buf, sizeof(uint16_t));
|
||||||
val = be16toh(val);
|
val = oemcrypto_be16toh(val);
|
||||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||||
<< "\n";
|
<< "\n";
|
||||||
break;
|
break;
|
||||||
@@ -326,7 +328,7 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
|||||||
case ODK_UINT32: {
|
case ODK_UINT32: {
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
memcpy(&val, buf, sizeof(uint32_t));
|
memcpy(&val, buf, sizeof(uint32_t));
|
||||||
val = be32toh(val);
|
val = oemcrypto_be32toh(val);
|
||||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||||
<< "\n";
|
<< "\n";
|
||||||
break;
|
break;
|
||||||
@@ -334,7 +336,7 @@ OEMCryptoResult ODK_DumpSingleField(const uint8_t* buf,
|
|||||||
case ODK_UINT64: {
|
case ODK_UINT64: {
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
memcpy(&val, buf, sizeof(uint64_t));
|
memcpy(&val, buf, sizeof(uint64_t));
|
||||||
val = be64toh(val);
|
val = oemcrypto_be64toh(val);
|
||||||
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
std::cerr << field->name << ": " << val << " = 0x" << std::hex << val
|
||||||
<< "\n";
|
<< "\n";
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user