/* * 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; }