Files
odkitee/serialization/special_case_apis.c
2020-07-24 12:03:58 -07:00

132 lines
4.4 KiB
C

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