// 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 "OEMCryptoCENC.h" #include "log.h" #include "oemcrypto_fuzz_helper.h" #include "oemcrypto_fuzz_structs.h" namespace wvoec { // Free dynamic memory allocated by fuzzer script. void FreeOutputBuffers(OEMCrypto_SESSION session_id, OEMCrypto_DestBufferDesc& output_descriptor, int* secure_fd) { switch (output_descriptor.type) { case OEMCrypto_BufferType_Clear: { delete[] output_descriptor.buffer.clear.address; break; } case OEMCrypto_BufferType_Secure: { OEMCrypto_FreeSecureBuffer(session_id, &output_descriptor, *secure_fd); break; } case OEMCrypto_BufferType_Direct: { break; } } } bool InitializeOutputBuffers(OEMCrypto_SESSION session_id, OEMCrypto_DestBufferDesc& output_descriptor, int* secure_fd, size_t input_buffer_size) { switch (output_descriptor.type) { case OEMCrypto_BufferType_Clear: { output_descriptor.buffer.clear.address = new OEMCrypto_SharedMemory[input_buffer_size]; return true; } case OEMCrypto_BufferType_Secure: { OEMCryptoResult sts = OEMCrypto_AllocateSecureBuffer( session_id, input_buffer_size, &output_descriptor, secure_fd); return sts == OEMCrypto_SUCCESS; } case OEMCrypto_BufferType_Direct: { return true; } } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Redirect printf and log statements from oemcrypto functions to a file to // reduce noise RedirectStdoutToFile(); uint8_t subsample_flags; // OEMCrypto_DestBufferDesc and a buffer from which data needs to be copied // are expected as inputs to copy buffer API. // Input fuzzed data is interpreted as // (OEMCrypto_DestBufferDesc | subsample_flags | input_buffer) if (size <= sizeof(OEMCrypto_Copy_Buffer_Fuzz)) { return 0; } OEMCrypto_Copy_Buffer_Fuzz fuzzed_structure; // Fuzz dest_buffer_desc. memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure)); ConvertDataToValidEnum(OEMCrypto_BufferType_MaxValue, &fuzzed_structure.dest_buffer_desc.type); OEMCryptoLicenseAPIFuzz license_api_fuzz; Session* session = license_api_fuzz.session(); // Fuzz input buffer to be copied. size_t input_buffer_size = size - sizeof(fuzzed_structure); int secure_fd = 0; // Create output buffer pointers. If secure buffer is not supported, we // explicitly convert to clear buffer and fuzz. if (!InitializeOutputBuffers(session->session_id(), fuzzed_structure.dest_buffer_desc, &secure_fd, input_buffer_size)) { LOGI( "[OEMCrypto decrypt CENC fuzz] Secure buffers are not supported. Use " "clear buffer instead."); fuzzed_structure.dest_buffer_desc.type = OEMCrypto_BufferType_Clear; InitializeOutputBuffers(session->session_id(), fuzzed_structure.dest_buffer_desc, &secure_fd, input_buffer_size); } OEMCrypto_CopyBuffer(session->session_id(), data + sizeof(fuzzed_structure), input_buffer_size, &fuzzed_structure.dest_buffer_desc, subsample_flags); FreeOutputBuffers(session->session_id(), fuzzed_structure.dest_buffer_desc, &secure_fd); return 0; } } // namespace wvoec