First Publicly Shared Version of ODKiTEE v15

This commit is contained in:
John W. Bruce
2020-07-24 12:03:58 -07:00
commit eaa8984c06
56 changed files with 21391 additions and 0 deletions

File diff suppressed because it is too large Load Diff

123
serialization/api_support.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
/*
* Support functions for the OEMCrypto API functions, related to
* message handling
*/
#include "OEMCryptoCENC.h"
#include "api_support.h"
#include "bump_allocator.h"
#include "message.h"
#include "shared_memory_allocator.h"
#include "shared_memory_interface.h"
#include "special_cases.h"
#include "transport_interface.h"
/*
* If true, the system has been invalidated due to a communications
* breakdown with the TEE. This is a persistent condition and will
* cause OEMCrypto_ERROR_SYSTEM_INVALIDATED to be returned from any
* function that returns an OEMCryptoResult until the transport
* interface is reinitialized.
*/
static bool system_invalidated;
/*
* This is the result code to be returned from any function that
* returns OEMCryptoResult code.
*/
OEMCryptoResult api_result;
/*
* odkitee OEMCrypto API is single threaded
*/
pthread_mutex_t api_lock;
/*
* Called at the beginning of every API function. Checks configuration
* state and if it is okay allocates a request message. Sets
* api_result based on the status of the operations, which will be
* returned from any API function that returns an OEMCryptoResult
* code. On exit, if api_result is not OEMCrypto_SUCCESS or NULL is
* returned, then any allocated messages will have been deallocated
* prior to returning.
*/
Message *API_InitializeRequest(void) {
api_result = OEMCrypto_SUCCESS;
SharedMemory_Reset();
BumpAllocator_Reset();
Message* request = ODK_Transport_AllocateMessage();
if (request == NULL) {
api_result = OEMCrypto_ERROR_INSUFFICIENT_RESOURCES;
} else if (GetStatus(request) != MESSAGE_STATUS_OK) {
/* The transport allocator must return initialized messages */
api_result = OEMCrypto_ERROR_SYSTEM_INVALIDATED;
}
if (api_result != OEMCrypto_SUCCESS) {
if (request != NULL) {
ODK_Transport_DeallocateMessage(request);
request = NULL;
}
}
return request;
}
/*
* Called to send the request message to the TEE and receive the
* response. Sets api_result based on the status of the
* operations. Returns either a valid response message or NULL. If
* NULL is returned or api_result != OEMCrypto_SUCCESS then any
* allocated messages will have been deallocated prior to returning.
*/
Message *API_Transact(Message* request) {
if (api_result != OEMCrypto_SUCCESS || request == NULL) {
return NULL;
}
ODK_Transport_Status transport_status = ODK_Transport_SendMessage(request);
Message* response = NULL;
if (transport_status == ODK_TRANSPORT_STATUS_IO_ERROR) {
api_result = OEMCrypto_ERROR_SYSTEM_INVALIDATED;
} else {
transport_status = ODK_Transport_ReceiveMessage(&response);
if (transport_status == ODK_TRANSPORT_STATUS_IO_ERROR || response == NULL) {
api_result = OEMCrypto_ERROR_SYSTEM_INVALIDATED;
} else if (GetStatus(response) != MESSAGE_STATUS_OK) {
api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
if (api_result != OEMCrypto_SUCCESS) {
if (response) {
ODK_Transport_DeallocateMessage(response);
response = NULL;
}
}
return response;
}
/*
* Called at the end of every API function. Sets system_invalidated if
* the local api_result indicates a failure in the current
* function. Once system_invalidated is set, it will persist until
* reset by the next OEMCrypto_Inititalize/OEMCrypto_Terminate.
*/
OEMCryptoResult API_CheckResult(OEMCryptoResult unpacked_result) {
if (api_result == OEMCrypto_ERROR_SYSTEM_INVALIDATED) {
system_invalidated = true;
} else if (api_result == OEMCrypto_SUCCESS) {
api_result = unpacked_result;
}
return api_result;
}
/*
* Called by OEMCrypto_Terminate
*/
void API_Terminate(void) {
system_invalidated = false;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
/*
* Support functions for the OEMCrypto API functions, related to
* message handling
*/
#include <pthread.h>
#include "OEMCryptoCENC.h"
#include "bump_allocator.h"
#include "deserializer.h"
#include "marshaller_base.h"
#include "serializer.h"
#include "shared_memory_allocator.h"
#include "shared_memory_interface.h"
#include "special_cases.h"
#include "transport_interface.h"
#ifndef ODKITEE_API_SUPPORT_H_
#define ODKITEE_API_SUPPORT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define OEMCRYPTO_API __attribute__((visibility("default")))
extern pthread_mutex_t api_lock;
extern OEMCryptoResult api_result;
Message *API_InitializeRequest();
Message *API_Transact(Message *request);
OEMCryptoResult API_CheckResult(OEMCryptoResult unpacked_result);
void API_Terminate();
#ifdef __cplusplus
}
#endif
#endif /* ODKITEE_API_SUPOPRT_H_ */

View File

@@ -0,0 +1,61 @@
/*
* 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 "bump_allocator.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INITIAL_ALLOCATOR_BUFFER_SIZE (8 * 1024)
static uint8_t buffer[INITIAL_ALLOCATOR_BUFFER_SIZE];
static uint8_t* ptr = buffer;
static size_t buffer_size = sizeof(buffer);
static size_t buffer_offset = 0;
uint8_t* BumpAllocate(size_t nbytes) {
size_t new_offset = 0;
if(__builtin_add_overflow(buffer_offset, nbytes, &new_offset) ||
(new_offset > buffer_size)) {
/*
* The bump allocator buffer should be large enough that a malloc
* is never required. But allow a malloc if the buffer overflows.
*/
fprintf(stderr, "Warning: bump allocator memory size exceeded,"
" size=%zd, requested=%zd\n", buffer_size, new_offset);
size_t new_size = 2 * buffer_size;
uint8_t* new_ptr = malloc(new_size);
if (new_ptr == NULL) {
fprintf(stderr, "Fatal: bump allocator could not malloc %zd bytes\n",
new_size);
abort();
}
memcpy(new_ptr, ptr, buffer_size);
memset(new_ptr + buffer_size, 0, buffer_size);
buffer_size = new_size;
if (ptr != buffer) {
free(ptr);
}
ptr = new_ptr;
}
uint8_t* result = ptr + buffer_offset;
memset(result, 0, nbytes);
buffer_offset = new_offset;
return result;
}
void BumpAllocator_Reset(void) {
buffer_offset = 0;
if (ptr != buffer) {
free(ptr);
}
ptr = buffer;
buffer_size = sizeof(buffer);
memset(buffer, 0, sizeof(buffer));
}

View File

