// 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 "FuzzedDataProvider.h" #include "OEMCryptoCENC.h" #include "oemcrypto_fuzz_helper.h" #include "oemcrypto_fuzz_structs.h" namespace { // Avoid calling non-trivial destructor. wvoec::OEMCryptoLicenseAPIFuzz& license_api_fuzz = *new wvoec::OEMCryptoLicenseAPIFuzz; } // namespace extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { wvoec::RedirectStdoutToFile(); license_api_fuzz.Initialize(); return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // 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) wvoec::OEMCrypto_Copy_Buffer_Fuzz fuzzed_structure; if (size < sizeof(fuzzed_structure)) { return 0; } FuzzedDataProvider fuzzed_data(data, size); fuzzed_data.ConsumeData(&fuzzed_structure, sizeof(fuzzed_structure)); wvoec::ConvertDataToValidEnum(OEMCrypto_BufferType_MaxValue, &fuzzed_structure.dest_buffer_desc.type); fuzzed_structure.dest_buffer_desc.buffer_config %= wvoec::MAX_FUZZ_OUTPUT_LENGTH + 1; const std::vector input_buffer = fuzzed_data.ConsumeRemainingBytes(); const uint32_t session_id = license_api_fuzz.session().session_id(); // Initialize output buffer. OEMCrypto_DestBufferDesc dest_buffer_desc; int secure_fd = 0; dest_buffer_desc.type = fuzzed_structure.dest_buffer_desc.type; switch (dest_buffer_desc.type) { case OEMCrypto_BufferType_Clear: dest_buffer_desc.buffer.clear.clear_buffer = new OEMCrypto_SharedMemory[fuzzed_structure.dest_buffer_desc .buffer_config]; dest_buffer_desc.buffer.clear.clear_buffer_length = fuzzed_structure.dest_buffer_desc.buffer_config; break; case OEMCrypto_BufferType_Secure: if (OEMCrypto_AllocateSecureBuffer( session_id, fuzzed_structure.dest_buffer_desc.buffer_config, &dest_buffer_desc, &secure_fd) != OEMCrypto_SUCCESS) { return 0; } break; case OEMCrypto_BufferType_Direct: dest_buffer_desc.buffer.direct.is_video = fuzzed_structure.dest_buffer_desc.buffer_config & 1; break; } OEMCrypto_CopyBuffer(session_id, input_buffer.data(), input_buffer.size(), &dest_buffer_desc, fuzzed_structure.subsample_flags); // Free output buffer. switch (dest_buffer_desc.type) { case OEMCrypto_BufferType_Clear: delete[] dest_buffer_desc.buffer.clear.clear_buffer; break; case OEMCrypto_BufferType_Secure: OEMCrypto_FreeSecureBuffer(session_id, &dest_buffer_desc, secure_fd); break; case OEMCrypto_BufferType_Direct: break; } return 0; }