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:
Fred Gylys-Colwell
2021-04-09 14:43:02 -07:00
parent 985d0b5129
commit 6a59fee30a
22 changed files with 588 additions and 324 deletions

View File

@@ -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",

View File

@@ -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

View File

@@ -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,

View 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_

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);

View 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;
}

View 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_

View File

@@ -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;
}

View File

@@ -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
} }

View File

@@ -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);

View File

@@ -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

View File

@@ -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); }

View File

@@ -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"

View File

@@ -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;
} }

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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>

View File

@@ -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;