@@ -0,0 +1,29 @@
/*
* 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 ODKITEE_BUMP_ALLOCATOR_H_
#define ODKITEE_BUMP_ALLOCATOR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
/*
* Simple bump allocator. Allocate memory chunks from a fixed region
* at consecutively increasing offsets. The memory is all released
* when BumpAllocator_Reset is called.
*/
uint8_t* BumpAllocate(size_t size);
void BumpAllocator_Reset(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //ODKITEE_BUMP_ALLOCATOR_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,383 @@
/*
* 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
*/
#ifndef ODKITEE_DESERIALIZER_H_
#define ODKITEE_DESERIALIZER_H_
#include "deserializer.h"
#include "serialization_base.h"
#include "serializer.h"
#ifdef __cplusplus
extern "C" {
#endif
bool Is_Valid_OEMCryptoResult(uint32_t value);
bool Is_Valid_OEMCryptoBufferType(uint32_t value);
bool Is_Valid_OEMCryptoCipherMode(uint32_t value);
bool Is_Valid_OEMCrypto_LicenseType(uint32_t value);
bool Is_Valid_OEMCrypto_Algorithm(uint32_t value);
bool Is_Valid_OEMCrypto_Usage_Entry_Status(uint32_t value);
bool Is_Valid_OEMCrypto_Clock_Security_Level(uint32_t value);
bool Is_Valid_OEMCrypto_HDCP_Capability(uint32_t value);
bool Is_Valid_OEMCrypto_ProvisioningMethod(uint32_t value);
void ODK_Unpack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring* obj);
void ODK_Unpack_OEMCrypto_KeyObject(Message* msg, OEMCrypto_KeyObject* obj);
void ODK_Unpack_OEMCrypto_EntitledContentKeyObject(
Message* msg, OEMCrypto_EntitledContentKeyObject* obj);
void ODK_Unpack_OEMCrypto_KeyRefreshObject(Message* msg,
OEMCrypto_KeyRefreshObject* obj);
void ODK_Unpack_OEMCrypto_CENCEncryptPatternDesc(
Message* msg, OEMCrypto_CENCEncryptPatternDesc* obj);
void ODK_Unpack_SecurityLevel_Request(Message* msg);
void ODK_Unpack_SecurityLevel_Response(Message* msg, char** result);
void ODK_Unpack_BuildInformation_Request(Message* msg);
void ODK_Unpack_BuildInformation_Response(Message* msg, char** result);
void ODK_Unpack_SetSandbox_Request(Message* msg, uint8_t** sandbox_id,
size_t* sandbox_id_length);
void ODK_Unpack_SetSandbox_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_Initialize_Request(Message* msg);
void ODK_Unpack_Initialize_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_Terminate_Request(Message* msg);
void ODK_Unpack_Terminate_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_OpenSession_Request(Message* msg, OEMCrypto_SESSION** session);
void ODK_Unpack_OpenSession_Response(Message* msg, OEMCryptoResult* result,
OEMCrypto_SESSION** session);
void ODK_Unpack_CloseSession_Request(Message* msg, OEMCrypto_SESSION* session);
void ODK_Unpack_CloseSession_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_GenerateDerivedKeys_Request(Message* msg,
OEMCrypto_SESSION* session,
SharedMemory** mac_key_context,
uint32_t* mac_key_context_length,
SharedMemory** enc_key_context,
uint32_t* enc_key_context_length);
void ODK_Unpack_GenerateDerivedKeys_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_DeriveKeysFromSessionKey_Request(
Message* msg, OEMCrypto_SESSION* session, uint8_t** enc_session_key,
size_t* enc_session_key_length, SharedMemory** mac_key_context,
size_t* mac_key_context_length, SharedMemory** enc_key_context,
size_t* enc_key_context_length);
void ODK_Unpack_DeriveKeysFromSessionKey_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_GenerateNonce_Request(Message* msg, OEMCrypto_SESSION* session,
uint32_t** nonce);
void ODK_Unpack_GenerateNonce_Response(Message* msg, OEMCryptoResult* result,
uint32_t** nonce);
void ODK_Unpack_GenerateSignature_Request(
Message* msg, OEMCrypto_SESSION* session, SharedMemory** message,
size_t* message_length, uint8_t** signature, size_t** signature_length);
void ODK_Unpack_GenerateSignature_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** signature,
size_t** signature_length);
void ODK_Unpack_LoadSRM_Request(Message* msg, uint8_t** buffer,
size_t* buffer_length);
void ODK_Unpack_LoadSRM_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_LoadKeys_Request(
Message* msg, OEMCrypto_SESSION* session, SharedMemory** message,
size_t* message_length, SharedMemory** signature, size_t* signature_length,
OEMCrypto_Substring* enc_mac_keys_iv, OEMCrypto_Substring* enc_mac_keys,
size_t* key_array_length, OEMCrypto_KeyObject** key_array,
OEMCrypto_Substring* pst, OEMCrypto_Substring* srm_restriction_data,
OEMCrypto_LicenseType* license_type);
void ODK_Unpack_LoadKeys_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_LoadEntitledContentKeys_Request(
Message* msg, OEMCrypto_SESSION* session, SharedMemory** message,
size_t* message_length, size_t* key_array_length,
OEMCrypto_EntitledContentKeyObject** key_array);
void ODK_Unpack_LoadEntitledContentKeys_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_RefreshKeys_Request(
Message* msg, OEMCrypto_SESSION* session, SharedMemory** message,
size_t* message_length, SharedMemory** signature, size_t* signature_length,
size_t* key_array_length, OEMCrypto_KeyRefreshObject** key_array);
void ODK_Unpack_RefreshKeys_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_QueryKeyControl_Request(Message* msg,
OEMCrypto_SESSION* session,
uint8_t** content_key_id,
size_t* content_key_id_length,
uint8_t** key_control_block,
size_t** key_control_block_length);
void ODK_Unpack_QueryKeyControl_Response(Message* msg, OEMCryptoResult* result,
uint8_t** key_control_block,
size_t** key_control_block_length);
void ODK_Unpack_SelectKey_Request(Message* msg, OEMCrypto_SESSION* session,
uint8_t** content_key_id,
size_t* content_key_id_length,
OEMCryptoCipherMode* cipher_mode);
void ODK_Unpack_SelectKey_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_DecryptCENC_Request(
Message* msg, OEMCrypto_SESSION* session, SharedMemory** data_addr,
size_t* data_addr_length, bool* is_encrypted, uint8_t* iv,
size_t* block_offset, OEMCrypto_DestBufferDesc** out_buffer,
OEMCrypto_CENCEncryptPatternDesc** pattern, uint8_t* subsample_flags);
void ODK_Unpack_DecryptCENC_Response(Message* msg, OEMCryptoResult* result,
OEMCrypto_DestBufferDesc** out_buffer);
void ODK_Unpack_CopyBuffer_Request(Message* msg, OEMCrypto_SESSION* session,
SharedMemory** data_addr,
size_t* data_addr_length,
OEMCrypto_DestBufferDesc** out_buffer,
uint8_t* subsample_flags);
void ODK_Unpack_CopyBuffer_Response(Message* msg, OEMCryptoResult* result,
OEMCrypto_DestBufferDesc** out_buffer);
void ODK_Unpack_Generic_Encrypt_Request(Message* msg,
OEMCrypto_SESSION* session,
SharedMemory** in_buffer,
size_t* in_buffer_length, uint8_t* iv,
OEMCrypto_Algorithm* algorithm,
uint8_t** out_buffer);
void ODK_Unpack_Generic_Encrypt_Response(Message* msg, OEMCryptoResult* result,
size_t* in_buffer_length,
uint8_t** out_buffer);
void ODK_Unpack_Generic_Decrypt_Request(Message* msg,
OEMCrypto_SESSION* session,
SharedMemory** in_buffer,
size_t* in_buffer_length, uint8_t* iv,
OEMCrypto_Algorithm* algorithm,
uint8_t** out_buffer);
void ODK_Unpack_Generic_Decrypt_Response(Message* msg, OEMCryptoResult* result,
size_t* in_buffer_length,
uint8_t** out_buffer);
void ODK_Unpack_Generic_Sign_Request(Message* msg, OEMCrypto_SESSION* session,
SharedMemory** buffer,
size_t* buffer_length,
OEMCrypto_Algorithm* algorithm,
uint8_t** signature,
size_t** signature_length);
void ODK_Unpack_Generic_Sign_Response(Message* msg, OEMCryptoResult* result,
uint8_t** signature,
size_t** signature_length);
void ODK_Unpack_Generic_Verify_Request(Message* msg, OEMCrypto_SESSION* session,
SharedMemory** buffer,
size_t* buffer_length,
OEMCrypto_Algorithm* algorithm,
SharedMemory** signature,
size_t* signature_length);
void ODK_Unpack_Generic_Verify_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_UpdateUsageTable_Request(Message* msg);
void ODK_Unpack_UpdateUsageTable_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_WrapKeyboxOrOEMCert_Request(Message* msg, uint8_t** rot,
size_t* rotLength,
uint8_t** wrappedRot,
size_t** wrappedRotLength,
uint8_t** transportKey,
size_t* transportKeyLength);
void ODK_Unpack_WrapKeyboxOrOEMCert_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** wrappedRot,
size_t** wrappedRotLength);
void ODK_Unpack_InstallKeyboxOrOEMCert_Request(Message* msg, uint8_t** rot,
size_t* rotLength);
void ODK_Unpack_InstallKeyboxOrOEMCert_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_GetProvisioningMethod_Request(Message* msg);
void ODK_Unpack_GetProvisioningMethod_Response(
Message* msg, OEMCrypto_ProvisioningMethod* result);
void ODK_Unpack_IsKeyboxOrOEMCertValid_Request(Message* msg);
void ODK_Unpack_IsKeyboxOrOEMCertValid_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_GetDeviceID_Request(Message* msg, uint8_t** device_id,
size_t** device_id_length);
void ODK_Unpack_GetDeviceID_Response(Message* msg, OEMCryptoResult* result,
uint8_t** device_id,
size_t** device_id_length);
void ODK_Unpack_GetKeyData_Request(Message* msg, uint8_t** keyData,
size_t** keyDataLength);
void ODK_Unpack_GetKeyData_Response(Message* msg, OEMCryptoResult* result,
uint8_t** keyData, size_t** keyDataLength);
void ODK_Unpack_LoadTestKeybox_Request(Message* msg, uint8_t** buffer,
size_t* buffer_length);
void ODK_Unpack_LoadTestKeybox_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_GetOEMPublicCertificate_Request(Message* msg,
OEMCrypto_SESSION* session,
uint8_t** public_cert,
size_t** public_cert_length);
void ODK_Unpack_GetOEMPublicCertificate_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** public_cert,
size_t** public_cert_length);
void ODK_Unpack_GetRandom_Request(Message* msg, uint8_t** random_data,
size_t* random_data_length);
void ODK_Unpack_GetRandom_Response(Message* msg, OEMCryptoResult* result,
uint8_t** random_data,
size_t* random_data_length);
void ODK_Unpack_APIVersion_Request(Message* msg);
void ODK_Unpack_APIVersion_Response(Message* msg, uint32_t* result);
void ODK_Unpack_Security_Patch_Level_Request(Message* msg);
void ODK_Unpack_Security_Patch_Level_Response(Message* msg, uint8_t* result);
void ODK_Unpack_GetHDCPCapability_Request(Message* msg,
OEMCrypto_HDCP_Capability** current,
OEMCrypto_HDCP_Capability** maximum);
void ODK_Unpack_GetHDCPCapability_Response(Message* msg,
OEMCryptoResult* result,
OEMCrypto_HDCP_Capability** current,
OEMCrypto_HDCP_Capability** maximum);
void ODK_Unpack_SupportsUsageTable_Request(Message* msg);
void ODK_Unpack_SupportsUsageTable_Response(Message* msg, bool* result);
void ODK_Unpack_IsAntiRollbackHwPresent_Request(Message* msg);
void ODK_Unpack_IsAntiRollbackHwPresent_Response(Message* msg, bool* result);
void ODK_Unpack_GetNumberOfOpenSessions_Request(Message* msg, size_t** count);
void ODK_Unpack_GetNumberOfOpenSessions_Response(Message* msg,
OEMCryptoResult* result,
size_t** count);
void ODK_Unpack_GetMaxNumberOfSessions_Request(Message* msg, size_t** max);
void ODK_Unpack_GetMaxNumberOfSessions_Response(Message* msg,
OEMCryptoResult* result,
size_t** max);
void ODK_Unpack_SupportedCertificates_Request(Message* msg);
void ODK_Unpack_SupportedCertificates_Response(Message* msg, uint32_t* result);
void ODK_Unpack_IsSRMUpdateSupported_Request(Message* msg);
void ODK_Unpack_IsSRMUpdateSupported_Response(Message* msg, bool* result);
void ODK_Unpack_GetCurrentSRMVersion_Request(Message* msg, uint16_t** version);
void ODK_Unpack_GetCurrentSRMVersion_Response(Message* msg,
OEMCryptoResult* result,
uint16_t** version);
void ODK_Unpack_GetAnalogOutputFlags_Request(Message* msg);
void ODK_Unpack_GetAnalogOutputFlags_Response(Message* msg, uint32_t* result);
void ODK_Unpack_ResourceRatingTier_Request(Message* msg);
void ODK_Unpack_ResourceRatingTier_Response(Message* msg, uint32_t* result);
void ODK_Unpack_RewrapDeviceRSAKey30_Request(
Message* msg, OEMCrypto_SESSION* session, uint32_t** unaligned_nonce,
SharedMemory** encrypted_message_key, size_t* encrypted_message_key_length,
SharedMemory** enc_rsa_key, size_t* enc_rsa_key_length,
uint8_t** enc_rsa_key_iv, uint8_t** wrapped_rsa_key,
size_t** wrapped_rsa_key_length);
void ODK_Unpack_RewrapDeviceRSAKey30_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** wrapped_rsa_key,
size_t** wrapped_rsa_key_length);
void ODK_Unpack_RewrapDeviceRSAKey_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** wrapped_rsa_key,
size_t** wrapped_rsa_key_length);
void ODK_Unpack_LoadDeviceRSAKey_Request(Message* msg,
OEMCrypto_SESSION* session,
SharedMemory** wrapped_rsa_key,
size_t* wrapped_rsa_key_length);
void ODK_Unpack_LoadDeviceRSAKey_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_LoadTestRSAKey_Request(Message* msg);
void ODK_Unpack_LoadTestRSAKey_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_GenerateRSASignature_Request(
Message* msg, OEMCrypto_SESSION* session, SharedMemory** message,
size_t* message_length, uint8_t** signature, size_t** signature_length,
RSA_Padding_Scheme* padding_scheme);
void ODK_Unpack_GenerateRSASignature_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** signature,
size_t** signature_length);
void ODK_Unpack_CreateUsageTableHeader_Request(Message* msg,
uint8_t** header_buffer,
size_t** header_buffer_length);
void ODK_Unpack_CreateUsageTableHeader_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** header_buffer,
size_t** header_buffer_length);
void ODK_Unpack_LoadUsageTableHeader_Request(Message* msg, uint8_t** buffer,
size_t* buffer_length);
void ODK_Unpack_LoadUsageTableHeader_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_CreateNewUsageEntry_Request(Message* msg,
OEMCrypto_SESSION* session,
uint32_t** usage_entry_number);
void ODK_Unpack_CreateNewUsageEntry_Response(Message* msg,
OEMCryptoResult* result,
uint32_t** usage_entry_number);
void ODK_Unpack_LoadUsageEntry_Request(Message* msg, OEMCrypto_SESSION* session,
uint32_t* usage_entry_number,
uint8_t** buffer, size_t* buffer_length);
void ODK_Unpack_LoadUsageEntry_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_UpdateUsageEntry_Request(Message* msg,
OEMCrypto_SESSION* session,
SharedMemory** header_buffer,
size_t** header_buffer_length,
SharedMemory** entry_buffer,
size_t** entry_buffer_length);
void ODK_Unpack_UpdateUsageEntry_Response(Message* msg, OEMCryptoResult* result,
SharedMemory** header_buffer,
size_t** header_buffer_length,
SharedMemory** entry_buffer,
size_t** entry_buffer_length);
void ODK_Unpack_DeactivateUsageEntry_Request(Message* msg,
OEMCrypto_SESSION* session,
uint8_t** pst, size_t* pst_length);
void ODK_Unpack_DeactivateUsageEntry_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_ReportUsage_Request(Message* msg, OEMCrypto_SESSION* session,
uint8_t** pst, size_t* pst_length,
uint8_t** buffer, size_t** buffer_length);
void ODK_Unpack_ReportUsage_Response(Message* msg, OEMCryptoResult* result,
uint8_t** buffer, size_t** buffer_length);
void ODK_Unpack_DeleteUsageEntry_Request(
Message* msg, OEMCrypto_SESSION* session, uint8_t** pst, size_t* pst_length,
uint8_t** message, size_t* message_length, uint8_t** signature,
size_t* signature_length);
void ODK_Unpack_DeleteUsageEntry_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_ForceDeleteUsageEntry_Request(Message* msg, uint8_t** pst,
size_t* pst_length);
void ODK_Unpack_ForceDeleteUsageEntry_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_MoveEntry_Request(Message* msg, OEMCrypto_SESSION* session,
uint32_t* new_index);
void ODK_Unpack_MoveEntry_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_ShrinkUsageTableHeader_Request(Message* msg,
uint32_t* new_entry_count,
uint8_t** header_buffer,
size_t** header_buffer_length);
void ODK_Unpack_ShrinkUsageTableHeader_Response(Message* msg,
OEMCryptoResult* result,
uint8_t** header_buffer,
size_t** header_buffer_length);
void ODK_Unpack_CopyOldUsageEntry_Request(Message* msg,
OEMCrypto_SESSION* session,
uint8_t** pst, size_t* pst_length);
void ODK_Unpack_CopyOldUsageEntry_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_DeleteOldUsageTable_Request(Message* msg);
void ODK_Unpack_DeleteOldUsageTable_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_RemoveSRM_Request(Message* msg);
void ODK_Unpack_RemoveSRM_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_CreateOldUsageEntry_Request(
Message* msg, uint64_t* time_since_license_received,
uint64_t* time_since_first_decrypt, uint64_t* time_since_last_decrypt,
OEMCrypto_Usage_Entry_Status* status, uint8_t* server_mac_key,
uint8_t* client_mac_key, uint8_t** pst, size_t* pst_length);
void ODK_Unpack_CreateOldUsageEntry_Response(Message* msg,
OEMCryptoResult* result);
void ODK_Unpack_SupportsDecryptHash_Request(Message* msg);
void ODK_Unpack_SupportsDecryptHash_Response(Message* msg, uint32_t* result);
void ODK_Unpack_SetDecryptHash_Request(Message* msg, OEMCrypto_SESSION* session,
uint32_t* frame_number, uint8_t** hash,
size_t* hash_length);
void ODK_Unpack_SetDecryptHash_Response(Message* msg, OEMCryptoResult* result);
void ODK_Unpack_GetHashErrorCode_Request(Message* msg,
OEMCrypto_SESSION* session,
uint32_t** failed_frame_number);
void ODK_Unpack_GetHashErrorCode_Response(Message* msg, OEMCryptoResult* result,
uint32_t** failed_frame_number);
void ODK_UnpackNullable_c_str(Message* msg, char** value);
void ODK_UnpackAlloc_c_str(Message* msg, char** value);
void ODK_UnpackNullable_uint32_t(Message* msg, OEMCrypto_SESSION** value);
void ODK_UnpackAlloc_uint32_t(Message* msg, OEMCrypto_SESSION** value);
void ODK_UnpackNullable_size_t(Message* msg, size_t** value);
void ODK_UnpackNullable_OEMCrypto_DestBufferDesc(
Message* msg, OEMCrypto_DestBufferDesc** value);
void ODK_UnpackNullable_OEMCrypto_CENCEncryptPatternDesc(
Message* msg, OEMCrypto_CENCEncryptPatternDesc** value);
void ODK_UnpackAlloc_size_t(Message* msg, size_t** value);
void ODK_UnpackNullable_uint16_t(Message* msg, uint16_t** value);
void ODK_UnpackAlloc_uint16_t(Message* msg, uint16_t** value);
void ODK_UnpackNullable_uint8_t(Message* msg, uint8_t** value);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ODKITEE_DESERIALIZER_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,369 @@
/*
* 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
*/
#ifndef ODKITEE_SERIALIZER_H_
#define ODKITEE_SERIALIZER_H_
#include "deserializer.h"
#include "serialization_base.h"
#include "serializer.h"
#ifdef __cplusplus
extern "C" {
#endif
bool SuccessResult(OEMCryptoResult result);
void ODK_Pack_OEMCrypto_Substring(Message* msg, OEMCrypto_Substring const* obj);
void ODK_Pack_OEMCrypto_KeyObject(Message* msg, OEMCrypto_KeyObject const* obj);
void ODK_Pack_OEMCrypto_EntitledContentKeyObject(
Message* msg, OEMCrypto_EntitledContentKeyObject const* obj);
void ODK_Pack_OEMCrypto_KeyRefreshObject(Message* msg,
OEMCrypto_KeyRefreshObject const* obj);
void ODK_Pack_OEMCrypto_CENCEncryptPatternDesc(
Message* msg, OEMCrypto_CENCEncryptPatternDesc const* obj);
void ODK_Pack_SecurityLevel_Request(Message* msg);
void ODK_Pack_SecurityLevel_Response(Message* msg, const char* result);
void ODK_Pack_BuildInformation_Request(Message* msg);
void ODK_Pack_BuildInformation_Response(Message* msg, const char* result);
void ODK_Pack_SetSandbox_Request(Message* msg, const uint8_t* sandbox_id,
size_t sandbox_id_length);
void ODK_Pack_SetSandbox_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_Initialize_Request(Message* msg);
void ODK_Pack_Initialize_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_Terminate_Request(Message* msg);
void ODK_Pack_Terminate_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_OpenSession_Request(Message* msg,
const OEMCrypto_SESSION* session);
void ODK_Pack_OpenSession_Response(Message* msg, OEMCryptoResult result,
const OEMCrypto_SESSION* session);
void ODK_Pack_CloseSession_Request(Message* msg, OEMCrypto_SESSION session);
void ODK_Pack_CloseSession_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_GenerateDerivedKeys_Request(Message* msg,
OEMCrypto_SESSION session,
const SharedMemory* mac_key_context,
uint32_t mac_key_context_length,
const SharedMemory* enc_key_context,
uint32_t enc_key_context_length);
void ODK_Pack_GenerateDerivedKeys_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_DeriveKeysFromSessionKey_Request(
Message* msg, OEMCrypto_SESSION session, const uint8_t* enc_session_key,
size_t enc_session_key_length, const SharedMemory* mac_key_context,
size_t mac_key_context_length, const SharedMemory* enc_key_context,
size_t enc_key_context_length);
void ODK_Pack_DeriveKeysFromSessionKey_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_GenerateNonce_Request(Message* msg, OEMCrypto_SESSION session,
const uint32_t* nonce);
void ODK_Pack_GenerateNonce_Response(Message* msg, OEMCryptoResult result,
const uint32_t* nonce);
void ODK_Pack_GenerateSignature_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* message,
size_t message_length,
const uint8_t* signature,
const size_t* signature_length);
void ODK_Pack_GenerateSignature_Response(Message* msg, OEMCryptoResult result,
const uint8_t* signature,
const size_t* signature_length);
void ODK_Pack_LoadSRM_Request(Message* msg, const uint8_t* buffer,
size_t buffer_length);
void ODK_Pack_LoadSRM_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_LoadKeys_Request(
Message* msg, OEMCrypto_SESSION session, const SharedMemory* message,
size_t message_length, const SharedMemory* signature,
size_t signature_length, OEMCrypto_Substring enc_mac_keys_iv,
OEMCrypto_Substring enc_mac_keys, size_t key_array_length,
const OEMCrypto_KeyObject* key_array, OEMCrypto_Substring pst,
OEMCrypto_Substring srm_restriction_data,
OEMCrypto_LicenseType license_type);
void ODK_Pack_LoadKeys_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_LoadEntitledContentKeys_Request(
Message* msg, OEMCrypto_SESSION session, const SharedMemory* message,
size_t message_length, size_t key_array_length,
const OEMCrypto_EntitledContentKeyObject* key_array);
void ODK_Pack_LoadEntitledContentKeys_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_RefreshKeys_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* message,
size_t message_length,
const SharedMemory* signature,
size_t signature_length,
size_t key_array_length,
const OEMCrypto_KeyRefreshObject* key_array);
void ODK_Pack_RefreshKeys_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_QueryKeyControl_Request(Message* msg, OEMCrypto_SESSION session,
const uint8_t* content_key_id,
size_t content_key_id_length,
const uint8_t* key_control_block,
const size_t* key_control_block_length);
void ODK_Pack_QueryKeyControl_Response(Message* msg, OEMCryptoResult result,
const uint8_t* key_control_block,
const size_t* key_control_block_length);
void ODK_Pack_SelectKey_Request(Message* msg, OEMCrypto_SESSION session,
const uint8_t* content_key_id,
size_t content_key_id_length,
OEMCryptoCipherMode cipher_mode);
void ODK_Pack_SelectKey_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_DecryptCENC_Request(
Message* msg, OEMCrypto_SESSION session, const SharedMemory* data_addr,
size_t data_addr_length, bool is_encrypted, const uint8_t* iv,
size_t block_offset, const OEMCrypto_DestBufferDesc* out_buffer,
const OEMCrypto_CENCEncryptPatternDesc* pattern, uint8_t subsample_flags);
void ODK_Pack_DecryptCENC_Response(Message* msg, OEMCryptoResult result,
const OEMCrypto_DestBufferDesc* out_buffer);
void ODK_Pack_CopyBuffer_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* data_addr,
size_t data_addr_length,
const OEMCrypto_DestBufferDesc* out_buffer,
uint8_t subsample_flags);
void ODK_Pack_CopyBuffer_Response(Message* msg, OEMCryptoResult result,
const OEMCrypto_DestBufferDesc* out_buffer);
void ODK_Pack_Generic_Encrypt_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* in_buffer,
size_t in_buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
const uint8_t* out_buffer);
void ODK_Pack_Generic_Encrypt_Response(Message* msg, OEMCryptoResult result,
size_t in_buffer_length,
const uint8_t* out_buffer);
void ODK_Pack_Generic_Decrypt_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* in_buffer,
size_t in_buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
const uint8_t* out_buffer);
void ODK_Pack_Generic_Decrypt_Response(Message* msg, OEMCryptoResult result,
size_t in_buffer_length,
const uint8_t* out_buffer);
void ODK_Pack_Generic_Sign_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const uint8_t* signature,
const size_t* signature_length);
void ODK_Pack_Generic_Sign_Response(Message* msg, OEMCryptoResult result,
const uint8_t* signature,
const size_t* signature_length);
void ODK_Pack_Generic_Verify_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const SharedMemory* signature,
size_t signature_length);
void ODK_Pack_Generic_Verify_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_UpdateUsageTable_Request(Message* msg);
void ODK_Pack_UpdateUsageTable_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_WrapKeyboxOrOEMCert_Request(Message* msg, const uint8_t* rot,
size_t rotLength,
const uint8_t* wrappedRot,
const size_t* wrappedRotLength,
const uint8_t* transportKey,
size_t transportKeyLength);
void ODK_Pack_WrapKeyboxOrOEMCert_Response(Message* msg, OEMCryptoResult result,
const uint8_t* wrappedRot,
const size_t* wrappedRotLength);
void ODK_Pack_InstallKeyboxOrOEMCert_Request(Message* msg, const uint8_t* rot,
size_t rotLength);
void ODK_Pack_InstallKeyboxOrOEMCert_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_GetProvisioningMethod_Request(Message* msg);
void ODK_Pack_GetProvisioningMethod_Response(
Message* msg, OEMCrypto_ProvisioningMethod result);
void ODK_Pack_IsKeyboxOrOEMCertValid_Request(Message* msg);
void ODK_Pack_IsKeyboxOrOEMCertValid_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_GetDeviceID_Request(Message* msg, const uint8_t* device_id,
const size_t* device_id_length);
void ODK_Pack_GetDeviceID_Response(Message* msg, OEMCryptoResult result,
const uint8_t* device_id,
const size_t* device_id_length);
void ODK_Pack_GetKeyData_Request(Message* msg, const uint8_t* keyData,
const size_t* keyDataLength);
void ODK_Pack_GetKeyData_Response(Message* msg, OEMCryptoResult result,
const uint8_t* keyData,
const size_t* keyDataLength);
void ODK_Pack_LoadTestKeybox_Request(Message* msg, const uint8_t* buffer,
size_t buffer_length);
void ODK_Pack_LoadTestKeybox_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_GetOEMPublicCertificate_Request(Message* msg,
OEMCrypto_SESSION session,
const uint8_t* public_cert,
const size_t* public_cert_length);
void ODK_Pack_GetOEMPublicCertificate_Response(
Message* msg, OEMCryptoResult result, const uint8_t* public_cert,
const size_t* public_cert_length);
void ODK_Pack_GetRandom_Request(Message* msg, const uint8_t* random_data,
size_t random_data_length);
void ODK_Pack_GetRandom_Response(Message* msg, OEMCryptoResult result,
const uint8_t* random_data,
size_t random_data_length);
void ODK_Pack_APIVersion_Request(Message* msg);
void ODK_Pack_APIVersion_Response(Message* msg, uint32_t result);
void ODK_Pack_Security_Patch_Level_Request(Message* msg);
void ODK_Pack_Security_Patch_Level_Response(Message* msg, uint8_t result);
void ODK_Pack_GetHDCPCapability_Request(
Message* msg, const OEMCrypto_HDCP_Capability* current,
const OEMCrypto_HDCP_Capability* maximum);
void ODK_Pack_GetHDCPCapability_Response(
Message* msg, OEMCryptoResult result,
const OEMCrypto_HDCP_Capability* current,
const OEMCrypto_HDCP_Capability* maximum);
void ODK_Pack_SupportsUsageTable_Request(Message* msg);
void ODK_Pack_SupportsUsageTable_Response(Message* msg, bool result);
void ODK_Pack_IsAntiRollbackHwPresent_Request(Message* msg);
void ODK_Pack_IsAntiRollbackHwPresent_Response(Message* msg, bool result);
void ODK_Pack_GetNumberOfOpenSessions_Request(Message* msg,
const size_t* count);
void ODK_Pack_GetNumberOfOpenSessions_Response(Message* msg,
OEMCryptoResult result,
const size_t* count);
void ODK_Pack_GetMaxNumberOfSessions_Request(Message* msg, const size_t* max);
void ODK_Pack_GetMaxNumberOfSessions_Response(Message* msg,
OEMCryptoResult result,
const size_t* max);
void ODK_Pack_SupportedCertificates_Request(Message* msg);
void ODK_Pack_SupportedCertificates_Response(Message* msg, uint32_t result);
void ODK_Pack_IsSRMUpdateSupported_Request(Message* msg);
void ODK_Pack_IsSRMUpdateSupported_Response(Message* msg, bool result);
void ODK_Pack_GetCurrentSRMVersion_Request(Message* msg,
const uint16_t* version);
void ODK_Pack_GetCurrentSRMVersion_Response(Message* msg,
OEMCryptoResult result,
const uint16_t* version);
void ODK_Pack_GetAnalogOutputFlags_Request(Message* msg);
void ODK_Pack_GetAnalogOutputFlags_Response(Message* msg, uint32_t result);
void ODK_Pack_ResourceRatingTier_Request(Message* msg);
void ODK_Pack_ResourceRatingTier_Response(Message* msg, uint32_t result);
void ODK_Pack_RewrapDeviceRSAKey30_Request(
Message* msg, OEMCrypto_SESSION session, const uint32_t* unaligned_nonce,
const SharedMemory* encrypted_message_key,
size_t encrypted_message_key_length, const SharedMemory* enc_rsa_key,
size_t enc_rsa_key_length, const uint8_t* enc_rsa_key_iv,
const uint8_t* wrapped_rsa_key, const size_t* wrapped_rsa_key_length);
void ODK_Pack_RewrapDeviceRSAKey30_Response(
Message* msg, OEMCryptoResult result, const uint8_t* wrapped_rsa_key,
const size_t* wrapped_rsa_key_length);
void ODK_Pack_RewrapDeviceRSAKey_Response(Message* msg, OEMCryptoResult result,
const uint8_t* wrapped_rsa_key,
const size_t* wrapped_rsa_key_length);
void ODK_Pack_LoadDeviceRSAKey_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* wrapped_rsa_key,
size_t wrapped_rsa_key_length);
void ODK_Pack_LoadDeviceRSAKey_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_LoadTestRSAKey_Request(Message* msg);
void ODK_Pack_LoadTestRSAKey_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_GenerateRSASignature_Request(
Message* msg, OEMCrypto_SESSION session, const SharedMemory* message,
size_t message_length, const uint8_t* signature,
const size_t* signature_length, RSA_Padding_Scheme padding_scheme);
void ODK_Pack_GenerateRSASignature_Response(Message* msg,
OEMCryptoResult result,
const uint8_t* signature,
const size_t* signature_length);
void ODK_Pack_CreateUsageTableHeader_Request(
Message* msg, const uint8_t* header_buffer,
const size_t* header_buffer_length);
void ODK_Pack_CreateUsageTableHeader_Response(
Message* msg, OEMCryptoResult result, const uint8_t* header_buffer,
const size_t* header_buffer_length);
void ODK_Pack_LoadUsageTableHeader_Request(Message* msg, const uint8_t* buffer,
size_t buffer_length);
void ODK_Pack_LoadUsageTableHeader_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_CreateNewUsageEntry_Request(Message* msg,
OEMCrypto_SESSION session,
const uint32_t* usage_entry_number);
void ODK_Pack_CreateNewUsageEntry_Response(Message* msg, OEMCryptoResult result,
const uint32_t* usage_entry_number);
void ODK_Pack_LoadUsageEntry_Request(Message* msg, OEMCrypto_SESSION session,
uint32_t usage_entry_number,
const uint8_t* buffer,
size_t buffer_length);
void ODK_Pack_LoadUsageEntry_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_UpdateUsageEntry_Request(Message* msg, OEMCrypto_SESSION session,
const SharedMemory* header_buffer,
const size_t* header_buffer_length,
const SharedMemory* entry_buffer,
const size_t* entry_buffer_length);
void ODK_Pack_UpdateUsageEntry_Response(Message* msg, OEMCryptoResult result,
const SharedMemory* header_buffer,
const size_t* header_buffer_length,
const SharedMemory* entry_buffer,
const size_t* entry_buffer_length);
void ODK_Pack_DeactivateUsageEntry_Request(Message* msg,
OEMCrypto_SESSION session,
const uint8_t* pst,
size_t pst_length);
void ODK_Pack_DeactivateUsageEntry_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_ReportUsage_Request(Message* msg, OEMCrypto_SESSION session,
const uint8_t* pst, size_t pst_length,
const uint8_t* buffer,
const size_t* buffer_length);
void ODK_Pack_ReportUsage_Response(Message* msg, OEMCryptoResult result,
const uint8_t* buffer,
const size_t* buffer_length);
void ODK_Pack_DeleteUsageEntry_Request(Message* msg, OEMCrypto_SESSION session,
const uint8_t* pst, size_t pst_length,
const uint8_t* message,
size_t message_length,
const uint8_t* signature,
size_t signature_length);
void ODK_Pack_DeleteUsageEntry_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_ForceDeleteUsageEntry_Request(Message* msg, const uint8_t* pst,
size_t pst_length);
void ODK_Pack_ForceDeleteUsageEntry_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_MoveEntry_Request(Message* msg, OEMCrypto_SESSION session,
uint32_t new_index);
void ODK_Pack_MoveEntry_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_ShrinkUsageTableHeader_Request(
Message* msg, uint32_t new_entry_count, const uint8_t* header_buffer,
const size_t* header_buffer_length);
void ODK_Pack_ShrinkUsageTableHeader_Response(
Message* msg, OEMCryptoResult result, const uint8_t* header_buffer,
const size_t* header_buffer_length);
void ODK_Pack_CopyOldUsageEntry_Request(Message* msg, OEMCrypto_SESSION session,
const uint8_t* pst, size_t pst_length);
void ODK_Pack_CopyOldUsageEntry_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_DeleteOldUsageTable_Request(Message* msg);
void ODK_Pack_DeleteOldUsageTable_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_RemoveSRM_Request(Message* msg);
void ODK_Pack_RemoveSRM_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_CreateOldUsageEntry_Request(
Message* msg, uint64_t time_since_license_received,
uint64_t time_since_first_decrypt, uint64_t time_since_last_decrypt,
OEMCrypto_Usage_Entry_Status status, const uint8_t* server_mac_key,
const uint8_t* client_mac_key, const uint8_t* pst, size_t pst_length);
void ODK_Pack_CreateOldUsageEntry_Response(Message* msg,
OEMCryptoResult result);
void ODK_Pack_SupportsDecryptHash_Request(Message* msg);
void ODK_Pack_SupportsDecryptHash_Response(Message* msg, uint32_t result);
void ODK_Pack_SetDecryptHash_Request(Message* msg, OEMCrypto_SESSION session,
uint32_t frame_number, const uint8_t* hash,
size_t hash_length);
void ODK_Pack_SetDecryptHash_Response(Message* msg, OEMCryptoResult result);
void ODK_Pack_GetHashErrorCode_Request(Message* msg, OEMCrypto_SESSION session,
const uint32_t* failed_frame_number);
void ODK_Pack_GetHashErrorCode_Response(Message* msg, OEMCryptoResult result,
const uint32_t* failed_frame_number);
void ODK_PackNullable_c_str(Message* msg, const char* value);
void ODK_PackNullable_uint32_t(Message* msg, const OEMCrypto_SESSION* value);
void ODK_PackNullable_size_t(Message* msg, const size_t* value);
void ODK_PackNullable_OEMCrypto_DestBufferDesc(
Message* msg, const OEMCrypto_DestBufferDesc* value);
void ODK_PackNullable_OEMCrypto_CENCEncryptPatternDesc(
Message* msg, const OEMCrypto_CENCEncryptPatternDesc* value);
void ODK_PackNullable_uint16_t(Message* msg, const uint16_t* value);
void ODK_PackNullable_uint8_t(Message* msg, const uint8_t* value);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ODKITEE_SERIALIZER_H_ */

