132 lines
4.4 KiB
C
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);
|
|
}
|