Update Partner Repo
This update brings the partner repo up-to-date with commit ae93405f980295f9a783bd04e2132a2370720107 in the internal repo.
This commit is contained in:
@@ -39,13 +39,11 @@ bool ParseRequest(uint32_t message_type,
|
||||
reinterpret_cast<const uint8_t*>(oemcrypto_core_message.c_str());
|
||||
const size_t buf_length = oemcrypto_core_message.size();
|
||||
|
||||
Message* msg = nullptr;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, const_cast<uint8_t*>(buf), buf_length);
|
||||
SetSize(msg, buf_length);
|
||||
ODK_Message msg = ODK_Message_Create(const_cast<uint8_t*>(buf), buf_length);
|
||||
ODK_Message_SetSize(&msg, buf_length);
|
||||
|
||||
unpacker(msg, prepared);
|
||||
if (!ValidMessage(msg)) {
|
||||
unpacker(&msg, prepared);
|
||||
if (!ODK_Message_IsValid(&msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -62,7 +60,7 @@ bool ParseRequest(uint32_t message_type,
|
||||
} else if (core_request->api_major_version == 16) {
|
||||
// For version 16, we demand a minor version of at least 2.
|
||||
// We accept 16.2, 16.3, or higher.
|
||||
if (core_request->api_major_version < 2) return false;
|
||||
if (core_request->api_minor_version < 2) return false;
|
||||
} else {
|
||||
// Other versions do not (yet) have a restriction on minor number.
|
||||
// In particular, future versions are accepted for forward compatibility.
|
||||
@@ -70,7 +68,8 @@ bool ParseRequest(uint32_t message_type,
|
||||
// For v16, a release and a renewal use the same message structure.
|
||||
// However, for future API versions, the release might be a separate
|
||||
// message. Otherwise, we expect an exact match of message types.
|
||||
if (core_message.message_type != message_type &&
|
||||
if (message_type != ODK_Common_Request_Type &&
|
||||
core_message.message_type != message_type &&
|
||||
!(message_type == ODK_Renewal_Request_Type &&
|
||||
core_message.message_type == ODK_Release_Request_Type)) {
|
||||
return false;
|
||||
@@ -79,7 +78,7 @@ bool ParseRequest(uint32_t message_type,
|
||||
// than the total message size. We allow the total message size to be larger
|
||||
// for forward compatibility because future messages might have extra fields
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -129,5 +128,13 @@ bool CoreProvisioningRequestFromMessage(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreCommonRequestFromMessage(const std::string& oemcrypto_core_message,
|
||||
ODK_CommonRequest* common_request) {
|
||||
const auto unpacker = Unpack_ODK_PreparedCommonRequest;
|
||||
ODK_PreparedCommonRequest prepared_common = {};
|
||||
return ParseRequest(ODK_Common_Request_Type, oemcrypto_core_message,
|
||||
common_request, &prepared_common, unpacker);
|
||||
}
|
||||
|
||||
} // namespace deserialize
|
||||
} // namespace oemcrypto_core_message
|
||||
|
||||
@@ -46,22 +46,23 @@ bool CreateResponse(uint32_t message_type, const S& core_request,
|
||||
if (core_request.api_major_version > ODK_MAJOR_VERSION) {
|
||||
header->nonce_values.api_major_version = ODK_MAJOR_VERSION;
|
||||
header->nonce_values.api_minor_version = ODK_MINOR_VERSION;
|
||||
} else if (core_request.api_major_version == ODK_MAJOR_VERSION &&
|
||||
core_request.api_minor_version > ODK_MINOR_VERSION) {
|
||||
header->nonce_values.api_minor_version = ODK_MINOR_VERSION;
|
||||
}
|
||||
|
||||
static constexpr size_t BUF_CAPACITY = 2048;
|
||||
std::vector<uint8_t> buf(BUF_CAPACITY, 0);
|
||||
Message* msg = nullptr;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, buf.data(), buf.capacity());
|
||||
packer(msg, &response);
|
||||
if (!ValidMessage(msg)) {
|
||||
ODK_Message msg = ODK_Message_Create(buf.data(), buf.capacity());
|
||||
packer(&msg, &response);
|
||||
if (!ODK_Message_IsValid(&msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t message_length = GetSize(msg);
|
||||
InitMessage(msg, buf.data() + sizeof(header->message_type),
|
||||
sizeof(header->message_length));
|
||||
Pack_uint32_t(msg, &message_length);
|
||||
uint32_t message_length = ODK_Message_GetSize(&msg);
|
||||
msg = ODK_Message_Create(buf.data() + sizeof(header->message_type),
|
||||
sizeof(header->message_length));
|
||||
Pack_uint32_t(&msg, &message_length);
|
||||
oemcrypto_core_message->assign(reinterpret_cast<const char*>(buf.data()),
|
||||
message_length);
|
||||
return true;
|
||||
|
||||
@@ -41,17 +41,23 @@ OEMCrypto_Substring GetOecSubstring(const std::string& message,
|
||||
}
|
||||
|
||||
OEMCrypto_KeyObject KeyContainerToOecKey(
|
||||
const std::string& proto, const video_widevine::License::KeyContainer& k) {
|
||||
const std::string& proto, const video_widevine::License::KeyContainer& k,
|
||||
const bool uses_padding) {
|
||||
OEMCrypto_KeyObject obj = {};
|
||||
obj.key_id = GetOecSubstring(proto, k.id());
|
||||
obj.key_data_iv = GetOecSubstring(proto, k.iv());
|
||||
// Strip off PKCS#5 padding - since we know the key is 16 or 32 bytes,
|
||||
// the padding will always be 16 bytes.
|
||||
const std::string& key_data = k.key();
|
||||
const size_t PKCS5_PADDING_SIZE = 16;
|
||||
obj.key_data = GetOecSubstring(
|
||||
proto, key_data.substr(0, std::max(PKCS5_PADDING_SIZE, key_data.size()) -
|
||||
PKCS5_PADDING_SIZE));
|
||||
|
||||
OEMCrypto_Substring key_data = GetOecSubstring(proto, k.key());
|
||||
|
||||
// Strip off PKCS#5 padding. A key can either be 16 of 32 bytes, but that
|
||||
// makes it hard to know if a key (when 32 bytes) is a 16 byte key with
|
||||
// padding or a 32 byte key without padding.
|
||||
if (uses_padding) {
|
||||
const size_t PKCS5_PADDING_SIZE = 16;
|
||||
key_data.length -= PKCS5_PADDING_SIZE;
|
||||
}
|
||||
obj.key_data = key_data;
|
||||
|
||||
if (k.has_key_control()) {
|
||||
const auto& key_control = k.key_control();
|
||||
obj.key_control_iv = GetOecSubstring(proto, key_control.iv());
|
||||
@@ -68,6 +74,7 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
||||
const ODK_LicenseRequest& core_request,
|
||||
const std::string& core_request_sha256,
|
||||
const bool nonce_required,
|
||||
const bool uses_padding,
|
||||
std::string* oemcrypto_core_message) {
|
||||
video_widevine::License lic;
|
||||
if (!lic.ParseFromString(serialized_license)) {
|
||||
@@ -102,7 +109,8 @@ bool CreateCoreLicenseResponseFromProto(const std::string& serialized_license,
|
||||
return false;
|
||||
}
|
||||
uint32_t& n = parsed_lic.key_array_length;
|
||||
parsed_lic.key_array[n++] = KeyContainerToOecKey(serialized_license, k);
|
||||
parsed_lic.key_array[n++] =
|
||||
KeyContainerToOecKey(serialized_license, k, uses_padding);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
static OEMCryptoResult ODK_PrepareRequest(
|
||||
uint8_t* message, size_t message_length, size_t* core_message_length,
|
||||
uint32_t message_type, const ODK_NonceValues* nonce_values,
|
||||
ODK_MessageType message_type, const ODK_NonceValues* nonce_values,
|
||||
void* prepared_request_buffer, size_t prepared_request_buffer_length) {
|
||||
if (nonce_values == NULL || core_message_length == NULL ||
|
||||
prepared_request_buffer == NULL ||
|
||||
@@ -27,9 +27,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
Message* msg = NULL;
|
||||
AllocateMessage(&msg, message_block);
|
||||
InitMessage(msg, message, *core_message_length);
|
||||
ODK_Message msg = ODK_Message_Create(message, *core_message_length);
|
||||
|
||||
/* The core message should be at the beginning of the buffer, and with a
|
||||
* shorter length. */
|
||||
@@ -52,7 +50,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedLicenseRequest(
|
||||
msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||
&msg, (ODK_PreparedLicenseRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Renewal_Request_Type: {
|
||||
@@ -61,7 +59,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedRenewalRequest(
|
||||
msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
|
||||
&msg, (ODK_PreparedRenewalRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning_Request_Type: {
|
||||
@@ -71,7 +69,7 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Pack_ODK_PreparedProvisioningRequest(
|
||||
msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
&msg, (ODK_PreparedProvisioningRequest*)prepared_request_buffer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -80,13 +78,13 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
}
|
||||
|
||||
*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
|
||||
* appropriately set, but the message buffer is either empty or too small,
|
||||
* which needs to be initialized and filled in the subsequent call. */
|
||||
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. */
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
@@ -95,21 +93,18 @@ static OEMCryptoResult ODK_PrepareRequest(
|
||||
|
||||
static OEMCryptoResult ODK_ParseResponse(
|
||||
const uint8_t* message, size_t message_length, size_t core_message_length,
|
||||
uint32_t message_type, const ODK_NonceValues* nonce_values,
|
||||
ODK_MessageType message_type, const ODK_NonceValues* nonce_values,
|
||||
void* response_buffer, uint32_t response_buffer_length) {
|
||||
if (message == NULL || response_buffer == NULL ||
|
||||
core_message_length > message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
Message* msg = NULL;
|
||||
AllocateMessage(&msg, message_block);
|
||||
/* We initialize the message buffer with a size of the entire message
|
||||
* length. */
|
||||
InitMessage(msg, (uint8_t*)message, message_length);
|
||||
ODK_Message msg = ODK_Message_Create((uint8_t*)message, message_length);
|
||||
|
||||
/* 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. */
|
||||
SetSize(msg, core_message_length);
|
||||
ODK_Message_SetSize(&msg, core_message_length);
|
||||
|
||||
/* Parse message and unpack it into response buffer. */
|
||||
switch (message_type) {
|
||||
@@ -117,14 +112,14 @@ static OEMCryptoResult ODK_ParseResponse(
|
||||
if (sizeof(ODK_LicenseResponse) > response_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_LicenseResponse(msg, (ODK_LicenseResponse*)response_buffer);
|
||||
Unpack_ODK_LicenseResponse(&msg, (ODK_LicenseResponse*)response_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Renewal_Response_Type: {
|
||||
if (sizeof(ODK_RenewalResponse) > response_buffer_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_RenewalResponse(msg, (ODK_RenewalResponse*)response_buffer);
|
||||
Unpack_ODK_RenewalResponse(&msg, (ODK_RenewalResponse*)response_buffer);
|
||||
break;
|
||||
}
|
||||
case ODK_Provisioning_Response_Type: {
|
||||
@@ -132,7 +127,7 @@ static OEMCryptoResult ODK_ParseResponse(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
Unpack_ODK_ProvisioningResponse(
|
||||
msg, (ODK_ProvisioningResponse*)response_buffer);
|
||||
&msg, (ODK_ProvisioningResponse*)response_buffer);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -141,9 +136,9 @@ static OEMCryptoResult ODK_ParseResponse(
|
||||
}
|
||||
|
||||
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 ||
|
||||
GetOffset(msg) != core_message->message_length) {
|
||||
ODK_Message_GetOffset(&msg) != core_message->message_length) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
@@ -168,7 +163,7 @@ OEMCryptoResult ODK_PrepareCoreLicenseRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedLicenseRequest license_request = {
|
||||
{0},
|
||||
{0, 0, {}},
|
||||
};
|
||||
return ODK_PrepareRequest(
|
||||
message, message_length, core_message_length, ODK_License_Request_Type,
|
||||
@@ -197,7 +192,7 @@ OEMCryptoResult ODK_PrepareCoreRenewalRequest(uint8_t* message,
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
ODK_PreparedRenewalRequest renewal_request = {{0}, 0};
|
||||
ODK_PreparedRenewalRequest renewal_request = {{0, 0, {}}, 0};
|
||||
/* First, we compute the time this request was made relative to the playback
|
||||
* clock. */
|
||||
if (clock_values->time_of_first_decrypt == 0) {
|
||||
@@ -231,14 +226,14 @@ OEMCryptoResult ODK_PrepareCoreProvisioningRequest(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
ODK_PreparedProvisioningRequest provisioning_request = {
|
||||
{0},
|
||||
{0, 0, {}},
|
||||
0,
|
||||
{0},
|
||||
};
|
||||
if (device_id_length > sizeof(provisioning_request.device_id)) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
provisioning_request.device_id_length = device_id_length;
|
||||
provisioning_request.device_id_length = (uint32_t)device_id_length;
|
||||
if (device_id) {
|
||||
memcpy(provisioning_request.device_id, device_id, device_id_length);
|
||||
}
|
||||
@@ -261,7 +256,9 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
ODK_LicenseResponse license_response = {{{0}}, parsed_license, {0}};
|
||||
ODK_LicenseResponse license_response = {{{0, 0, {}}}, NULL, {0}};
|
||||
license_response.parsed_license = parsed_license;
|
||||
|
||||
const OEMCryptoResult err = ODK_ParseResponse(
|
||||
message, message_length, core_message_length, ODK_License_Response_Type,
|
||||
NULL, &license_response, sizeof(ODK_LicenseResponse));
|
||||
@@ -299,20 +296,24 @@ OEMCryptoResult ODK_ParseLicense(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
if (parsed_license->nonce_required) {
|
||||
if (initial_license_load) {
|
||||
if (nonce_values->nonce !=
|
||||
license_response.request.core_message.nonce_values.nonce ||
|
||||
nonce_values->session_id !=
|
||||
license_response.request.core_message.nonce_values.session_id) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
} else { /* !initial_license_load */
|
||||
nonce_values->nonce =
|
||||
license_response.request.core_message.nonce_values.nonce;
|
||||
nonce_values->session_id =
|
||||
license_response.request.core_message.nonce_values.session_id;
|
||||
/* If this is the first time we load this license, then we verify that the
|
||||
* nonce values are the correct, otherwise we copy the nonce values. If the
|
||||
* nonce values are not required to be correct, then we don't know if this is
|
||||
* an initial load or not. In that case, we also copy the values so that we
|
||||
* can use the nonce values later for a renewal.
|
||||
*/
|
||||
if (parsed_license->nonce_required && initial_license_load) {
|
||||
if (nonce_values->nonce !=
|
||||
license_response.request.core_message.nonce_values.nonce ||
|
||||
nonce_values->session_id !=
|
||||
license_response.request.core_message.nonce_values.session_id) {
|
||||
return OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
} 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,
|
||||
* OEMCrypto stores a hash of the core license request and only signs the
|
||||
@@ -342,7 +343,7 @@ OEMCryptoResult ODK_ParseRenewal(const uint8_t* message, size_t message_length,
|
||||
}
|
||||
|
||||
ODK_RenewalResponse renewal_response = {
|
||||
{{0}, 0},
|
||||
{{0, 0, {}}, 0},
|
||||
0,
|
||||
};
|
||||
const OEMCryptoResult err = ODK_ParseResponse(
|
||||
@@ -359,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
|
||||
* 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 <
|
||||
renewal_response.request.playback_time) {
|
||||
if (clock_values->timer_status != ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED &&
|
||||
clock_values->time_of_renewal_request <
|
||||
renewal_response.request.playback_time) {
|
||||
return ODK_STALE_RENEWAL;
|
||||
}
|
||||
return ODK_ComputeRenewalDuration(timer_limits, clock_values, system_time,
|
||||
@@ -378,8 +382,9 @@ OEMCryptoResult ODK_ParseProvisioning(
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
ODK_ProvisioningResponse provisioning_response = {{{0}, 0, {0}},
|
||||
parsed_response};
|
||||
ODK_ProvisioningResponse provisioning_response = {{{0, 0, {}}, 0, {0}}, NULL};
|
||||
provisioning_response.parsed_provisioning = parsed_response;
|
||||
|
||||
if (device_id_length > ODK_DEVICE_ID_LEN_MAX) {
|
||||
return ODK_ERROR_CORE_MESSAGE;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
{
|
||||
'sources': [
|
||||
'odk.c',
|
||||
'odk_message.c',
|
||||
'odk_overflow.c',
|
||||
'odk_serialize.c',
|
||||
'odk_timer.c',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_SRC_ODK_ASSERT_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_ASSERT_H_
|
||||
@@ -21,4 +21,4 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_ASSERT_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_ASSERT_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_SRC_ODK_ENDIAN_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
|
||||
@@ -15,7 +15,7 @@ extern "C" {
|
||||
#define oemcrypto_be32toh be32toh
|
||||
#define oemcrypto_htobe64 htobe64
|
||||
#define oemcrypto_be64toh be64toh
|
||||
#else /* defined(__linux__) || defined(__ANDROID__) */
|
||||
#else /* defined(__linux__) || defined(__ANDROID__) */
|
||||
uint32_t oemcrypto_htobe32(uint32_t u32);
|
||||
uint32_t oemcrypto_be32toh(uint32_t u32);
|
||||
uint64_t oemcrypto_htobe64(uint64_t u64);
|
||||
@@ -26,4 +26,4 @@ uint64_t oemcrypto_be64toh(uint64_t u64);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_ENDIAN_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_ENDIAN_H_
|
||||
|
||||
163
oemcrypto/odk/src/odk_message.c
Normal file
163
oemcrypto/odk/src/odk_message.c
Normal file
@@ -0,0 +1,163 @@
|
||||
// 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 <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "odk_message_priv.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. 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) {
|
||||
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;
|
||||
ODK_Message_Clear(&message);
|
||||
if (buffer == NULL || capacity == 0) {
|
||||
message_impl->status = MESSAGE_STATUS_NOT_INITIALIZED;
|
||||
}
|
||||
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 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);
|
||||
ODK_Message_Reset(message);
|
||||
message_impl->size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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);
|
||||
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.
|
||||
*/
|
||||
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->base == NULL) {
|
||||
message_impl->status = MESSAGE_STATUS_NULL_POINTER_ERROR;
|
||||
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
oemcrypto/odk/src/odk_message_priv.h
Normal file
41
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_SRC_ODK_MESSAGE_PRIV_H_
|
||||
#define WIDEVINE_ODK_SRC_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>
|
||||
|
||||
#include "odk_message.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_SRC_ODK_MESSAGE_PRIV_H_
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_SRC_ODK_OVERFLOW_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
|
||||
@@ -20,4 +20,4 @@ int odk_add_overflow_ux(size_t a, size_t b, size_t* c);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_OVERFLOW_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*
|
||||
* This code is auto-generated, do not edit
|
||||
@@ -13,20 +13,20 @@
|
||||
|
||||
/* @@ 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_major_version);
|
||||
Pack_uint32_t(msg, &obj->nonce);
|
||||
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_length);
|
||||
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) {
|
||||
Pack_OEMCrypto_Substring(msg, &obj->key_id);
|
||||
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);
|
||||
}
|
||||
|
||||
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_playback_duration);
|
||||
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);
|
||||
}
|
||||
|
||||
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 */
|
||||
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
Pack_enum(msg, obj->key_type);
|
||||
Pack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
||||
@@ -74,19 +75,19 @@ static void Pack_ODK_ParsedProvisioning(Message* msg,
|
||||
|
||||
/* @@ odk serialize */
|
||||
|
||||
void Pack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
ODK_PreparedLicenseRequest const* obj) {
|
||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
}
|
||||
|
||||
void Pack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
ODK_PreparedRenewalRequest const* obj) {
|
||||
Pack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
Pack_uint64_t(msg, &obj->playback_time);
|
||||
}
|
||||
|
||||
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_uint32_t(msg, &obj->device_id_length);
|
||||
PackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||
@@ -94,18 +95,20 @@ void Pack_ODK_PreparedProvisioningRequest(
|
||||
|
||||
/* @@ 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_ParsedLicense(msg, (const ODK_ParsedLicense*)obj->parsed_license);
|
||||
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_uint64_t(msg, &obj->renewal_duration_seconds);
|
||||
}
|
||||
|
||||
void Pack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
ODK_ProvisioningResponse const* obj) {
|
||||
Pack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
||||
Pack_ODK_ParsedProvisioning(
|
||||
@@ -116,20 +119,21 @@ void Pack_ODK_ProvisioningResponse(Message* msg,
|
||||
|
||||
/* @@ 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_major_version);
|
||||
Unpack_uint32_t(msg, &obj->nonce);
|
||||
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_length);
|
||||
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_data_iv);
|
||||
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);
|
||||
}
|
||||
|
||||
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_playback_duration);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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_uint32_t(msg, &obj->key_array_length);
|
||||
if (obj->key_array_length > ODK_MAX_NUM_KEYS) {
|
||||
SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
ODK_Message_SetStatus(msg, MESSAGE_STATUS_OVERFLOW_ERROR);
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
obj->key_type = (OEMCrypto_PrivateKeyType)Unpack_enum(msg);
|
||||
Unpack_OEMCrypto_Substring(msg, &obj->enc_private_key);
|
||||
@@ -175,38 +179,42 @@ static void Unpack_ODK_ParsedProvisioning(Message* msg,
|
||||
|
||||
/* @ kdo deserialize */
|
||||
|
||||
void Unpack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
ODK_PreparedLicenseRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
}
|
||||
|
||||
void Unpack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
ODK_PreparedRenewalRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
Unpack_uint64_t(msg, &obj->playback_time);
|
||||
}
|
||||
|
||||
void Unpack_ODK_PreparedProvisioningRequest(
|
||||
Message* msg, ODK_PreparedProvisioningRequest* obj) {
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
Unpack_uint32_t(msg, &obj->device_id_length);
|
||||
UnpackArray(msg, &obj->device_id[0], sizeof(obj->device_id));
|
||||
}
|
||||
|
||||
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
||||
ODK_PreparedCommonRequest* obj) {
|
||||
Unpack_ODK_CoreMessage(msg, &obj->core_message);
|
||||
}
|
||||
/* @@ 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_ParsedLicense(msg, obj->parsed_license);
|
||||
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_uint64_t(msg, &obj->renewal_duration_seconds);
|
||||
}
|
||||
|
||||
void Unpack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
ODK_ProvisioningResponse* obj) {
|
||||
Unpack_ODK_PreparedProvisioningRequest(msg, &obj->request);
|
||||
Unpack_ODK_ParsedProvisioning(msg, obj->parsed_provisioning);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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.
|
||||
|
||||
/*
|
||||
* This code is auto-generated, do not edit
|
||||
@@ -16,34 +16,37 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* odk pack */
|
||||
void Pack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Pack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
const ODK_PreparedLicenseRequest* obj);
|
||||
void Pack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Pack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
const ODK_PreparedRenewalRequest* obj);
|
||||
void Pack_ODK_PreparedProvisioningRequest(
|
||||
Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
||||
ODK_Message* msg, const ODK_PreparedProvisioningRequest* obj);
|
||||
|
||||
/* odk unpack */
|
||||
void Unpack_ODK_LicenseResponse(Message* msg, ODK_LicenseResponse* obj);
|
||||
void Unpack_ODK_RenewalResponse(Message* msg, ODK_RenewalResponse* obj);
|
||||
void Unpack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Unpack_ODK_LicenseResponse(ODK_Message* msg, ODK_LicenseResponse* obj);
|
||||
void Unpack_ODK_RenewalResponse(ODK_Message* msg, ODK_RenewalResponse* obj);
|
||||
void Unpack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
ODK_ProvisioningResponse* obj);
|
||||
|
||||
/* kdo pack */
|
||||
void Pack_ODK_LicenseResponse(Message* msg, const ODK_LicenseResponse* obj);
|
||||
void Pack_ODK_RenewalResponse(Message* msg, const ODK_RenewalResponse* obj);
|
||||
void Pack_ODK_ProvisioningResponse(Message* msg,
|
||||
void Pack_ODK_LicenseResponse(ODK_Message* msg, const ODK_LicenseResponse* obj);
|
||||
void Pack_ODK_RenewalResponse(ODK_Message* msg, const ODK_RenewalResponse* obj);
|
||||
void Pack_ODK_ProvisioningResponse(ODK_Message* msg,
|
||||
const ODK_ProvisioningResponse* obj);
|
||||
|
||||
/* kdo unpack */
|
||||
void Unpack_ODK_PreparedLicenseRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedLicenseRequest(ODK_Message* msg,
|
||||
ODK_PreparedLicenseRequest* obj);
|
||||
void Unpack_ODK_PreparedRenewalRequest(Message* msg,
|
||||
void Unpack_ODK_PreparedRenewalRequest(ODK_Message* msg,
|
||||
ODK_PreparedRenewalRequest* obj);
|
||||
void Unpack_ODK_PreparedProvisioningRequest(
|
||||
Message* msg, ODK_PreparedProvisioningRequest* obj);
|
||||
ODK_Message* msg, ODK_PreparedProvisioningRequest* obj);
|
||||
|
||||
void Unpack_ODK_PreparedCommonRequest(ODK_Message* msg,
|
||||
ODK_PreparedCommonRequest* obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_SERIALIZE_H_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_SRC_ODK_STRUCTS_PRIV_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
|
||||
@@ -22,9 +22,11 @@ typedef enum {
|
||||
ODK_Provisioning_Request_Type = 5,
|
||||
ODK_Provisioning_Response_Type = 6,
|
||||
|
||||
/* Reserve future message types to support forward compatibility. */
|
||||
// Reserve future message types to support forward compatibility.
|
||||
ODK_Release_Request_Type = 7,
|
||||
ODK_Release_Response_Type = 8,
|
||||
ODK_Common_Request_Type = 9,
|
||||
ODK_Common_Response_Type = 10,
|
||||
} ODK_MessageType;
|
||||
|
||||
typedef struct {
|
||||
@@ -48,6 +50,10 @@ typedef struct {
|
||||
uint8_t device_id[ODK_DEVICE_ID_LEN_MAX];
|
||||
} ODK_PreparedProvisioningRequest;
|
||||
|
||||
typedef struct {
|
||||
ODK_CoreMessage core_message;
|
||||
} ODK_PreparedCommonRequest;
|
||||
|
||||
typedef struct {
|
||||
ODK_PreparedLicenseRequest request;
|
||||
ODK_ParsedLicense* parsed_license;
|
||||
@@ -64,33 +70,32 @@ typedef struct {
|
||||
ODK_ParsedProvisioning* parsed_provisioning;
|
||||
} ODK_ProvisioningResponse;
|
||||
|
||||
/* These are the sum of sizeof of each individual member of the request structs
|
||||
*/
|
||||
/* without any padding added by the compiler. Make sure they get updated when */
|
||||
/* request structs change. Refer to test suite OdkSizeTest in */
|
||||
/* ../test/odk_test.cpp for validations of each of the defined request sizes. */
|
||||
// These are the sum of sizeof of each individual member of the request structs
|
||||
// without any padding added by the compiler. Make sure they get updated when
|
||||
// request structs change. Refer to test suite OdkSizeTest in
|
||||
// ../test/odk_test.cpp for validations of each of the defined request sizes.
|
||||
#define ODK_LICENSE_REQUEST_SIZE 20
|
||||
#define ODK_RENEWAL_REQUEST_SIZE 28
|
||||
#define ODK_PROVISIONING_REQUEST_SIZE 88
|
||||
|
||||
/* These are the possible timer status values. */
|
||||
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 /* Should not happen. */
|
||||
/* When the structure has been initialized, but no license is loaded. */
|
||||
// These are the possible timer status values.
|
||||
#define ODK_CLOCK_TIMER_STATUS_UNDEFINED 0 // Should not happen.
|
||||
// When the structure has been initialized, but no license is loaded.
|
||||
#define ODK_CLOCK_TIMER_STATUS_LICENSE_NOT_LOADED 1
|
||||
/* After the license is loaded, before a successful decrypt. */
|
||||
// After the license is loaded, before a successful decrypt.
|
||||
#define ODK_CLOCK_TIMER_STATUS_LICENSE_LOADED 2
|
||||
/* After the license is loaded, if a renewal has also been loaded. */
|
||||
// After the license is loaded, if a renewal has also been loaded.
|
||||
#define ODK_CLOCK_TIMER_STATUS_RENEWAL_LOADED 3
|
||||
/* The first decrypt has occurred and the timer is active. */
|
||||
// The first decrypt has occurred and the timer is active.
|
||||
#define ODK_CLOCK_TIMER_STATUS_ACTIVE 4
|
||||
/* The first decrypt has occurred and the timer is unlimited. */
|
||||
// The first decrypt has occurred and the timer is unlimited.
|
||||
#define ODK_CLOCK_TIMER_STATUS_UNLIMITED 5
|
||||
/* The timer has transitioned from active to expired. */
|
||||
// The timer has transitioned from active to expired.
|
||||
#define ODK_CLOCK_TIMER_STATUS_EXPIRED 6
|
||||
/* The license has been marked as inactive. */
|
||||
// The license has been marked as inactive.
|
||||
#define ODK_CLOCK_TIMER_STATUS_LICENSE_INACTIVE 7
|
||||
|
||||
/* A helper function for computing timer limits when a renewal is loaded. */
|
||||
// A helper function for computing timer limits when a renewal is loaded.
|
||||
OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||
ODK_ClockValues* clock_values,
|
||||
uint64_t system_time_seconds,
|
||||
@@ -101,4 +106,4 @@ OEMCryptoResult ODK_ComputeRenewalDuration(const ODK_TimerLimits* timer_limits,
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_STRUCTS_PRIV_H_
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/* 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. */
|
||||
// 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "odk.h"
|
||||
#include "odk_attributes.h"
|
||||
#include "odk_overflow.h"
|
||||
#include "odk_structs_priv.h"
|
||||
|
||||
@@ -311,7 +312,7 @@ OEMCryptoResult ODK_ReloadClockValues(ODK_ClockValues* clock_values,
|
||||
uint64_t time_of_first_decrypt,
|
||||
uint64_t time_of_last_decrypt,
|
||||
enum OEMCrypto_Usage_Entry_Status status,
|
||||
uint64_t system_time_seconds) {
|
||||
uint64_t system_time_seconds UNUSED) {
|
||||
if (clock_values == NULL) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_util.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_SRC_ODK_UTIL_H_
|
||||
#define WIDEVINE_ODK_SRC_ODK_UTIL_H_
|
||||
@@ -23,6 +23,6 @@ int crypto_memcmp(const void* a, const void* b, size_t len);
|
||||
bool ODK_NonceValuesEqual(const ODK_NonceValues* a, const ODK_NonceValues* b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif /* WIDEVINE_ODK_SRC_ODK_UTIL_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_ODK_UTIL_H_
|
||||
|
||||
@@ -1,82 +1,63 @@
|
||||
/* 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. */
|
||||
// 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 "serialization_base.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "OEMCryptoCENCCommon.h"
|
||||
#include "odk_assert.h"
|
||||
#include "odk_message.h"
|
||||
#include "odk_message_priv.h"
|
||||
#include "odk_overflow.h"
|
||||
|
||||
struct _Message {
|
||||
uint8_t* base;
|
||||
size_t capacity;
|
||||
size_t size; /* bytes written */
|
||||
size_t read_offset; /* bytes read */
|
||||
MessageStatus status;
|
||||
};
|
||||
|
||||
/* TODO(b/150776214): this can be removed once AllocateMessage gets cleaned up
|
||||
*/
|
||||
/*
|
||||
* odk_static_assert(SIZE_OF_MESSAGE_STRUCT >= sizeof(struct _Message),
|
||||
* "SIZE_OF_MESSAGE_STRUCT too small");
|
||||
* An ODK_Message_Impl pointer must only be obtained by calling GetMessageImpl.
|
||||
* This forces any message to pass the validity check before being operated on,
|
||||
* which means that no function can modify or access the internals of a message
|
||||
* without having it be validated first.
|
||||
*/
|
||||
|
||||
bool ValidMessage(Message* 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 ODK_Message_Impl* GetMessageImpl(ODK_Message* message) {
|
||||
if (!ODK_Message_IsValid(message)) return NULL;
|
||||
return (ODK_Message_Impl*)message;
|
||||
}
|
||||
|
||||
static void PackBytes(Message* message, const uint8_t* ptr, size_t count) {
|
||||
if (count <= message->capacity - message->size) {
|
||||
memcpy((void*)(message->base + message->size), (void*)ptr, count);
|
||||
message->size += count;
|
||||
static void PackBytes(ODK_Message* message, const uint8_t* ptr, size_t count) {
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
if (count <= message_impl->capacity - message_impl->size) {
|
||||
memcpy((void*)(message_impl->base + message_impl->size), (void*)ptr, count);
|
||||
message_impl->size += count;
|
||||
} 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;
|
||||
Pack_uint32_t(message, &v32);
|
||||
}
|
||||
|
||||
void Pack_bool(Message* message, const bool* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_bool(ODK_Message* message, const bool* value) {
|
||||
assert(value);
|
||||
uint8_t data[4] = {0};
|
||||
data[3] = *value ? 1 : 0;
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint16_t(Message* message, const uint16_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint16_t(ODK_Message* message, const uint16_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[2] = {0};
|
||||
data[0] = *value >> 8;
|
||||
data[1] = *value >> 0;
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint32_t(Message* message, const uint32_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint32_t(ODK_Message* message, const uint32_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[4] = {0};
|
||||
data[0] = *value >> 24;
|
||||
data[1] = *value >> 16;
|
||||
@@ -85,175 +66,112 @@ void Pack_uint32_t(Message* message, const uint32_t* value) {
|
||||
PackBytes(message, data, sizeof(data));
|
||||
}
|
||||
|
||||
void Pack_uint64_t(Message* message, const uint64_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Pack_uint64_t(ODK_Message* message, const uint64_t* value) {
|
||||
assert(value);
|
||||
uint32_t hi = *value >> 32;
|
||||
uint32_t lo = *value;
|
||||
Pack_uint32_t(message, &hi);
|
||||
Pack_uint32_t(message, &lo);
|
||||
}
|
||||
|
||||
void PackArray(Message* message, const uint8_t* base, size_t size) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void PackArray(ODK_Message* message, const uint8_t* base, size_t size) {
|
||||
PackBytes(message, base, size);
|
||||
}
|
||||
|
||||
void Pack_OEMCrypto_Substring(Message* msg, const OEMCrypto_Substring* obj) {
|
||||
uint32_t offset = obj->offset;
|
||||
uint32_t length = obj->length;
|
||||
Pack_uint32_t(msg, &offset);
|
||||
Pack_uint32_t(msg, &length);
|
||||
void Pack_OEMCrypto_Substring(ODK_Message* message,
|
||||
const OEMCrypto_Substring* obj) {
|
||||
assert(obj);
|
||||
uint32_t offset = (uint32_t)obj->offset;
|
||||
uint32_t length = (uint32_t)obj->length;
|
||||
Pack_uint32_t(message, &offset);
|
||||
Pack_uint32_t(message, &length);
|
||||
}
|
||||
|
||||
static void UnpackBytes(Message* message, uint8_t* ptr, size_t count) {
|
||||
if (count <= message->size - message->read_offset) {
|
||||
memcpy((void*)ptr, (void*)(message->base + message->read_offset), count);
|
||||
message->read_offset += count;
|
||||
static void UnpackBytes(ODK_Message* message, uint8_t* ptr, size_t count) {
|
||||
assert(ptr);
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
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 {
|
||||
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;
|
||||
Unpack_uint32_t(message, &v32);
|
||||
return v32;
|
||||
}
|
||||
|
||||
void Unpack_bool(Message* message, bool* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_bool(ODK_Message* message, bool* value) {
|
||||
uint8_t data[4] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
assert(value);
|
||||
*value = (0 != data[3]);
|
||||
}
|
||||
|
||||
void Unpack_uint16_t(Message* message, uint16_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint16_t(ODK_Message* message, uint16_t* value) {
|
||||
assert(value);
|
||||
uint8_t data[2] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
*value = data[0];
|
||||
*value = *value << 8 | data[1];
|
||||
}
|
||||
|
||||
void Unpack_uint32_t(Message* message, uint32_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint32_t(ODK_Message* message, uint32_t* value) {
|
||||
ODK_Message_Impl* message_impl = (ODK_Message_Impl*)message;
|
||||
if (!message_impl) return;
|
||||
uint8_t data[4] = {0};
|
||||
UnpackBytes(message, data, sizeof(data));
|
||||
assert(value);
|
||||
*value = data[0];
|
||||
*value = *value << 8 | data[1];
|
||||
*value = *value << 8 | data[2];
|
||||
*value = *value << 8 | data[3];
|
||||
}
|
||||
|
||||
void Unpack_uint64_t(Message* message, uint64_t* value) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void Unpack_uint64_t(ODK_Message* message, uint64_t* value) {
|
||||
uint32_t hi = 0;
|
||||
uint32_t lo = 0;
|
||||
Unpack_uint32_t(message, &hi);
|
||||
Unpack_uint32_t(message, &lo);
|
||||
assert(value);
|
||||
*value = hi;
|
||||
*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;
|
||||
Unpack_uint32_t(msg, &offset);
|
||||
Unpack_uint32_t(msg, &length);
|
||||
if (!ValidMessage(msg)) return;
|
||||
Unpack_uint32_t(message, &offset);
|
||||
Unpack_uint32_t(message, &length);
|
||||
ODK_Message_Impl* message_impl = GetMessageImpl(message);
|
||||
if (!message_impl) return;
|
||||
|
||||
/* 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
|
||||
* relative to the message body. So we need to verify:
|
||||
* 0 < offset and offset + length < message->capacity - message->size
|
||||
* or offset + length + message->size < message->capacity
|
||||
* 0 < offset and offset + length < message_impl->capacity -
|
||||
* message_impl->size or offset + length + message_impl->size <
|
||||
* message_impl->capacity
|
||||
*/
|
||||
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) ||
|
||||
odk_add_overflow_ux(substring_end, msg->size, &end) ||
|
||||
end > msg->capacity) {
|
||||
msg->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
odk_add_overflow_ux(substring_end, message_impl->size, &end) ||
|
||||
end > message_impl->capacity) {
|
||||
message_impl->status = MESSAGE_STATUS_OVERFLOW_ERROR;
|
||||
return;
|
||||
}
|
||||
assert(obj);
|
||||
obj->offset = offset;
|
||||
obj->length = length;
|
||||
}
|
||||
|
||||
/* copy out */
|
||||
void UnpackArray(Message* message, uint8_t* address, size_t size) {
|
||||
if (!ValidMessage(message)) return;
|
||||
void UnpackArray(ODK_Message* message, uint8_t* address, size_t 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* The message structure is in the first sizeof(Memory) bytes
|
||||
* of the buffer
|
||||
*/
|
||||
Message* CreateMessage(uint8_t* buffer, size_t buffer_size) {
|
||||
if (buffer == NULL || buffer_size < sizeof(Message)) return NULL;
|
||||
Message* message = (Message*)buffer;
|
||||
message->base = buffer + sizeof(Message);
|
||||
message->capacity = buffer_size - sizeof(Message);
|
||||
message->size = 0;
|
||||
message->read_offset = 0;
|
||||
message->status = MESSAGE_STATUS_OK;
|
||||
return message;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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); }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
// 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_SRC_SERIALIZATION_BASE_H_
|
||||
#define WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
|
||||
@@ -13,84 +13,28 @@ extern "C" {
|
||||
#include <stdint.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* message,
|
||||
const OEMCrypto_Substring* obj);
|
||||
|
||||
/*
|
||||
* Description:
|
||||
* Point |msg| to stack-array |blk|.
|
||||
* |blk| is guaranteed large enough to hold a |Message| struct.
|
||||
* |blk| cannot be used in the same scope as a variable name.
|
||||
* |msg| points to valid memory in the same scope |AllocateMessage| is used.
|
||||
* 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,
|
||||
int Unpack_enum(ODK_Message* message);
|
||||
void Unpack_bool(ODK_Message* message, bool* value);
|
||||
void Unpack_uint16_t(ODK_Message* message, uint16_t* value);
|
||||
void Unpack_uint32_t(ODK_Message* message, uint32_t* value);
|
||||
void Unpack_uint64_t(ODK_Message* message, uint64_t* value);
|
||||
void UnpackArray(ODK_Message* message, uint8_t* address,
|
||||
size_t size); /* copy out */
|
||||
void Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj);
|
||||
|
||||
/*
|
||||
* Create a message from a buffer. The message structure consumes the first
|
||||
* sizeof(Message) bytes of the buffer. The caller is responsible for ensuring
|
||||
* that the buffer remains allocated for the lifetime of the message.
|
||||
*/
|
||||
Message* CreateMessage(uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/*
|
||||
* 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();
|
||||
void Unpack_OEMCrypto_Substring(ODK_Message* message, OEMCrypto_Substring* obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_ */
|
||||
#endif // WIDEVINE_ODK_SRC_SERIALIZATION_BASE_H_
|
||||
|
||||
Reference in New Issue
Block a user