View File

@@ -0,0 +1,95 @@
/*
* 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 "bump_allocator.h"
#include "marshaller_base.h"
static void InitBytes(uint8_t* ptr, size_t count) {
if (ptr && count) {
memset(ptr, 0, count);
}
}
/*
* The functions here are declared weak so they can
* be overriden by test functions that inject
* various initialized values for testing
*/
__attribute__((weak)) void Init_bool(bool* value) {
if (value) {
*value = false;
}
}
__attribute__((weak)) void Init_size_t(size_t* value) {
if (value) {
*value = 0;
}
}
__attribute__((weak)) void Init_c_str(char** value) {
if (value) {
*value = NULL;
}
}
__attribute__((weak)) void Init_uint8_t(uint8_t* value) {
if (value) {
*value = 0;
}
}
__attribute__((weak)) void Init_uint16_t(uint16_t* value) {
if (value) {
*value = 0;
}
}
__attribute__((weak)) void Init_uint32_t(uint32_t* value) {
if (value) {
*value = 0;
}
}
__attribute__((weak)) void Init_uint64_t(uint64_t* value) {
if (value) {
*value = 0;
}
}
__attribute__((weak)) void InitMemory(uint8_t* address, size_t length)
{
if (address && length) {
InitBytes(address, length);
}
}
__attribute__((weak)) void InitPointer(uint8_t** ptr) {
if (ptr) {
*ptr = NULL;
}
}
/*
* Allocate memory for a variable from the bump allocator, used for
* DeclarePackVar, DeclareUnpackVar, for some pointer types
*/
__attribute__((weak)) uint8_t* VarAlloc(size_t size) {
return BumpAllocate(size);
}
/*
* Special cases due to union & shared memory
*/
__attribute__((weak)) void Init_OEMCrypto_DestBufferDesc(OEMCrypto_DestBufferDesc* d) {
if (d) {
d->type = OEMCrypto_BufferType_Clear;
d->buffer.clear.address = NULL;
d->buffer.clear.max_length = 0;
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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 ODKITEE_MARSHALLER_BASE_H_
#define ODKITEE_MARSHALLER_BASE_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "OEMCryptoCENC.h"
#include "serialization_base.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _Message Message;
/*
* When packing a pointer to size_t, and the pointer is null, pass
* this special value of size_t instead
*/
#define SZ_NULL (size_t)~0
void Init_bool(bool* value);
void Init_size_t(size_t* value);
void Init_c_str(char** value);
void Init_uint8_t(uint8_t* value);
void Init_uint16_t(uint16_t* value);
void Init_uint32_t(uint32_t* value);
void Init_uint64_t(uint64_t* value);
void InitMemory(uint8_t* addr, size_t length);
void InitPointer(uint8_t** addr);
/*
* Allocate memory for a variable from the bump allocator, used for
* DeclarePackVar, DeclareUnpackVar, for some pointer types
*/
uint8_t* VarAlloc(size_t size);
/*
* Special cases due to union & shared memory
*/
void Init_OEMCrypto_DestBufferDesc(OEMCrypto_DestBufferDesc* desc);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ODKITEE_MARSHALLER_BASE_H_

101
serialization/message.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* 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 "message.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/* Round up address to the nearest 8 byte boundary */
#define align_8(addr) (((uintptr_t)(addr) + 7) & ~(uintptr_t)7)
struct _Message {
uint8_t* base;
size_t capacity;
size_t size;
size_t read_offset;
MessageStatus status;
};
/*
* 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) {
assert(message != NULL);
assert(buffer != NULL);
message->base = buffer;
message->capacity = capacity;
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
}
/*
* Cast pointer of Message from the input buffer. Since Message* is 8-byte
* aligned on a 64-bit system, or 4-byte aligned on a 32-bit system, the input
* buffer needs to be adjusted to 8-byte alignment before pointer casting, in
* order to avoid misaligned pointer
*/
Message* CreateMessage(uint8_t* buffer, size_t buffer_size) {
assert(buffer != NULL);
uint8_t* const buffer_aligned = (uint8_t* const)align_8(buffer);
assert(buffer_size >= sizeof(Message) + (size_t)(buffer_aligned - buffer));
Message* const message = (Message* const)buffer_aligned;
message->base = buffer_aligned + sizeof(Message);
message->capacity =
buffer_size - sizeof(Message) - (size_t)(buffer_aligned - buffer);
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
return message;
}
void ClearMessage(Message* message) {
assert(message != NULL);
message->size = 0;
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
}
void ResetMessage(Message* message) {
assert(message != NULL);
message->read_offset = 0;
message->status = MESSAGE_STATUS_OK;
}
uint8_t* GetBase(Message* message) {
assert(message != NULL);
return message->base;
}
size_t GetCapacity(Message* message) {
assert(message != NULL);
return message->capacity;
}
size_t GetSize(Message* message) {
assert(message != NULL);
return message->size;
}
MessageStatus GetStatus(Message* message) {
assert(message != NULL);
return message->status;
}
void SetStatus(Message* message, MessageStatus status) {
assert(message != NULL);
message->status = status;
}
void SetSize(Message* message, size_t size) {
assert(message != NULL);
message->size = size;
}

103
serialization/message.h Normal file
View File

@@ -0,0 +1,103 @@
/*
* 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 ODKITEE_MESSAGE_H_
#define ODKITEE_MESSAGE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
typedef struct _Message Message;
/*
* TODO: there is a dangerous duplication of the MessageStatus
* enum with odk/src/serialization_base.h. The two need to
* be converged. Removing the random enum values here, since
* a proper fix is outside the scope of the current CL. Opened
* b/158603784.
*/
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,
MESSAGE_STATUS_INVALID_TAG_ERROR,
MESSAGE_STATUS_END_OF_MESSAGE_ERROR,
MESSAGE_STATUS_INVALID_ENUM_VALUE
} MessageStatus;
/*
* 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);
/*
* Erase the contents of the message, set it
* to an empty state.
*/
void ClearMessage(Message* message);
/*
* Reset read pointer to the beginning of the
* message and clear status
*/
void ResetMessage(Message* message);
/*
* The message base is the start of the payload
*/
uint8_t* GetBase(Message* message);
/*
* Get the maximum number of bytes the message
* can hold.
*/
size_t GetCapacity(Message* message);
/*
* Get the number of bytes currently in the
* message
*/
size_t GetSize(Message* message);
/*
* Return the status of the message
*/
MessageStatus GetStatus(Message* message);
/*
* Set the message status to a specific value
*/
void SetStatus(Message* message, MessageStatus status);
/*
* Set the size of the message to a value. This
* may be needed after writing data into the payload.
*/
void SetSize(Message*message, size_t size);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ODKITEE_MESSAGE_H_

View File

@@ -0,0 +1,642 @@
/*
* 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 <stdio.h>
#include <string.h>
#include "OEMCryptoCENC.h"
#include "bump_allocator.h"
#include "marshaller_base.h"
#include "shared_memory_allocator.h"
#include "shared_memory_interface.h"
struct _Message {
uint8_t* base;
size_t capacity;
size_t size;
size_t read_offset;
MessageStatus status;
};
typedef enum {
TAG_INVALID,
TAG_BOOL,
TAG_SIZE_T,
TAG_UINT8,
TAG_UINT16,
TAG_UINT32,
TAG_UINT64,
TAG_MEMORY,
TAG_SHARED_MEMORY,
TAG_EOM
} TagType;
static 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->read_offset > message->capacity ||
message->size > message->capacity ||
message->read_offset > message->size) {
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
return false;
}
return true;
}
static bool NullCheck(Message* message, const void* ptr) {
if (!ptr) {
message->status = MESSAGE_STATUS_NULL_POINTER_ERROR;
return true;
}
return false;
}
/* Callers are expected to have validated the message already */
static void PackBytes(Message* message, const uint8_t* ptr, size_t count) {
if (!NullCheck(message, ptr)) {
if (count <= message->capacity - message->size) {
memcpy(message->base + message->size, ptr, count);
message->size += count;
} else {
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
}
}
}
static void PackTag(Message* message, TagType tag) {
if (!ValidMessage(message)) return;
uint8_t byte = (uint8_t)tag;
PackBytes(message, &byte, sizeof(byte));
}
LengthType LengthFromUint32T(uint32_t length) {
LengthType length_type = {.tag = LENGTH_TYPE_UINT32_T,
.type.uint32_t_value = length};
return length_type;
}
LengthType LengthFromSizeT(size_t length) {
LengthType length_type = {.tag = LENGTH_TYPE_SIZE_T,
.type.size_t_value = length};
return length_type;
}
LengthType LengthFromUint32TPointer(const uint32_t* length) {
LengthType length_type = {.tag = LENGTH_TYPE_UINT32_T_POINTER,
.type.uint32_t_pointer = length};
return length_type;
}
LengthType LengthFromSizeTPointer(const size_t* length) {
LengthType length_type = {.tag = LENGTH_TYPE_SIZE_T_POINTER,
.type.size_t_pointer = length};
return length_type;
}
LengthType LengthFromUint32TDoublePointer(uint32_t** length) {
LengthType length_type = {.tag = LENGTH_TYPE_UINT32_T_DOUBLE_POINTER,
.type.uint32_t_double_pointer = length};
return length_type;
}
LengthType LengthFromSizeTDoublePointer(size_t** length) {
LengthType length_type = {.tag = LENGTH_TYPE_SIZE_T_DOUBLE_POINTER,
.type.size_t_double_pointer = length};
return length_type;
}
size_t LengthAsSizeT(LengthType length) {
size_t result = 0;
switch(length.tag) {
case LENGTH_TYPE_SIZE_T:
result = length.type.size_t_value;
break;
case LENGTH_TYPE_UINT32_T:
result = (size_t)length.type.uint32_t_value;
break;
case LENGTH_TYPE_SIZE_T_POINTER:
if (length.type.size_t_pointer) {
result = *length.type.size_t_pointer;
}
break;
case LENGTH_TYPE_UINT32_T_POINTER:
if (length.type.uint32_t_pointer) {
result = (size_t)*length.type.uint32_t_pointer;
}
break;
case LENGTH_TYPE_SIZE_T_DOUBLE_POINTER:
if (length.type.size_t_double_pointer && *length.type.size_t_double_pointer) {
result = **length.type.size_t_double_pointer;
}
break;
case LENGTH_TYPE_UINT32_T_DOUBLE_POINTER:
if (length.type.uint32_t_double_pointer && *length.type.uint32_t_double_pointer) {
result = (size_t)**length.type.uint32_t_double_pointer;
}
break;
}
return result;
}
bool LengthIsNull(LengthType length) {
switch(length.tag) {
case LENGTH_TYPE_SIZE_T:
case LENGTH_TYPE_UINT32_T:
return false;
case LENGTH_TYPE_SIZE_T_POINTER:
return length.type.size_t_pointer == NULL;
case LENGTH_TYPE_UINT32_T_POINTER:
return length.type.uint32_t_pointer == NULL;
case LENGTH_TYPE_SIZE_T_DOUBLE_POINTER:
return length.type.size_t_double_pointer == NULL ||
*length.type.size_t_double_pointer == NULL;
case LENGTH_TYPE_UINT32_T_DOUBLE_POINTER:
return length.type.uint32_t_double_pointer == NULL ||
*length.type.uint32_t_double_pointer == NULL;
}
assert(false);
return true;
}
void ODK_Pack_bool(Message* message, const bool* value) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_BOOL);
uint8_t b = (*value) ? 1 : 0;
PackBytes(message, &b, sizeof(b));
}
void ODK_Pack_size_t(Message* message, const size_t* value) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_SIZE_T);
uint64_t u64 = *value;
uint8_t buf[sizeof(uint64_t)];
buf[0] = (uint8_t)u64;
buf[1] = (uint8_t)(u64 >> 8);
buf[2] = (uint8_t)(u64 >> 16);
buf[3] = (uint8_t)(u64 >> 24);
buf[4] = (uint8_t)(u64 >> 32);
buf[5] = (uint8_t)(u64 >> 40);
buf[6] = (uint8_t)(u64 >> 48);
buf[7] = (uint8_t)(u64 >> 56);
PackBytes(message, buf, sizeof(buf));
}
void ODK_Pack_c_str(Message* message, const char* value) {
if (!ValidMessage(message) || NullCheck(message, value)) return;
size_t length = strlen(value) + 1;
ODK_PackMemory(message, (const uint8_t*)value, LengthFromSizeT(length));
}
void ODK_Pack_uint8_t(Message* message, const uint8_t* value) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_UINT8);
PackBytes(message, (const uint8_t*)value, sizeof(*value));
}
void ODK_Pack_uint16_t(Message* message, const uint16_t* value) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_UINT16);
uint8_t buf[sizeof(uint16_t)];
buf[0] = (uint8_t)(*value);
buf[1] = (uint8_t)(*value >> 8);
PackBytes(message, buf, sizeof(buf));
}
void ODK_Pack_uint32_t(Message* message, const uint32_t* value) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_UINT32);
uint8_t buf[sizeof(uint32_t)];
buf[0] = (uint8_t)(*value);
buf[1] = (uint8_t)(*value >> 8);
buf[2] = (uint8_t)(*value >> 16);
buf[3] = (uint8_t)(*value >> 24);
PackBytes(message, buf, sizeof(buf));
}
void ODK_Pack_uint64_t(Message* message, const uint64_t* value) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_UINT64);
uint8_t buf[sizeof(uint64_t)];
buf[0] = (uint8_t)(*value);
buf[1] = (uint8_t)(*value >> 8);
buf[2] = (uint8_t)(*value >> 16);
buf[3] = (uint8_t)(*value >> 24);
buf[4] = (uint8_t)(*value >> 32);
buf[5] = (uint8_t)(*value >> 40);
buf[6] = (uint8_t)(*value >> 48);
buf[7] = (uint8_t)(*value >> 56);
PackBytes(message, buf, sizeof(buf));
}
/*
* Convenience function used by the serializer to
* pack a bool without having to allocate a local
* variable.
*/
bool ODK_PackBoolValue(Message* message, bool value) {
ODK_Pack_bool(message, (const bool*)&value);
return value;
}
/*
* Pack a boolean indicating if the pointer value is NULL
*/
bool ODK_PackIsNull(Message* message, const void* pointer) {
return ODK_PackBoolValue(message, pointer == NULL);
}
/*
* Pack a boolean indicating if the address value is NULL. It's
* effectivey the same as PackIsNull but provided for symmetry with
* UnpackAlloc.
*/
void ODK_PackAlloc(Message* message, const void* addr) {
ODK_PackIsNull(message, addr);
}
/*
* Pack a range of memory given by address and length. First pack a
* bool indicating if the address is NULL. If the address is non-null
* and length is non-null then pack the length and |length| bytes from
* memory beginning at |address|.
*/
void ODK_PackMemory(Message* message, const uint8_t* address,
LengthType length) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_MEMORY);
ODK_PackBoolValue(message, address == NULL || LengthIsNull(length));
if (address && !LengthIsNull(length)) {
size_t count = LengthAsSizeT(length);
ODK_Pack_size_t(message, &count);
if (LengthAsSizeT(length) > 0) {
PackBytes(message, address, LengthAsSizeT(length));
}
}
}
/*
* Pack memory representing an array of fundamental types, given by
* address and length.
*/
void ODK_PackArray(Message* message, const uint8_t* address, size_t length) {
ODK_PackMemory(message, address, LengthFromSizeT(length));
}
/*
* Pack a variable length array of objects at the base address given
* by |address|, with |length| elements of size |size|. The ObjPacker is
* a pack function able to pack elements of the array.
*/
void ODK_PackObjArray(Message* message, const uint8_t* objs, LengthType length,
size_t size, ObjPacker packer) {
bool is_null = objs == NULL || LengthIsNull(length);
if (!ODK_PackBoolValue(message, is_null)) {
for (size_t i = 0; i < LengthAsSizeT(length); i++) {
(*packer)(message, objs + i * size);
}
}
}
/*
* On the REE side, if address and length are not null, map the shared
* memory segment specified by index into our address space using the
* shared memory bump allocator and pack fields into the message so
* that the receiver can map the corresponding segment if needed. Copy
* the input data into the shared segment.
*
* Parameters:
* message - The message to pack into
* index - the index that identifies which segment to map
* address - base address of the local memory buffer. If address is
* null, shared memory will not be allocated, which is indicated
* by a packed bool value so the receiver will also know not to
* allocate the segment.
* length - the length of the segment. A segment of this size will
* be mapped if length is non-null and *length is non-zero.
* otherwise the segment will not be mapped.
*/
void ODK_PackSharedInputBuffer(Message* message, uint16_t index,
const uint8_t* address, LengthType length) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_SHARED_MEMORY);
ODK_PackBoolValue(message, address == NULL || LengthIsNull(length));
if (address && !LengthIsNull(length)) {
uint8_t* shared_address = SharedMemory_Allocate(index, LengthAsSizeT(length));
if (shared_address) {
memcpy(shared_address, address, LengthAsSizeT(length));
}
}
}
/*
* Pass information to the receiver indicating whether shared memory
* needs to be allocated for the buffer indicated by |address| and |length|.
*
* Parameters:
* message - The message to pack into
* address - base address of the local memory buffer. If null, a shared
* memory segment will not need to be mapped by the receiver.
* length - the length of the segment. If null, or if the length is 0,
* a shared memory segment will not need to be mapped by the receiver.
*
* Returns:
* void
*/
void ODK_PackSharedOutputBuffer(Message* message, const uint8_t* address,
LengthType length) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_SHARED_MEMORY);
ODK_PackBoolValue(message, address == NULL || LengthIsNull(length));
}
void ODK_PackEOM(Message* message) {
if (!ValidMessage(message)) return;
PackTag(message, TAG_EOM);
}
/**************************** Unpack Functions *******************************/
static void UnpackBytes(Message* message, uint8_t* ptr, size_t count) {
if (!ValidMessage(message)) return;
if (count <= message->size - message->read_offset) {
if (ptr) {
memcpy(ptr, message->base + message->read_offset, count);
}
message->read_offset += count;
} else {
message->status = MESSAGE_STATUS_UNDERFLOW_ERROR;
}
}
static bool CheckTag(Message* message, TagType tag) {
uint8_t byte = TAG_INVALID;
UnpackBytes(message, &byte, sizeof(byte));
if (tag != (TagType)byte) {
message->status = MESSAGE_STATUS_INVALID_TAG_ERROR;
return false;
}
return true;
}
void ODK_Unpack_bool(Message* message, bool* value) {
if (!ValidMessage(message)) return;
if (!CheckTag(message, TAG_BOOL)) return;
uint8_t b = 0;
UnpackBytes(message, &b, sizeof(b));
*value = b ? true : false;
}
void ODK_Unpack_size_t(Message* message, size_t* value) {
if (!ValidMessage(message)) return;
if (!CheckTag(message, TAG_SIZE_T)) return;
uint8_t buf[sizeof(uint64_t)];
UnpackBytes(message, buf, sizeof(buf));
uint64_t u64 = *value;
u64 = buf[0];
u64 |= (uint64_t)buf[1] << 8;
u64 |= (uint64_t)buf[2] << 16;
u64 |= (uint64_t)buf[3] << 24;
u64 |= (uint64_t)buf[4] << 32;
u64 |= (uint64_t)buf[5] << 40;
u64 |= (uint64_t)buf[6] << 48;
u64 |= (uint64_t)buf[7] << 56;
*value = u64;
}
void ODK_Unpack_c_str(Message* message, char** value) {
if (!ValidMessage(message) || NullCheck(message, value)) return;
*value = NULL;
uint8_t* ptr = NULL;
ODK_UnpackPointerToMemory(message, &ptr);
if (ptr) {
/* calculate length, be careful to stay within length of message */
size_t length = 0;
uint8_t* p = ptr;
while (*p && p < message->base + message->size) {
length++;
p++;
}
void* buffer = BumpAllocate(length + 1);
if (buffer) {
memcpy(buffer, ptr, length);
*value = buffer;
}
}
}
void ODK_Unpack_uint8_t(Message* message, uint8_t* value) {
if (!ValidMessage(message)) return;
if (!CheckTag(message, TAG_UINT8)) return;
UnpackBytes(message, (uint8_t*)value, sizeof(*value));
}
void ODK_Unpack_uint16_t(Message* message, uint16_t* value) {
if (!ValidMessage(message)) return;
if (!CheckTag(message, TAG_UINT16)) return;
uint8_t buf[sizeof(uint16_t)];
UnpackBytes(message, buf, sizeof(buf));
*value = buf[0];
*value |= (uint16_t)buf[1] << 8;
}
void ODK_Unpack_uint32_t(Message* message, uint32_t* value) {
if (!ValidMessage(message)) return;
if (!CheckTag(message, TAG_UINT32)) return;
uint8_t buf[sizeof(uint32_t)];
UnpackBytes(message, buf, sizeof(buf));
*value = buf[0];
*value |= (uint32_t)buf[1] << 8;
*value |= (uint32_t)buf[2] << 16;
*value |= (uint32_t)buf[3] << 24;
}
void ODK_Unpack_uint64_t(Message* message, uint64_t* value) {
if (!ValidMessage(message)) return;
if (!CheckTag(message, TAG_UINT64)) return;
uint8_t buf[sizeof(uint64_t)];
UnpackBytes(message, buf, sizeof(buf));
*value = buf[0];
*value |= (uint64_t)buf[1] << 8;
*value |= (uint64_t)buf[2] << 16;
*value |= (uint64_t)buf[3] << 24;
*value |= (uint64_t)buf[4] << 32;
*value |= (uint64_t)buf[5] << 40;
*value |= (uint64_t)buf[6] << 48;
*value |= (uint64_t)buf[7] << 56;
}
bool ODK_UnpackBoolValue(Message* message) {
bool value = false;
ODK_Unpack_bool(message, &value);
return value;
}
/* Return true if the pointer was packed as NULL */
bool ODK_UnpackIsNull(Message* message) { return ODK_UnpackBoolValue(message); }
/*
* If the pointer was packed as NULL, return NULL. Otherwise
* return the number of bytes of memory from the bump allocator
* requested by |size|
*/
uint8_t* ODK_UnpackAlloc(Message* message, size_t size) {
return ODK_UnpackIsNull(message) ? NULL : BumpAllocate(size);
}
/*
* If the pointer was packed as NULL, return NULL. Otherwise
* return the number of bytes of memory from the bump allocator
* requested by |size|
*/
uint8_t* ODK_UnpackAllocBuffer(Message* message, LengthType length, size_t size) {
uint8_t* buffer = NULL;
if (!ODK_UnpackIsNull(message) && !LengthIsNull(length)) {
buffer = BumpAllocate(LengthAsSizeT(length) * size);
}
return buffer;
}
/*
* If the pointer was packed as NULL, return NULL. Otherwise unpack
* the array of objects into memory allocated from the bump allocator.
*/
void ODK_UnpackObjArray(Message* message, uint8_t** address, LengthType count,
size_t size, ObjUnpacker unpacker) {
if (address) {
*address = NULL;
}
if (!ODK_UnpackIsNull(message)) {
if (address && !LengthIsNull(count)) {
*address = BumpAllocate(LengthAsSizeT(count) * size);
if (*address) {
for (size_t i = 0; i < LengthAsSizeT(count); i++) {
(*unpacker)(message, (*address) + size * i);
}
}
}
}
}
/*
* Unpack a range of memory representing an array of fundamental types
* given a pointer to a buffer and a length. The caller is responsible
* for ensuring that the buffer is large enough to handle the number
* of bytes specified by |length|. First unpack a bool that indicates
* if the pointer to the memory is NULL and if not unpack the
* requested number of bytes into the address specified by |address|.
*/
void ODK_UnpackArray(Message* message, uint8_t* address, size_t length) {
if (!ValidMessage(message) || NullCheck(message, address)) return;
uint8_t* array = NULL;
ODK_UnpackPointerToMemory(message, &array);
if (array) {
memcpy(address, array, length);
}
}
/*
* Unpack a pointer to memory within the received message and return
* it. First unpack a bool that indicates if the address was passed in
* as NULL. If so set *address to NULL and return. Otherwise set
* *|address| to the current message read offset and unpack the length
* of the memory range. Then increment the message read offset by that
* amount.
*/
void ODK_UnpackPointerToMemory(Message* message, uint8_t** address) {
if (!ValidMessage(message) || NullCheck(message, address)) return;
if (!CheckTag(message, TAG_MEMORY)) return;
bool is_null = true;
ODK_Unpack_bool(message, &is_null);
if (is_null) {
*address = NULL;
return;
} else {
size_t length;
ODK_Unpack_size_t(message, &length);
size_t new_offset;
if (__builtin_add_overflow(message->read_offset, length, &new_offset) ||
new_offset > message->size) {
message->status = MESSAGE_STATUS_OVERFLOW_ERROR;
} else {
*address = message->base + message->read_offset;
message->read_offset = new_offset;
}
}
}
/*
* Unpack fields from |message| and use them to map a shared memory
* segment using the shared memory bump allocator. If the packed bool
* indicates that the output buffer is non-null, allocate a shared
* memory segment identified by |index| of the size indicated by
* |length|.
*
* Parameters:
* message - the message to unpack from
* index - the index that identifies which segment to map
* length - the length of the segment
* Returns:
* The address of the mapped segment
*/
uint8_t* ODK_UnpackSharedBuffer(Message* message, uint16_t index,
LengthType length) {
if (!ValidMessage(message)) return NULL;
if (!CheckTag(message, TAG_SHARED_MEMORY)) return NULL;
if (!ODK_UnpackIsNull(message)) {
return SharedMemory_Allocate(index, LengthAsSizeT(length));
}
return NULL;
}
/*
* In the REE, unpack fields from |message| and use them to map a
* shared memory segment using the shared memory bump allocator. If
* the packed bool indicates that the output buffer is non-null,
* allocate a shared memory segment identified by |index| of the size
* indicated by |length|. Copy the buffer from shared memory to
* the OEMCrypto API parameter.
*
* Parameters:
* message - the message to unpack from
* address - the OEMCrypto API parameter for the output buffer
* index - the index that identifies which segment to map
* length - the length of the segment
*/
void ODK_UnpackSharedOutputBuffer(Message* message, uint16_t index,
uint8_t** address, LengthType length) {
if (address && !LengthIsNull(length)) {
uint8_t* shared_address = ODK_UnpackSharedBuffer(message, index, length);
if (*address && LengthAsSizeT(length) > 0) {
memcpy(*address, shared_address, LengthAsSizeT(length));
}
}
}
/* end of message */
void ODK_UnpackEOM(Message* message) {
if (!ValidMessage(message)) return;
if (!CheckTag(message, TAG_EOM)) return;
if (message->read_offset != message->size) {
message->status = MESSAGE_STATUS_END_OF_MESSAGE_ERROR;
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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 ODKITEE_SERIALIZATION_BASE_H_
#define ODKITEE_SERIALIZATION_BASE_H_
#include <stddef.h>
#include <stdint.h>
#include "OEMCryptoCENC.h"
#include "message.h"
#include "shared_memory_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef char* c_str;
/*
* In the OEMCrypto API, the lengths of variable length buffers can be
* of various types: base types of size_t or uint32_t and [in] values
* or [in/out] pointers. The LengthType struct is used to pass
* lengths in a consistent way to the primitives that take lengths as
* arguments.
*/
typedef enum {
LENGTH_TYPE_SIZE_T,
LENGTH_TYPE_UINT32_T,
LENGTH_TYPE_SIZE_T_POINTER,
LENGTH_TYPE_UINT32_T_POINTER,
LENGTH_TYPE_SIZE_T_DOUBLE_POINTER,
LENGTH_TYPE_UINT32_T_DOUBLE_POINTER
} LengthTypeTag;
typedef struct {
LengthTypeTag tag;
union {
size_t size_t_value;
uint32_t uint32_t_value;
const size_t* size_t_pointer;
const uint32_t* uint32_t_pointer;
size_t** size_t_double_pointer;
uint32_t** uint32_t_double_pointer;
} type;
} LengthType;
LengthType LengthFromSizeT(size_t length);
LengthType LengthFromUint32T(uint32_t length);
LengthType LengthFromSizeTPointer(const size_t* length);
LengthType LengthFromUint32TPointer(const uint32_t* length);
LengthType LengthFromSizeTDoublePointer(size_t** length);
LengthType LengthFromUint32TDoublePointer(uint32_t** length);
size_t LengthAsSizeT(LengthType length_type);
bool LengthIsNull(LengthType length_type);
void ODK_Pack_bool(Message* message, const bool* value);
void ODK_Pack_size_t(Message* message, const size_t* value);
void ODK_Pack_c_str(Message* message, const char* value);
void ODK_Pack_uint8_t(Message* message, const uint8_t* value);
void ODK_Pack_uint16_t(Message* message, const uint16_t* value);
void ODK_Pack_uint32_t(Message* message, const uint32_t* value);
void ODK_Pack_uint64_t(Message* message, const uint64_t* value);
bool ODK_PackBoolValue(Message* message, bool value);
bool ODK_PackIsNull(Message* message, const void* value);
void ODK_PackAlloc(Message* message, const void* address);
void ODK_PackMemory(Message* message, const uint8_t* addr,
LengthType length);
void ODK_PackArray(Message* message, const uint8_t* addr, size_t length);
typedef void (*ObjPacker)(Message* message, const uint8_t* obj);
void ODK_PackObjArray(Message* message, const uint8_t* address,
LengthType length, size_t size, ObjPacker packer);
void ODK_PackEOM(Message* message); /* end of message */
void ODK_PackSharedInputBuffer(Message* message, uint16_t index,
const uint8_t* address, const LengthType);
void ODK_PackSharedOutputBuffer(Message* message, const uint8_t* address,
LengthType length);
void ODK_Unpack_bool(Message* message, bool* value);
void ODK_Unpack_size_t(Message* message, size_t* value);
void ODK_Unpack_c_str(Message* message, char** value);
void ODK_Unpack_uint8_t(Message* message, uint8_t* value);
void ODK_Unpack_uint16_t(Message* message, uint16_t* value);
void ODK_Unpack_uint32_t(Message* message, uint32_t* value);
void ODK_Unpack_uint64_t(Message* message, uint64_t* value);
bool ODK_UnpackBoolValue(Message* message);
bool ODK_UnpackIsNull(Message* message);
uint8_t* ODK_UnpackAlloc(Message* message, size_t size);
uint8_t* ODK_UnpackAllocBuffer(Message* message, LengthType length,
size_t size);
void ODK_UnpackArray(Message* message, uint8_t* addr, size_t length);
typedef void (*ObjUnpacker)(Message* message, uint8_t* obj);
void ODK_UnpackObjArray(Message* message, uint8_t** address,
LengthType length, size_t size,
ObjUnpacker unpacker);
void ODK_UnpackPointerToMemory(Message* message, uint8_t** addr);
uint8_t* ODK_UnpackSharedBuffer(Message* message, uint16_t index,
LengthType length);
void ODK_UnpackSharedInputBuffer(Message* message, uint16_t index,
uint8_t** address, LengthType length);
void ODK_UnpackSharedOutputBuffer(Message* message, uint16_t index,
uint8_t** address, LengthType length);
void ODK_UnpackEOM(Message* message);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ODKITEE_SERIALIZATION_BASE_H_

View File

@@ -0,0 +1,260 @@
/*
* Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
#include <string.h>
#include "shared_memory_allocator.h"
#include "shared_memory_interface.h"
#include "oemcrypto_overflow.h"
/*
* This file implements the allocator for shared memory. Shared memory
* is managed using two different schemes. There is a memory region,
* called the "pool" that is allocated once at initialization and kept
* open for the lifetime of OEMCrypto, and discrete allocations that
* are made on each OEMCrypto call where additional shared memory is
* required.
*
* Every shared memory allocation is identified by an index number,
* which is provided by the caller. Allowing the caller to specify the
* index allows the code generator to refer to specific regions
* explicitly, which is needed to correlate segments across
* serialization endpoints. The index numbers start from 0. Given an
* index number, the address and size of the allocation can be
* returned. The code generator requires that the allocation algorithm
* be deterministic and repeatable, i.e. that a specific sequence of
* allocations when replayed after a reset will result in the same
* shared memory regions being mapped to the same indexes.
*
* The memory pool is managed with a bump allocator. The pool is
* allocated from the porting layer's ODK_SharedMemory interface. The
* pool is divided into "segments" which are allocated consecutively
* from the pool by AllocateSegment. The allocator is reset before
* each api call, which removes all segments.
*
* Shared memory allocations that are too large to put in the pool are
* allocated directly from ODK_SharedMemory and are released at the
* end of each OEMCrypto call. A threshold is defined (e.g. pool
* size/4) that determines whether allocations are from the pool or
* from the discrete regions.
*/
/* Region ID for the shared memory pool */
#define SHARED_MEMORY_POOL_REGION_ID 0
/* The ID of the next discrete region to allocate */
static size_t next_discrete_region_id_ = SHARED_MEMORY_POOL_REGION_ID + 1;
/*
* Descriptor for a segment allocated from the pool.
*/
typedef struct {
uint32_t size;
uint32_t offset;
} Segment;
/*
* Descriptor for an allocation, which may be either from the pool
* or from a discrete region.
*/
typedef enum {FREE, POOL_SEGMENT, DISCRETE_REGION} AllocationType;
typedef struct {
AllocationType type;
union {
Segment segment;
ODK_SharedHandle* handle;
} u;
} Allocation;
/*
* Maximum number of allocations allowed. Indexes go from 0 to
* MAX_ALLOCATIONS - 1
*/
#define MAX_ALLOCATIONS 16
static Allocation allocations_[MAX_ALLOCATIONS];
/*
* Shared memory handle for the bump allocator pool
*/
static ODK_SharedHandle *pool_handle_;
/*
* The offset from pool_address of the next segment that will be
* allocated.
*/
static size_t next_segment_offset_ = 0;
/*
* Initial size of the memory pool
*/
static size_t pool_size_ = 0;
/*
* Initialize shared memory state variables. Set the initial pool size
* to the specified value.
*/
void SharedMemory_Initialize(size_t pool_size) {
ODK_SharedMemory_Initialize();
memset(&allocations_[0], 0, sizeof(allocations_));
pool_size_ = pool_size;
pool_handle_ = NULL;
next_discrete_region_id_ = SHARED_MEMORY_POOL_REGION_ID + 1;
}
/*
* Release all shared memory resources from the current process.
*/
void SharedMemory_Terminate(void) {
SharedMemory_Reset();
ODK_SharedMemory_Free(pool_handle_);
pool_handle_ = NULL;
ODK_SharedMemory_Terminate();
}
/*
* Allocate shared memory as a discrete region
*/
static uint8_t* AllocateAsRegion(uint16_t index, size_t size) {
ODK_SharedHandle* handle =
ODK_SharedMemory_Allocate(next_discrete_region_id_, size);
if (handle) {
Allocation* alloc = &allocations_[index];
alloc->type = DISCRETE_REGION;
alloc->u.handle = handle;
next_discrete_region_id_++;
}
return ODK_SharedMemory_GetAddress(handle);
}
/*
* Allocate a segment of shared memory from the pool
*/
static uint8_t* AllocateFromPool(uint16_t index, size_t size) {
if (!pool_handle_) {
pool_handle_ = ODK_SharedMemory_Allocate(SHARED_MEMORY_POOL_REGION_ID,
pool_size_);
if (!pool_handle_) {
return NULL;
}
next_segment_offset_ = 0;
}
size_t new_offset = 0;
if (AddOverflowUX(next_segment_offset_, size, &new_offset)) {
return NULL;
}
if (new_offset > ODK_SharedMemory_GetSize(pool_handle_)) {
return AllocateAsRegion(index, size);
}
uint8_t* segment_address =
ODK_SharedMemory_GetAddress(pool_handle_) + next_segment_offset_;
Allocation* alloc = &allocations_[index];
alloc->type = POOL_SEGMENT;
Segment* segment = &alloc->u.segment;
segment->size = size;
segment->offset = next_segment_offset_;
next_segment_offset_ = new_offset;
return segment_address;
}
/*
* Allocate shared memory from either the pool or a discrete region.
* If the requested memory size is larger than 1/4 of the pool size, or
* if the pool is full, allocate as a discrete region.
*
* Parameters:
* index - the index number of the allocation, assigned by the caller.
* indexes start at 0. The index cannot exceed MAX_ALLOCATIONS.
*
* Returns:
* The address of the allocation or NULL if the index has already
* been allocated or allocation fails.
*/
uint8_t* SharedMemory_Allocate(uint16_t index, size_t size) {
if (index >= MAX_ALLOCATIONS || allocations_[index].type != FREE) {
return NULL;
}
if (size <= pool_size_ / 4) {
return AllocateFromPool(index, size);
} else {
return AllocateAsRegion(index, size);
}
}
/*
* Get the size of a shared memory segment.
*
* Parameters:
* index - identifies the allocation. Valid values are
* 0..MAX_ALLOCATIONS-1
*
* Returns:
* The size of the allocation indicated by |index| or 0 if the
* index is invalid or no matching allocation was found
*/
size_t SharedMemory_GetSize(uint16_t index) {
if (index >= MAX_ALLOCATIONS) {
return 0;
}
Allocation* alloc = &allocations_[index];
switch (alloc->type) {
case DISCRETE_REGION:
return ODK_SharedMemory_GetSize(alloc->u.handle);
case POOL_SEGMENT:
return alloc->u.segment.size;
default:
break;
}
return 0;
}
/*
* Get the address of a shared memory segment.
*
* Parameters:
* index - identifies the allocation. Valid values are
* 0..MAX_ALLOCATIONS-1
*
* Returns:
* The address of the allocation indicated by |index| or NULL if the
* index is invalid or no matching allocation was found
*/
uint8_t* SharedMemory_GetAddress(uint16_t index) {
if (index >= MAX_ALLOCATIONS) {
return NULL;
}
Allocation* alloc = &allocations_[index];
switch (alloc->type) {
case DISCRETE_REGION:
return ODK_SharedMemory_GetAddress(alloc->u.handle);
case POOL_SEGMENT:
if (!pool_handle_) {
return NULL;
}
return ODK_SharedMemory_GetAddress(pool_handle_) +
alloc->u.segment.offset;
default:
break;
}
return NULL;
}
/*
* Set the allocator to its initial state, where there are no segments
* allocated from the pool and there are no discrete allocations.
*/
void SharedMemory_Reset(void) {
next_segment_offset_ = 0;
for (size_t i = 0; i < MAX_ALLOCATIONS; i++) {
Allocation* alloc = &allocations_[i];
if (alloc->type == DISCRETE_REGION) {
ODK_SharedMemory_Free(alloc->u.handle);
}
}
memset(&allocations_[0], 0, sizeof(allocations_));
next_discrete_region_id_ = SHARED_MEMORY_POOL_REGION_ID + 1;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
#ifndef ODKITEE_SHARED_MEMORY_ALLOCATOR_H_
#define ODKITEE_SHARED_MEMORY_ALLOCATOR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
/*
* An allocator for shared memory
*/
void SharedMemory_Initialize(size_t initial_pool_size);
uint8_t* SharedMemory_Allocate(uint16_t index, size_t size);
size_t SharedMemory_GetSize(uint16_t index);
uint8_t* SharedMemory_GetAddress(uint16_t index);
void SharedMemory_Reset(void);
void SharedMemory_Terminate(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //ODKITEE_SHARED_MEMORY_ALLOCATOR_H_

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
* source code may only be used and distributed under the Widevine Master
* License Agreement.
*/
#ifndef ODKITEE_SHARED_MEMORY_INTERFACE_H_
#define ODKITEE_SHARED_MEMORY_INTERFACE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*
* This is the interface to shared memory that must be implemented in
* a port for a specific trusted OS. The interface defines functions
* to allocate, access and free regions of shared memory.
*
* Shared memory regions are defined by an address and a size. Regions
* are allocated by specifying an integer |region_id| that is used to
* correlate remote and local mappings. When a region is created, the
* implementation returns an ODK_SharedHandle which is used by callers
* when accessing the region.
*
* Each shared memory implementation defines its own _ODK_SharedHandle
* struct to hold the data needed to represent a shared memory region.
*/
typedef struct _ODK_SharedHandle ODK_SharedHandle;
/*
* Shared memory regions are identified with an id that correlates the
* remote and local mappings.
*/
typedef uint16_t ODK_SharedRegionId;
/*
* Note that the shared memory implementation must be initialized
* prior to calling any OEMCrypto API functions because it needs to be
* available when communicating with the TEE. Typically it would be
* initialized on service startup.
*/
/*
* Initialize the shared memory implementation, must be called prior
* to using any other ODK_SharedMemory functions. This function will
* be called by the dispatcher on the TEE side at startup. On the REE
* side it must be called by the service that is calling OEMCrypto
* because the communication with the TEE needs to be established
* before any OEMCrypto calls are made.
*/
void ODK_SharedMemory_Initialize(void);
/*
* Terminate the shared memory implementation, releasing any resources
* in use.
*/
void ODK_SharedMemory_Terminate(void);
/*
* Allocate a region of shared memory of |size| bytes. Regions are
* allocated based on a specified id that is used to correlate remote
* and local mappings. The shared memory region must remain mapped
* until released by ODK_SharedMemory_Free.
*
* Parameters:
* region_id - identifies the region to allocate
* size - the size of the memory region to allocate
*
* Returns:
* A pointer to an ODK_SharedHandle which refers to the allocated
* shared memory, or NULL if allocation fails. The memory for the
* handle is owned by the implementation. The handle must remain
* valid for as long as the shared memory region is allocated.
*/
ODK_SharedHandle* ODK_SharedMemory_Allocate(ODK_SharedRegionId region_id,
size_t size);
/*
* Return the address that a shared memory handle is mapped to.
*
* Parameters:
* handle - the shared handle for which an address is requested
*
* Returns:
* The address of the shared memory region refered by |handle|
*/
uint8_t* ODK_SharedMemory_GetAddress(ODK_SharedHandle* handle);
/*
* Return the size of a shared memory region
*
* Parameters:
* handle - the shared handle for which the region size is requested
*
* Returns:
* The size of the shared memory region refered by |handle|
*/
size_t ODK_SharedMemory_GetSize(ODK_SharedHandle* handle);
/*
* Release a handle for a previously allocated region of shared memory.
* The memory is unmapped and any associated resources are released.
*
* Parameters:
* address - the address of the shared memory region to release
*/
void ODK_SharedMemory_Free(ODK_SharedHandle* handle);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //ODKITEE_SHARED_MEMORY_INTERFACE_H_

View File

@@ -0,0 +1,131 @@
/*
* 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 "special_cases.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "api_support.h"
#include "deserializer.h"
#include "OEMCryptoCENC.h"
#include "serialization_base.h"
#include "shared_memory_allocator.h"
#include "shared_memory_interface.h"
#include "serializer.h"
/*
* Special case API functions. DecryptCENC and CopyBuffer have the
* |out_buffer| parameter of type OEMCrypt_DestBufferDesc. If the
* destination is to non-secure memory, the output data needs to be
* copied out from shared memory to the provided destination buffer.
* The length of the data is given by the seemingly unrelated input
* parameter data_addr_length so it's difficult to auto-generate these
* functions.
*
* To update these functions when the api generator changes, remove them
* from special_case_config.cpp, build, then copy the generated code
* from oemcrypto_api.c and apply the manual edits.
*/
OEMCRYPTO_API OEMCryptoResult OEMCrypto_DecryptCENC(
OEMCrypto_SESSION session, const SharedMemory *data_addr,
size_t data_addr_length, bool is_encrypted, const uint8_t *iv,
size_t block_offset, OEMCrypto_DestBufferDesc *out_buffer,
const OEMCrypto_CENCEncryptPatternDesc *pattern, uint8_t subsample_flags) {
OEMCryptoResult result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
pthread_mutex_lock(&api_lock);
Message *request = API_InitializeRequest();
Message *response = NULL;
if (!request) {
goto cleanup_and_return;
}
ODK_Pack_DecryptCENC_Request(request, session, data_addr, data_addr_length, is_encrypted,
iv, block_offset, out_buffer, pattern, subsample_flags);
if (GetStatus(request) != MESSAGE_STATUS_OK) {
api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
goto cleanup_and_return;
}
response = API_Transact(request);
if (!response) {
goto cleanup_and_return;
}
ODK_Unpack_DecryptCENC_Response(response, &result, &out_buffer);
/* Only this block is hand coded */
if (result == OEMCrypto_SUCCESS) {
if (out_buffer->type == OEMCrypto_BufferType_Clear) {
uint8_t* shared_address = SharedMemory_GetAddress(DEST_BUFFER_INDEX);
if (data_addr_length <= SharedMemory_GetSize(DEST_BUFFER_INDEX)) {
memcpy(out_buffer->buffer.clear.address, shared_address, data_addr_length);
} else {
result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
goto cleanup_and_return;
}
}
}
if (GetStatus(response) != MESSAGE_STATUS_OK) {
api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
goto cleanup_and_return;
}
cleanup_and_return:
if (request) {
ODK_Transport_DeallocateMessage(request);
}
if (response) {
ODK_Transport_DeallocateMessage(response);
}
pthread_mutex_unlock(&api_lock);
return API_CheckResult(result);
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_CopyBuffer(
OEMCrypto_SESSION session, const SharedMemory *data_addr,
size_t data_addr_length, OEMCrypto_DestBufferDesc *out_buffer,
uint8_t subsample_flags) {
OEMCryptoResult result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
pthread_mutex_lock(&api_lock);
Message *request = API_InitializeRequest();
Message *response = NULL;
if (!request) {
goto cleanup_and_return;
}
ODK_Pack_CopyBuffer_Request(request, session, data_addr, data_addr_length,
out_buffer, subsample_flags);
if (GetStatus(request) != MESSAGE_STATUS_OK) {
api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
goto cleanup_and_return;
}
response = API_Transact(request);
if (!response) {
goto cleanup_and_return;
}
ODK_Unpack_CopyBuffer_Response(response, &result, &out_buffer);
if (GetStatus(response) != MESSAGE_STATUS_OK) {
api_result = OEMCrypto_ERROR_UNKNOWN_FAILURE;
goto cleanup_and_return;
}
/* Only this block is hand coded */
if (result == OEMCrypto_SUCCESS) {
if (out_buffer->type == OEMCrypto_BufferType_Clear) {
uint8_t* shared_address = SharedMemory_GetAddress(DEST_BUFFER_INDEX);
memcpy(out_buffer->buffer.clear.address, shared_address, data_addr_length);
}
}
cleanup_and_return:
if (request) {
ODK_Transport_DeallocateMessage(request);
}
if (response) {
ODK_Transport_DeallocateMessage(response);
}
pthread_mutex_unlock(&api_lock);
return API_CheckResult(result);
}

View File

@@ -0,0 +1,202 @@
/*
* 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 "special_cases.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "deserializer.h"
#include "OEMCryptoCENC.h"
#include "serialization_base.h"
#include "shared_memory_allocator.h"
#include "shared_memory_interface.h"
#include "serializer.h"
/*
* Special cases due to union & shared memory
*/
/*
* Pack the destination buffer parameter to OEMCrypto_DecryptCENC and
* OEMCrypto_CopyBuffer
*/
void ODK_Pack_OEMCrypto_DestBufferDesc(Message* message,
const OEMCrypto_DestBufferDesc* obj) {
if (obj == NULL) {
SetStatus(message, MESSAGE_STATUS_NULL_POINTER_ERROR);
return;
}
ODK_Pack_uint32_t(message, (uint32_t*)&obj->type);
switch (obj->type) {
case OEMCrypto_BufferType_Clear: {
ODK_Pack_size_t(message, &obj->buffer.clear.max_length);
ODK_PackSharedOutputBuffer(message, obj->buffer.clear.address,
LengthFromSizeT(obj->buffer.clear.max_length));
break;
}
case OEMCrypto_BufferType_Secure:
/* secure memory - pass handle, length, offset */
ODK_Pack_uint64_t(message, (uint64_t*)&obj->buffer.secure.handle);
ODK_Pack_size_t(message, &obj->buffer.secure.max_length);
ODK_Pack_size_t(message, &obj->buffer.secure.offset);
break;
case OEMCrypto_BufferType_Direct:
ODK_Pack_bool(message, &obj->buffer.direct.is_video);
break;
}
}
/*
* Unpack the destination buffer parameter to OEMCrypto_DecryptCENC and
* OEMCrypto_CopyBuffer
*/
void ODK_Unpack_OEMCrypto_DestBufferDesc(Message* message,
OEMCrypto_DestBufferDesc* obj) {
if (obj == NULL) {
SetStatus(message, MESSAGE_STATUS_NULL_POINTER_ERROR);
return;
}
ODK_Unpack_uint32_t(message, (uint32_t*)&obj->type);
switch (obj->type) {
case OEMCrypto_BufferType_Clear: {
ODK_Unpack_size_t(message, &obj->buffer.clear.max_length);
uint8_t* shared_address =
ODK_UnpackSharedBuffer(message, DEST_BUFFER_INDEX,
LengthFromSizeT(obj->buffer.clear.max_length));
if (!obj->buffer.clear.address) {
// unpacking request in TEE - set the address to shared memory
obj->buffer.clear.address = shared_address;
}
break;
}
case OEMCrypto_BufferType_Secure:
/* secure memory handle - deal with later */
ODK_Unpack_uint64_t(message, (uint64_t*)&obj->buffer.secure.handle);
ODK_Unpack_size_t(message, &obj->buffer.secure.max_length);
ODK_Unpack_size_t(message, &obj->buffer.secure.offset);
break;
case OEMCrypto_BufferType_Direct:
ODK_Unpack_bool(message, &obj->buffer.direct.is_video);
break;
}
}
/*
* Special serialization cases due to some parameters being defined as
* pointers into other parameters.
*/
void ODK_Pack_RewrapDeviceRSAKey_Request(
Message* msg, OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,
const uint8_t* signature,
size_t signature_length,
const uint32_t* unaligned_nonce,
const uint8_t* enc_rsa_key,
size_t enc_rsa_key_length,
const uint8_t* enc_rsa_key_iv,
const uint8_t* wrapped_rsa_key,
const size_t* wrapped_rsa_key_length) {
uint32_t api_value = 18; /* from _oecc18 */
ODK_Pack_uint32_t(msg, &api_value);
ODK_Pack_size_t(msg, &message_length);
ODK_Pack_size_t(msg, &signature_length);
ODK_Pack_size_t(msg, &enc_rsa_key_length);
ODK_PackNullable_size_t(msg, wrapped_rsa_key_length);
ODK_Pack_uint32_t(msg, &session);
ODK_PackSharedInputBuffer(msg, 0, message, LengthFromSizeT(message_length));
ODK_PackSharedInputBuffer(msg, 1, signature, LengthFromSizeT(signature_length));
size_t unaligned_nonce_offset = 0;
if (__builtin_sub_overflow((uintptr_t)unaligned_nonce, (uintptr_t)message,
&unaligned_nonce_offset)) {
SetStatus(msg, MESSAGE_STATUS_PARSE_ERROR);
return;
}
ODK_Pack_size_t(msg, &unaligned_nonce_offset);
size_t enc_rsa_key_offset = 0;
if (__builtin_sub_overflow((uintptr_t)enc_rsa_key, (uintptr_t)message,
&enc_rsa_key_offset)) {
SetStatus(msg, MESSAGE_STATUS_PARSE_ERROR);
return;
}
ODK_Pack_size_t(msg, &enc_rsa_key_offset);
size_t enc_rsa_key_iv_offset = 0;
if (__builtin_sub_overflow((uintptr_t)enc_rsa_key_iv, (uintptr_t)message,
&enc_rsa_key_iv_offset)) {
SetStatus(msg, MESSAGE_STATUS_PARSE_ERROR);
return;
}
ODK_Pack_size_t(msg, &enc_rsa_key_iv_offset);
ODK_PackAlloc(msg, wrapped_rsa_key);
ODK_PackEOM(msg);
}
void ODK_Unpack_RewrapDeviceRSAKey_Request(
Message* msg, OEMCrypto_SESSION* session,
SharedMemory** message,
size_t* message_length,
SharedMemory** signature,
size_t* signature_length,
uint32_t** unaligned_nonce,
uint8_t** enc_rsa_key,
size_t* enc_rsa_key_length,
uint8_t** enc_rsa_key_iv,
uint8_t** wrapped_rsa_key,
size_t** wrapped_rsa_key_length) {
uint32_t api_value = ~(uint32_t)0;
ODK_Unpack_uint32_t(msg, &api_value);
if (api_value != 18) SetStatus(msg, MESSAGE_STATUS_API_VALUE_ERROR);
ODK_Unpack_size_t(msg, message_length);
ODK_Unpack_size_t(msg, signature_length);
ODK_Unpack_size_t(msg, enc_rsa_key_length);
ODK_UnpackNullable_size_t(msg, wrapped_rsa_key_length);
ODK_Unpack_uint32_t(msg, session);
ODK_UnpackSharedBuffer(msg, 0, LengthFromSizeTPointer(message_length));
ODK_UnpackSharedBuffer(msg, 1, LengthFromSizeTPointer(signature_length));
*message = SharedMemory_GetAddress(0);
*signature = SharedMemory_GetAddress(1);
size_t unaligned_nonce_offset = 0;
uintptr_t unaligned_nonce_ptr = 0;
ODK_Unpack_size_t(msg, &unaligned_nonce_offset);
if (__builtin_add_overflow((uintptr_t)*message, unaligned_nonce_offset,
&unaligned_nonce_ptr)) {
SetStatus(msg, MESSAGE_STATUS_PARSE_ERROR);
return;
}
*unaligned_nonce = (uint32_t*)unaligned_nonce_ptr;
size_t enc_rsa_key_offset = 0;
uintptr_t enc_rsa_key_ptr = 0;
ODK_Unpack_size_t(msg, &enc_rsa_key_offset);
if (__builtin_add_overflow((uintptr_t)*message, enc_rsa_key_offset,
&enc_rsa_key_ptr)) {
SetStatus(msg, MESSAGE_STATUS_PARSE_ERROR);
return;
}
*enc_rsa_key = (uint8_t*)enc_rsa_key_ptr;
size_t enc_rsa_key_iv_offset = 0;
uintptr_t enc_rsa_key_iv_ptr = 0;
ODK_Unpack_size_t(msg, &enc_rsa_key_iv_offset);
if (__builtin_add_overflow((uintptr_t)*message, enc_rsa_key_iv_offset,
&enc_rsa_key_iv_ptr)) {
SetStatus(msg, MESSAGE_STATUS_PARSE_ERROR);
return;
}
*enc_rsa_key_iv = (uint8_t*)enc_rsa_key_iv_ptr;
*wrapped_rsa_key = (uint8_t*)ODK_UnpackAllocBuffer(
msg, LengthFromSizeTDoublePointer(wrapped_rsa_key_length),
sizeof(uint8_t));
ODK_UnpackEOM(msg);
}

View File

@@ -0,0 +1,64 @@
/*
* 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 ODKITEE_SPECIAL_CASES_H_
#define ODKITEE_SPECIAL_CASES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include "OEMCryptoCENC.h"
#include "message.h"
/* shared memory index used for destination buffers */
#define DEST_BUFFER_INDEX 3
/*
* Special cases due to union & shared memory
*/
void ODK_Pack_OEMCrypto_DestBufferDesc(Message* msg,
const OEMCrypto_DestBufferDesc* obj);
void ODK_Unpack_OEMCrypto_DestBufferDesc(Message* msg,
OEMCrypto_DestBufferDesc* obj);
/*
* Special cases due to parameters defined as having pointers into other parameters
*/
void ODK_Pack_RewrapDeviceRSAKey_Request(
Message* msg, OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,
const uint8_t* signature,
size_t signature_length,
const uint32_t* unaligned_nonce,
const uint8_t* enc_rsa_key,
size_t enc_rsa_key_length,
const uint8_t* enc_rsa_key_iv,
const uint8_t* wrapped_rsa_key,
const size_t* wrapped_rsa_key_length);
void ODK_Unpack_RewrapDeviceRSAKey_Request(
Message* msg, OEMCrypto_SESSION* session,
SharedMemory** message,
size_t* message_length,
SharedMemory** signature,
size_t* signature_length,
uint32_t** unaligned_nonce,
uint8_t** enc_rsa_key,
size_t* enc_rsa_key_length,
uint8_t** enc_rsa_key_iv,
uint8_t** wrapped_rsa_key,
size_t** wrapped_rsa_key_length);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ODKITEE_SPECIAL_CASES_H_

View File

@@ -0,0 +1,116 @@
/*
* 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 ODKITEE_TRANSPORT_INTERFACE_H_
#define ODKITEE_TRANSPORT_INTERFACE_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* The Transport Interface is used by the oemcrypto library running
* on the REE side/HLOS. It connects liboemcrypto to the trusted
* OS's method of transporting data between the REE and the TEE.
*
* The trusted OS must provide primitives to transport data segments
* between the REE and TEE. The maximum size of the data segments may
* be fixed and predetermined by the trusted OS. However, the
* transport implementation must be able to append data segments
* sequentially to transport arbitrarily sized messages. For example
* if the maximum block size is 2 KiB and a message is serialized that
* requires 6 KiB, the transport layer must be able to extend the
* messsage to three logically consecutive 2 KiB segments during
* serialization to contain the message. Messages may be initially
* allocated at any block size. The serialization layer will call back
* into the transport layer to request that additional blocks be added
* to the message as needed. The serialization layer will attempt to
* minimize the actual size of messages by passing larger parameters
* in shared memory, if supported by the trusted OS.
*
* Functions need to be provided to allocate, extend and deallocate
* messages, and send and receive messages between the REE and the
* TEE.
*/
typedef enum {
/*
* ODK_TRANSPORT_STATUS_OK must be returned from transport functions
* if the requested operation completed succesfully.
*/
ODK_TRANSPORT_STATUS_OK,
/*
* ODK_TRANSPORT_STATUS_ALLOC_FAILED must be returned from
* ODK_Transport_ExtendMessage if there is insufficient memory. This
* is a fatal failure that will cause OEMCrypto to return
* OEMCrypto_ERROR_INSUFFICIENT_RESOURCES.
*/
ODK_TRANSPORT_STATUS_ALLOC_FAILED,
/*
* ODK_TRANSPORT_STATUS_IO_ERROR must be returned from
* ODK_Transport_SendMessage or ODK_Transport_ReceiveMessage if the
* transport interface was unable to deliver or receive a message
* for any reason. The transport implementation should be designed
* to be robust against communication failures, e.g. by providing
* logic to retry delivery or other techniques if possible. The
* odkitee library does not make any attempts to improve
* communcation reliability using these techniques.
*
* This return code indicates a fatal failure of the current command
* which will result in OEMCrypto returning
* OEMCrypto_ERROR_SYSTEM_INVALIDATED. This will cause the app to be
* notified that the drm system must be reinitialized.
*/
ODK_TRANSPORT_STATUS_IO_ERROR,
} ODK_Transport_Status;
/*
* Allocate a new message of a size that is determined by the
* transport implementation, which is most likely the maximum data
* segment transport size of the trusted OS. The message will be
* subsequently extended if it is too small for the message currently
* being serialized. Must return NULL if the transport implementation
* is unable to allocate a message of any size. Only two messages will
* be simultaneously allocated at any time.
*/
Message* ODK_Transport_AllocateMessage(void);
/*
* Extend an existing message to a new size. The new size is the total
* required size of the message including the currently allocation
* portion. Return ODK_TRANSPORT_STATUS_ALLOC_FAILED if the transport
* interface is unable to extend the message to the new size.
*/
ODK_Transport_Status ODK_Transport_ExtendMessage(Message* message, size_t new_size);
/*
* Request that a message be delivered from the REE to the TEE. If the
* delivery is successful ODK_TRANSPORT_STATUS_OK must be returned.
* Otherwise return ODK_TRANSPORT_STATUS_IO_ERROR.
*/
ODK_Transport_Status ODK_Transport_SendMessage(Message* message);
/*
* Request that a message be received by the REE from the TEE. If
* the receipt is successful ODK_TRANSPORT_STATUS_OK must be returned.
* Otherwise return ODK_TRANSPORT_STATUS_IO_ERROR.
*/
ODK_Transport_Status ODK_Transport_ReceiveMessage(Message** message);
/*
* Return a message that is not longer in use to the transport
* interface.
*/
void ODK_Transport_DeallocateMessage(Message* message);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ODKITEE_TRANSPORT_INTERFACE_H_ */