Pick widevine oemcrypto-v18 change
No-Typo-Check: From a third party header file Bug: 260918793 Test: unit tests Test: atp v2/widevine-eng/drm_compliance Change-Id: I36effd6a10a99bdb2399ab1f4a0fad026d607c70
This commit is contained in:
@@ -23,7 +23,7 @@ OEMCrypto implementations on linux.
|
||||
The options to select are `Job type: libfuzzer_asan_oemcrypto` and `Fuzzer:
|
||||
fuzzer name you are looking for`
|
||||
|
||||
Example: [load_license_fuzz](https://clusterfuzz.corp.google.com/fuzzer-stats?group_by=by-day&date_start=2020-07-11&date_end=2020-07-17&fuzzer=libFuzzer_oemcrypto_load_license_fuzz&job=libfuzzer_asan_oemcrypto)
|
||||
Example: [load_license_fuzz](https://clusterfuzz.corp.google.com/fuzzer-stats?group_by=by-day&date_start=2022-07-11&date_end=2022-07-17&fuzzer=libFuzzer_oemcrypto_load_license_fuzz&job=libfuzzer_asan_oemcrypto)
|
||||
|
||||
### Issues filed by clusterfuzz - Fixing those issues
|
||||
|
||||
@@ -127,8 +127,7 @@ OEMCrypto implementations on linux.
|
||||
information locally.
|
||||
|
||||
* Build and test fuzz scripts locally using following commands. The build
|
||||
script builds fuzz binaries for both oemcrypto reference implementation
|
||||
as well as opk implementation.
|
||||
script builds fuzz binaries for opk implementation.
|
||||
|
||||
```shell
|
||||
$ cd PATH_TO_CDM_DIR
|
||||
|
||||
@@ -6,18 +6,21 @@
|
||||
|
||||
set -ex
|
||||
|
||||
# CDM_DIR is used by several script, especially when there is some confusion
|
||||
if [ -z "$CDM_DIR" ]; then
|
||||
export CDM_DIR="$(readlink -e $(dirname $0)/../../..)"
|
||||
fi
|
||||
cd $CDM_DIR
|
||||
|
||||
export CXX=clang++
|
||||
export CC=clang
|
||||
export GYP_DEFINES="$GYP_DEFINES clang=1"
|
||||
export PATH_TO_CDM_DIR=.
|
||||
export PYTHONPATH="$PYTHONPATH:$PATH_TO_CDM_DIR/third_party"
|
||||
echo "CDM_DIR = $CDM_DIR"
|
||||
export PYTHONPATH="$PYTHONPATH:$CDM_DIR/third_party"
|
||||
|
||||
python3 $PATH_TO_CDM_DIR/third_party/gyp/__init__.py --format=ninja \
|
||||
--depth=$(pwd) oemcrypto/test/fuzz_tests/oemcrypto_fuzztests.gyp
|
||||
ninja -C out/Default
|
||||
# oemcrypto_opk_fuzztests.gypi has flags to instrument all the gyp targets
|
||||
# with fuzzer flags.
|
||||
python3 $PATH_TO_CDM_DIR/third_party/gyp/__init__.py --format=ninja \
|
||||
python3 $CDM_DIR/third_party/gyp/__init__.py --format=ninja \
|
||||
--depth=$(pwd) \
|
||||
--include=oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gypi \
|
||||
oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gyp
|
||||
|
||||
@@ -2,93 +2,82 @@
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#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.clear_buffer;
|
||||
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.clear_buffer =
|
||||
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
|
||||
// Input fuzzed data is interpreted as:
|
||||
// (OEMCrypto_DestBufferDesc | subsample_flags | input_buffer)
|
||||
if (size <= sizeof(OEMCrypto_Copy_Buffer_Fuzz)) {
|
||||
OEMCrypto_Copy_Buffer_Fuzz fuzzed_structure;
|
||||
if (size < sizeof(fuzzed_structure)) {
|
||||
return 0;
|
||||
}
|
||||
OEMCrypto_Copy_Buffer_Fuzz fuzzed_structure;
|
||||
// Fuzz dest_buffer_desc.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
FuzzedDataProvider fuzzed_data(data, size);
|
||||
fuzzed_data.ConsumeData(&fuzzed_structure, sizeof(fuzzed_structure));
|
||||
ConvertDataToValidEnum(OEMCrypto_BufferType_MaxValue,
|
||||
&fuzzed_structure.dest_buffer_desc.type);
|
||||
fuzzed_structure.dest_buffer_desc.buffer_config %= MAX_FUZZ_OUTPUT_LENGTH + 1;
|
||||
const std::vector<OEMCrypto_SharedMemory> input_buffer =
|
||||
fuzzed_data.ConsumeRemainingBytes<OEMCrypto_SharedMemory>();
|
||||
|
||||
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);
|
||||
const uint32_t session_id = license_api_fuzz.session()->session_id();
|
||||
|
||||
// Initialize output buffer.
|
||||
OEMCrypto_DestBufferDesc dest_buffer_desc;
|
||||
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);
|
||||
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->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);
|
||||
|
||||
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;
|
||||
}
|
||||
} // namespace wvoec
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -15,7 +15,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Open a session, create a usage entry.
|
||||
Session* session = entry.license_messages().session();
|
||||
session->open();
|
||||
entry.InstallTestRSAKey(session);
|
||||
entry.InstallTestDrmKey(session);
|
||||
session->CreateNewUsageEntry();
|
||||
session->GenerateNonce();
|
||||
vector<uint8_t> encrypted_usage_header;
|
||||
|
||||
@@ -4,187 +4,169 @@
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
#include "oemcrypto_fuzz_structs.h"
|
||||
#include "oemcrypto_overflow.h"
|
||||
|
||||
namespace wvoec {
|
||||
const size_t MAX_FUZZ_SAMPLE_SIZE = 5 * MB;
|
||||
// Free dynamic memory allocated by fuzzer script.
|
||||
void FreeOutputBuffers(OEMCrypto_SESSION session_id,
|
||||
OEMCrypto_SampleDescription* sample_description,
|
||||
size_t sample_index, int* secure_fd_array) {
|
||||
for (size_t i = 0; i < sample_index; i++) {
|
||||
OEMCrypto_DestBufferDesc fuzzed_output_descriptor =
|
||||
sample_description[i].buffers.output_descriptor;
|
||||
switch (fuzzed_output_descriptor.type) {
|
||||
case OEMCrypto_BufferType_Clear: {
|
||||
delete[] fuzzed_output_descriptor.buffer.clear.clear_buffer;
|
||||
break;
|
||||
}
|
||||
case OEMCrypto_BufferType_Secure: {
|
||||
OEMCrypto_FreeSecureBuffer(session_id, &fuzzed_output_descriptor,
|
||||
secure_fd_array[i]);
|
||||
break;
|
||||
}
|
||||
case OEMCrypto_BufferType_Direct: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to initialize output buffer pointers by allocating memory.
|
||||
// Limiting output buffer size to 5 MB as 4 MB is maximum size specified
|
||||
// by resource rating tier documentation.
|
||||
bool InitializeOutputBuffers(OEMCrypto_SESSION session_id,
|
||||
OEMCrypto_DestBufferDesc& output_descriptor,
|
||||
size_t sample_index,
|
||||
vector<int>& secure_fd_array) {
|
||||
switch (output_descriptor.type) {
|
||||
case OEMCrypto_BufferType_Clear: {
|
||||
output_descriptor.buffer.clear.clear_buffer =
|
||||
new OEMCrypto_SharedMemory[std::min(
|
||||
MAX_FUZZ_SAMPLE_SIZE,
|
||||
output_descriptor.buffer.clear.clear_buffer_length)];
|
||||
return true;
|
||||
}
|
||||
case OEMCrypto_BufferType_Secure: {
|
||||
int* secure_fd;
|
||||
OEMCryptoResult sts = OEMCrypto_AllocateSecureBuffer(
|
||||
session_id,
|
||||
std::min(MAX_FUZZ_SAMPLE_SIZE,
|
||||
output_descriptor.buffer.secure.secure_buffer_length),
|
||||
&output_descriptor, secure_fd);
|
||||
if (sts == OEMCrypto_SUCCESS) secure_fd_array[sample_index] = *secure_fd;
|
||||
return sts == OEMCrypto_SUCCESS;
|
||||
}
|
||||
case OEMCrypto_BufferType_Direct: {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Limit output buffer size to 5 MB as 4 MB is maximum size specified by
|
||||
// resource rating tier documentation.
|
||||
const size_t MAX_FUZZ_SAMPLE_SIZE = 5 * MB;
|
||||
|
||||
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();
|
||||
size_t samples_length;
|
||||
|
||||
// Split data using separator.
|
||||
auto inputs = SplitInput(data, size);
|
||||
if (inputs.size() < 2) {
|
||||
const std::vector<FuzzedData> inputs = SplitFuzzedData(data, size);
|
||||
if (inputs.size() < 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read cipher mode and pattern from fuzzed data.
|
||||
OEMCrypto_Decrypt_Cenc_Fuzz fuzzed_structure;
|
||||
if (inputs[0].size() < sizeof(fuzzed_structure)) {
|
||||
if (inputs[0].size < sizeof(fuzzed_structure)) {
|
||||
return 0;
|
||||
}
|
||||
// Copy OEMCrypto_Decrypt_Cenc_Fuzz from input data.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
FuzzedDataProvider fuzzed_data(inputs[0].data, inputs[0].size);
|
||||
fuzzed_data.ConsumeData(&fuzzed_structure, sizeof(fuzzed_structure));
|
||||
ConvertDataToValidEnum(OEMCrypto_CipherMode_MaxValue,
|
||||
&fuzzed_structure.cipher_mode);
|
||||
|
||||
size_t remaining_size_for_samples =
|
||||
inputs[0].size() - sizeof(fuzzed_structure);
|
||||
// Initialize FDP structures to read data using inbuilt functions.
|
||||
FuzzedDataProvider fuzzed_sample_data(data + sizeof(fuzzed_structure),
|
||||
remaining_size_for_samples);
|
||||
FuzzedDataProvider fuzzed_subsample_data(inputs[1].data(), inputs[1].size());
|
||||
// Allocate sample descriptions.
|
||||
std::vector<OEMCrypto_SampleDescription> sample_descriptions(
|
||||
fuzzed_data.remaining_bytes() / sizeof(OEMCrypto_SampleDescription_Fuzz));
|
||||
|
||||
// Read subsamples from fuzzed data.
|
||||
vector<OEMCrypto_SubSampleDescription> subsamples;
|
||||
while (fuzzed_subsample_data.remaining_bytes() >=
|
||||
sizeof(OEMCrypto_SubSampleDescription)) {
|
||||
OEMCrypto_SubSampleDescription subsample;
|
||||
fuzzed_subsample_data.ConsumeData(&subsample,
|
||||
sizeof(OEMCrypto_SubSampleDescription));
|
||||
subsamples.push_back(subsample);
|
||||
}
|
||||
if (subsamples.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
// Allocate input buffers for each sample description.
|
||||
std::vector<std::vector<OEMCrypto_SharedMemory>> input_buffers(
|
||||
sample_descriptions.size());
|
||||
|
||||
// Infer samples_length from fuzzed data.
|
||||
size_t sample_description_size = sizeof(OEMCrypto_SampleDescription);
|
||||
samples_length =
|
||||
fuzzed_sample_data.remaining_bytes() / sample_description_size;
|
||||
if (samples_length == 0) {
|
||||
return 0;
|
||||
}
|
||||
// Allocate secure_fd values for secure buffers.
|
||||
std::vector<int> secure_fd_array(sample_descriptions.size());
|
||||
|
||||
// Initialize sample_descriptions array.
|
||||
vector<OEMCrypto_SampleDescription> sample_descriptions(samples_length);
|
||||
// Create array to maintain secure_fd buffer values for secure buffers.
|
||||
vector<int> secure_fd_array(samples_length);
|
||||
// Allocate subsamples for each sample description.
|
||||
std::vector<std::vector<OEMCrypto_SubSampleDescription>> subsamples(
|
||||
sample_descriptions.size());
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Copy samples from fuzzed data.
|
||||
size_t input_subsample_index = 0;
|
||||
size_t total_input_data_length = 0;
|
||||
for (size_t i = 0; i < samples_length; i++) {
|
||||
fuzzed_sample_data.ConsumeData(&sample_descriptions[i],
|
||||
sample_description_size);
|
||||
const uint32_t session_id = license_api_fuzz.session()->session_id();
|
||||
|
||||
// Free first given number of output buffers.
|
||||
const auto FreeOutputBuffers = [&sample_descriptions, session_id,
|
||||
&secure_fd_array](size_t num_buffers) {
|
||||
for (size_t i = 0; i < num_buffers; i++) {
|
||||
OEMCrypto_DestBufferDesc& output_descriptor =
|
||||
sample_descriptions[i].buffers.output_descriptor;
|
||||
switch (output_descriptor.type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
delete[] output_descriptor.buffer.clear.clear_buffer;
|
||||
break;
|
||||
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
OEMCrypto_FreeSecureBuffer(session_id, &output_descriptor,
|
||||
secure_fd_array[i]);
|
||||
break;
|
||||
|
||||
case OEMCrypto_BufferType_Direct:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Prepare each sample description.
|
||||
FuzzedDataProvider& sample_description_data = fuzzed_data;
|
||||
FuzzedDataProvider input_buffer_data(inputs[1].data, inputs[1].size);
|
||||
FuzzedDataProvider subsample_data(inputs[2].data, inputs[2].size);
|
||||
for (size_t i = 0; i < sample_descriptions.size(); i++) {
|
||||
// Read and normalize sample description fuzzed properties.
|
||||
OEMCrypto_SampleDescription_Fuzz fuzzed_sample_description;
|
||||
sample_description_data.ConsumeData(&fuzzed_sample_description,
|
||||
sizeof(fuzzed_sample_description));
|
||||
fuzzed_sample_description.buffers.input_data_length %=
|
||||
MAX_FUZZ_SAMPLE_SIZE + 1;
|
||||
ConvertDataToValidEnum(
|
||||
OEMCrypto_BufferType_MaxValue,
|
||||
&sample_descriptions[i].buffers.output_descriptor.type);
|
||||
&fuzzed_sample_description.buffers.output_descriptor.type);
|
||||
fuzzed_sample_description.buffers.output_descriptor.buffer_config %=
|
||||
MAX_FUZZ_SAMPLE_SIZE + 1;
|
||||
|
||||
// Copy random data into input sample data. Cap input data length at 5 MB,
|
||||
// 1 MB higher than that described by resource rating tier.
|
||||
total_input_data_length += std::min(
|
||||
MAX_FUZZ_SAMPLE_SIZE, sample_descriptions[i].buffers.input_data_length);
|
||||
|
||||
// Copy sub sample data.
|
||||
sample_descriptions[i].subsamples = &subsamples[input_subsample_index];
|
||||
if (OPK_AddOverflowUX(input_subsample_index,
|
||||
sample_descriptions[i].subsamples_length,
|
||||
&input_subsample_index)) {
|
||||
// Read input data.
|
||||
if (fuzzed_sample_description.buffers.input_data_length >
|
||||
input_buffer_data.remaining_bytes()) {
|
||||
FreeOutputBuffers(i);
|
||||
return 0;
|
||||
}
|
||||
if (input_subsample_index > subsamples.size()) return 0;
|
||||
} // Sample loop.
|
||||
input_buffers[i] = input_buffer_data.ConsumeBytes<uint8_t>(
|
||||
fuzzed_sample_description.buffers.input_data_length);
|
||||
sample_descriptions[i].buffers.input_data = input_buffers[i].data();
|
||||
sample_descriptions[i].buffers.input_data_length = input_buffers[i].size();
|
||||
|
||||
// Allocate input/output buffers for each sample description.
|
||||
vector<OEMCrypto_SharedMemory> input_buffer(total_input_data_length);
|
||||
size_t input_buffer_index = 0;
|
||||
for (size_t i = 0; i < samples_length; i++) {
|
||||
if (total_input_data_length > 0) {
|
||||
sample_descriptions[i].buffers.input_data =
|
||||
&input_buffer[input_buffer_index];
|
||||
// Set subsample data.
|
||||
if (fuzzed_sample_description.subsamples_length >
|
||||
subsample_data.remaining_bytes() /
|
||||
sizeof(OEMCrypto_SubSampleDescription)) {
|
||||
FreeOutputBuffers(i);
|
||||
return 0;
|
||||
}
|
||||
input_buffer_index += std::min(
|
||||
MAX_FUZZ_SAMPLE_SIZE, sample_descriptions[i].buffers.input_data_length);
|
||||
if (fuzzed_sample_description.subsamples_length > 0) {
|
||||
subsamples[i].resize(fuzzed_sample_description.subsamples_length);
|
||||
subsample_data.ConsumeData(
|
||||
subsamples[i].data(),
|
||||
subsamples[i].size() * sizeof(OEMCrypto_SubSampleDescription));
|
||||
}
|
||||
sample_descriptions[i].subsamples = subsamples[i].data();
|
||||
sample_descriptions[i].subsamples_length = subsamples[i].size();
|
||||
|
||||
// Create output buffer pointers. If secure buffer is not supported, we
|
||||
// explicitly convert to clear buffer and fuzz.
|
||||
if (!InitializeOutputBuffers(
|
||||
session->session_id(),
|
||||
sample_descriptions[i].buffers.output_descriptor, i,
|
||||
secure_fd_array)) {
|
||||
LOGI(
|
||||
"[OEMCrypto decrypt CENC fuzz] Secure buffers are not supported. "
|
||||
"Use "
|
||||
"clear buffer instead.");
|
||||
sample_descriptions[i].buffers.output_descriptor.type =
|
||||
OEMCrypto_BufferType_Clear;
|
||||
InitializeOutputBuffers(session->session_id(),
|
||||
sample_descriptions[i].buffers.output_descriptor,
|
||||
i, secure_fd_array);
|
||||
// Set IV data.
|
||||
memcpy(sample_descriptions[i].iv, fuzzed_sample_description.iv,
|
||||
sizeof(sample_descriptions[i].iv));
|
||||
|
||||
// Initialize output buffer.
|
||||
OEMCrypto_DestBufferDesc& output_descriptor =
|
||||
sample_descriptions[i].buffers.output_descriptor;
|
||||
const OEMCrypto_DestBufferDesc_Fuzz& fuzzed_output_descriptor =
|
||||
fuzzed_sample_description.buffers.output_descriptor;
|
||||
output_descriptor.type = fuzzed_output_descriptor.type;
|
||||
switch (output_descriptor.type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
output_descriptor.buffer.clear.clear_buffer =
|
||||
new OEMCrypto_SharedMemory[fuzzed_output_descriptor.buffer_config];
|
||||
output_descriptor.buffer.clear.clear_buffer_length =
|
||||
fuzzed_output_descriptor.buffer_config;
|
||||
break;
|
||||
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
if (OEMCrypto_AllocateSecureBuffer(
|
||||
session_id, fuzzed_output_descriptor.buffer_config,
|
||||
&output_descriptor, &secure_fd_array[i]) != OEMCrypto_SUCCESS) {
|
||||
FreeOutputBuffers(i);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OEMCrypto_BufferType_Direct:
|
||||
output_descriptor.buffer.direct.is_video =
|
||||
fuzzed_output_descriptor.buffer_config & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Load license and call decrypt_cenc API.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCrypto_SelectKey(session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode);
|
||||
OEMCrypto_DecryptCENC(session->session_id(), sample_descriptions.data(),
|
||||
samples_length, &fuzzed_structure.pattern);
|
||||
FreeOutputBuffers(session->session_id(), sample_descriptions.data(),
|
||||
samples_length, secure_fd_array.data());
|
||||
const MessageKeyData& key = license_api_fuzz.session()->license().keys[0];
|
||||
vector<uint8_t> key_handle;
|
||||
GetKeyHandleIntoVector(session_id, key.key_id, key.key_id_length,
|
||||
fuzzed_structure.cipher_mode, key_handle);
|
||||
OEMCrypto_DecryptCENC(key_handle.data(), key_handle.size(),
|
||||
sample_descriptions.data(), sample_descriptions.size(),
|
||||
&fuzzed_structure.pattern);
|
||||
|
||||
// Free all output buffers.
|
||||
FreeOutputBuffers(sample_descriptions.size());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -6,19 +6,18 @@
|
||||
namespace wvoec {
|
||||
void RedirectStdoutToFile() { freopen("log.txt", "a", stdout); }
|
||||
|
||||
std::vector<std::vector<uint8_t>> SplitInput(const uint8_t* data, size_t size) {
|
||||
std::vector<std::vector<uint8_t>> result;
|
||||
auto current_pos = data;
|
||||
auto end = data + size;
|
||||
// Using memmem to find separator
|
||||
while (const uint8_t* pos = reinterpret_cast<const uint8_t*>(
|
||||
memmem(current_pos, end - current_pos, kFuzzDataSeparator,
|
||||
sizeof(kFuzzDataSeparator)))) {
|
||||
result.push_back({current_pos, pos});
|
||||
current_pos = pos + sizeof(kFuzzDataSeparator);
|
||||
std::vector<FuzzedData> SplitFuzzedData(const uint8_t* data, size_t size) {
|
||||
std::vector<FuzzedData> result;
|
||||
const uint8_t* const end = data + size;
|
||||
// Using memmem to find separator.
|
||||
while (
|
||||
const uint8_t* const separator = reinterpret_cast<const uint8_t*>(memmem(
|
||||
data, end - data, kFuzzDataSeparator, sizeof(kFuzzDataSeparator)))) {
|
||||
result.push_back({data, static_cast<size_t>(separator - data)});
|
||||
data = separator + sizeof(kFuzzDataSeparator);
|
||||
}
|
||||
if (current_pos < end) {
|
||||
result.push_back({current_pos, end});
|
||||
if (data < end) {
|
||||
result.push_back({data, static_cast<size_t>(end - data)});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -20,9 +20,16 @@ extern "C" size_t LLVMFuzzerMutate(uint8_t* Data, size_t Size, size_t MaxSize)
|
||||
__attribute__((weak));
|
||||
|
||||
const size_t KB = 1024;
|
||||
// Maximum signature length. If fuzzed signature length is greater that this,
|
||||
// this value will be used for signature length.
|
||||
const size_t MAX_FUZZ_SIGNATURE_LENGTH = 5 * KB;
|
||||
|
||||
// Default maximum length of fuzzing output parameters.
|
||||
const size_t MAX_FUZZ_OUTPUT_LENGTH = 5 * KB;
|
||||
|
||||
// Fuzzed data region.
|
||||
struct FuzzedData {
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Initial setup to create a valid OEMCrypto state such as initializing crypto
|
||||
// firmware/hardware, installing golden key box etc. in order to fuzz
|
||||
// OEMCrypto APIs.
|
||||
@@ -32,7 +39,8 @@ class InitializeFuzz : public SessionUtil {
|
||||
wvoec::global_features.Initialize();
|
||||
OEMCrypto_SetSandbox(kTestSandbox, sizeof(kTestSandbox));
|
||||
OEMCrypto_Initialize();
|
||||
EnsureTestKeys();
|
||||
OEMCrypto_EnterTestMode();
|
||||
EnsureTestROT();
|
||||
}
|
||||
|
||||
~InitializeFuzz() { OEMCrypto_Terminate(); }
|
||||
@@ -42,7 +50,7 @@ class OEMCryptoLicenseAPIFuzz : public InitializeFuzz {
|
||||
public:
|
||||
OEMCryptoLicenseAPIFuzz() : license_messages_(&session_) {
|
||||
session_.open();
|
||||
InstallTestRSAKey(&session_);
|
||||
InstallTestDrmKey(&session_);
|
||||
session_.GenerateNonce();
|
||||
}
|
||||
|
||||
@@ -113,20 +121,27 @@ class LicenseWithUsageEntryFuzz : public InitializeFuzz {
|
||||
Session session_;
|
||||
};
|
||||
|
||||
// Convert data to valid enum value.
|
||||
// Convert data from FuzzedDataProvider to valid enum value.
|
||||
template <typename T>
|
||||
T ConvertDataToValidEnum(FuzzedDataProvider& fuzzed_data, T max_enum_value) {
|
||||
return static_cast<T>(fuzzed_data.ConsumeIntegralInRange<uint32_t>(
|
||||
0, static_cast<uint32_t>(max_enum_value)));
|
||||
}
|
||||
|
||||
// Convert data to valid enum value in place.
|
||||
template <typename T>
|
||||
void ConvertDataToValidEnum(T max_enum_value, T* t) {
|
||||
FuzzedDataProvider fuzzed_enum_data(reinterpret_cast<uint8_t*>(t), sizeof(T));
|
||||
*t = static_cast<T>(fuzzed_enum_data.ConsumeIntegralInRange<uint32_t>(
|
||||
0, static_cast<uint32_t>(max_enum_value)));
|
||||
*t = ConvertDataToValidEnum(fuzzed_enum_data, max_enum_value);
|
||||
}
|
||||
|
||||
// Redirect printf and log statements from oemcrypto functions to a file to
|
||||
// reduce noise
|
||||
void RedirectStdoutToFile();
|
||||
|
||||
// Function to split fuzzer input using delimiter "-_^_".
|
||||
std::vector<std::vector<uint8_t>> SplitInput(const uint8_t* data, size_t size);
|
||||
// Split fuzzed data using delimiter "-_^_".
|
||||
std::vector<FuzzedData> SplitFuzzedData(const uint8_t* data, size_t size);
|
||||
|
||||
// Check the status and exit fuzzer if arguments do not match. This is usually
|
||||
// called to check status of APIs which are called to setup state for fuzzers.
|
||||
void CheckStatusAndExitFuzzerOnFailure(OEMCryptoResult result,
|
||||
|
||||
@@ -8,6 +8,26 @@
|
||||
#include "odk.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// OEMCrypto_DestBufferDesc fuzzed properties.
|
||||
struct OEMCrypto_DestBufferDesc_Fuzz {
|
||||
OEMCryptoBufferType type;
|
||||
size_t buffer_config;
|
||||
};
|
||||
|
||||
// OEMCrypto_InputOutputPair fuzzed properties.
|
||||
struct OEMCrypto_InputOutputPair_Fuzz {
|
||||
size_t input_data_length;
|
||||
OEMCrypto_DestBufferDesc_Fuzz output_descriptor;
|
||||
};
|
||||
|
||||
// OEMCrypto_SampleDescription fuzzed properties.
|
||||
struct OEMCrypto_SampleDescription_Fuzz {
|
||||
OEMCrypto_InputOutputPair_Fuzz buffers;
|
||||
uint8_t iv[16];
|
||||
size_t subsamples_length;
|
||||
};
|
||||
|
||||
struct OEMCrypto_Renewal_Response_Fuzz {
|
||||
// Timer limits in core license response needs to be fuzzed as load renewal
|
||||
// depends on timer limits loaded from license response.
|
||||
@@ -50,16 +70,6 @@ struct OEMCrypto_Generic_Api_Fuzz {
|
||||
// this structure.
|
||||
};
|
||||
|
||||
struct OEMCrypto_Generic_Verify_Fuzz {
|
||||
// Corpus format is as belowr.
|
||||
// cipher_mode + algorithm + signature_length + buffer with actual data
|
||||
OEMCryptoCipherMode cipher_mode;
|
||||
OEMCrypto_Algorithm algorithm;
|
||||
size_t signature_length;
|
||||
// Buffer data is of variable length and not included in
|
||||
// this structure.
|
||||
};
|
||||
|
||||
struct OEMCrypto_Generate_RSA_Signature_Fuzz {
|
||||
// Corpus format is as below, let | be separator.
|
||||
// padding_scheme + signature_length + input buffer
|
||||
@@ -72,10 +82,11 @@ struct OEMCrypto_Generate_RSA_Signature_Fuzz {
|
||||
struct OEMCrypto_Copy_Buffer_Fuzz {
|
||||
// Corpus format is as below.
|
||||
// dest_buffer_desc + subsample_flags + input buffer
|
||||
OEMCrypto_DestBufferDesc dest_buffer_desc;
|
||||
OEMCrypto_DestBufferDesc_Fuzz dest_buffer_desc;
|
||||
uint8_t subsample_flags;
|
||||
// Input buffer of variable length is not included in this structure.
|
||||
};
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // OEMCRYPTO_FUZZ_STRUCTS_H_
|
||||
#endif // OEMCRYPTO_FUZZ_STRUCTS_H_
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
@@ -11,23 +12,25 @@ 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();
|
||||
|
||||
OEMCrypto_Generate_RSA_Signature_Fuzz fuzzed_structure;
|
||||
if (size <= sizeof(OEMCrypto_Generate_RSA_Signature_Fuzz)) {
|
||||
if (size < sizeof(fuzzed_structure)) {
|
||||
return 0;
|
||||
}
|
||||
FuzzedDataProvider fuzzed_data(data, size);
|
||||
fuzzed_data.ConsumeData(&fuzzed_structure, sizeof(fuzzed_structure));
|
||||
const std::vector<uint8_t> message =
|
||||
fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
|
||||
// Copy data to fuzzed structure.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
// Creates wrapped rsa key and calls load drm private key.
|
||||
static OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
// We cannot allocate buffers of random huge lengths in memory.
|
||||
// This also slows down the fuzzer.
|
||||
size_t signature_length =
|
||||
std::min(MAX_FUZZ_SIGNATURE_LENGTH, fuzzed_structure.signature_length);
|
||||
vector<uint8_t> signature(signature_length);
|
||||
fuzzed_structure.signature_length %= MAX_FUZZ_OUTPUT_LENGTH + 1;
|
||||
std::vector<uint8_t> signature(fuzzed_structure.signature_length);
|
||||
OEMCrypto_GenerateRSASignature(
|
||||
license_api_fuzz.session()->session_id(), data + sizeof(fuzzed_structure),
|
||||
size - sizeof(fuzzed_structure), signature.data(), &signature_length,
|
||||
license_api_fuzz.session()->session_id(), message.data(), message.size(),
|
||||
signature.data(), &fuzzed_structure.signature_length,
|
||||
fuzzed_structure.padding_scheme);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
OEMCrypto_Initialize();
|
||||
session_helper.EnsureTestKeys();
|
||||
OEMCrypto_EnterTestMode();
|
||||
session_helper.EnsureTestROT();
|
||||
|
||||
Session s;
|
||||
s.open();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
#include "oemcrypto_fuzz_structs.h"
|
||||
#include "oemcrypto_types.h"
|
||||
@@ -16,45 +17,43 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
RedirectStdoutToFile();
|
||||
|
||||
// Split data using separator.
|
||||
auto inputs = SplitInput(data, size);
|
||||
const std::vector<FuzzedData> inputs = SplitFuzzedData(data, size);
|
||||
if (inputs.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OEMCrypto_Generic_Api_Fuzz fuzzed_structure;
|
||||
if (inputs[0].size() < sizeof(fuzzed_structure)) {
|
||||
if (inputs[0].size < sizeof(fuzzed_structure)) {
|
||||
return 0;
|
||||
}
|
||||
// Copy OEMCrypto_Generic_Api_Fuzz from input data.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
FuzzedDataProvider fuzzed_data(inputs[0].data, inputs[0].size);
|
||||
fuzzed_data.ConsumeData(&fuzzed_structure, sizeof(fuzzed_structure));
|
||||
ConvertDataToValidEnum(OEMCrypto_CipherMode_MaxValue,
|
||||
&fuzzed_structure.cipher_mode);
|
||||
ConvertDataToValidEnum(OEMCrypto_Algorithm_MaxValue,
|
||||
&fuzzed_structure.algorithm);
|
||||
|
||||
// Copy iv from input data.
|
||||
size_t iv_size = inputs[0].size() - sizeof(fuzzed_structure);
|
||||
if (iv_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
vector<uint8_t> iv(iv_size);
|
||||
memcpy(iv.data(), data + sizeof(fuzzed_structure), iv_size);
|
||||
const std::vector<uint8_t> iv = fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
|
||||
// Copy clear buffer from input data.
|
||||
vector<uint8_t> encrypted_buffer(inputs[1].size());
|
||||
vector<uint8_t> clear_buffer(inputs[1].size());
|
||||
memcpy(encrypted_buffer.data(), inputs[1].data(), inputs[1].size());
|
||||
// Initialize encrypted and clear buffers.
|
||||
const std::vector<uint8_t> encrypted_buffer(inputs[1].data,
|
||||
inputs[1].data + inputs[1].size);
|
||||
std::vector<uint8_t> clear_buffer(encrypted_buffer.size());
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Load license and call generic_decrypt API.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCrypto_SelectKey(session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode);
|
||||
OEMCrypto_Generic_Decrypt(session->session_id(), encrypted_buffer.data(),
|
||||
encrypted_buffer.size(), iv.data(),
|
||||
fuzzed_structure.algorithm, clear_buffer.data());
|
||||
vector<uint8_t> key_handle;
|
||||
GetKeyHandleIntoVector(session->session_id(),
|
||||
session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode, key_handle);
|
||||
OEMCrypto_Generic_Decrypt(key_handle.data(), key_handle.size(),
|
||||
encrypted_buffer.data(), encrypted_buffer.size(),
|
||||
iv.data(), fuzzed_structure.algorithm,
|
||||
clear_buffer.data());
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
#include "oemcrypto_fuzz_structs.h"
|
||||
#include "oemcrypto_types.h"
|
||||
@@ -16,45 +17,43 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
RedirectStdoutToFile();
|
||||
|
||||
// Split data using separator.
|
||||
auto inputs = SplitInput(data, size);
|
||||
const std::vector<FuzzedData> inputs = SplitFuzzedData(data, size);
|
||||
if (inputs.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OEMCrypto_Generic_Api_Fuzz fuzzed_structure;
|
||||
if (inputs[0].size() < sizeof(fuzzed_structure)) {
|
||||
if (inputs[0].size < sizeof(fuzzed_structure)) {
|
||||
return 0;
|
||||
}
|
||||
// Copy OEMCrypto_Generic_Api_Fuzz from input data.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
FuzzedDataProvider fuzzed_data(inputs[0].data, inputs[0].size);
|
||||
fuzzed_data.ConsumeData(&fuzzed_structure, sizeof(fuzzed_structure));
|
||||
ConvertDataToValidEnum(OEMCrypto_CipherMode_MaxValue,
|
||||
&fuzzed_structure.cipher_mode);
|
||||
ConvertDataToValidEnum(OEMCrypto_Algorithm_MaxValue,
|
||||
&fuzzed_structure.algorithm);
|
||||
|
||||
// Copy iv from input data.
|
||||
size_t iv_size = inputs[0].size() - sizeof(fuzzed_structure);
|
||||
if (iv_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
vector<uint8_t> iv(iv_size);
|
||||
memcpy(iv.data(), data + sizeof(fuzzed_structure), iv_size);
|
||||
const std::vector<uint8_t> iv = fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
|
||||
// Copy clear buffer from input data.
|
||||
vector<uint8_t> clear_buffer(inputs[1].size());
|
||||
vector<uint8_t> encrypted_buffer(inputs[1].size());
|
||||
memcpy(clear_buffer.data(), inputs[1].data(), inputs[1].size());
|
||||
// Initialize clear and encrypted buffers.
|
||||
const std::vector<uint8_t> clear_buffer(inputs[1].data,
|
||||
inputs[1].data + inputs[1].size);
|
||||
std::vector<uint8_t> encrypted_buffer(clear_buffer.size());
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Load license and call generic_encrypt API.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCrypto_SelectKey(session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode);
|
||||
OEMCrypto_Generic_Encrypt(
|
||||
session->session_id(), clear_buffer.data(), clear_buffer.size(),
|
||||
iv.data(), fuzzed_structure.algorithm, encrypted_buffer.data());
|
||||
vector<uint8_t> key_handle;
|
||||
GetKeyHandleIntoVector(session->session_id(),
|
||||
session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode, key_handle);
|
||||
OEMCrypto_Generic_Encrypt(key_handle.data(), key_handle.size(),
|
||||
clear_buffer.data(), clear_buffer.size(), iv.data(),
|
||||
fuzzed_structure.algorithm,
|
||||
encrypted_buffer.data());
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
#include "oemcrypto_fuzz_structs.h"
|
||||
#include "oemcrypto_types.h"
|
||||
@@ -19,36 +21,35 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
return 0;
|
||||
}
|
||||
// Copy OEMCrypto_Generic_Api_Fuzz from input data.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
FuzzedDataProvider fuzzed_data(data, size);
|
||||
fuzzed_data.ConsumeData(&fuzzed_structure, sizeof(fuzzed_structure));
|
||||
ConvertDataToValidEnum(OEMCrypto_CipherMode_MaxValue,
|
||||
&fuzzed_structure.cipher_mode);
|
||||
ConvertDataToValidEnum(OEMCrypto_Algorithm_MaxValue,
|
||||
&fuzzed_structure.algorithm);
|
||||
|
||||
size_t clear_buffer_size = size - sizeof(fuzzed_structure);
|
||||
if (clear_buffer_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
// Copy clear buffer from input data.
|
||||
vector<uint8_t> clear_buffer(clear_buffer_size);
|
||||
memcpy(clear_buffer.data(), data + sizeof(fuzzed_structure),
|
||||
clear_buffer_size);
|
||||
const std::vector<uint8_t> clear_buffer =
|
||||
fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Load license and call generic_sign API.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCrypto_SelectKey(session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode);
|
||||
vector<uint8_t> key_handle;
|
||||
GetKeyHandleIntoVector(session->session_id(),
|
||||
session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode, key_handle);
|
||||
size_t signature_length = 0;
|
||||
OEMCrypto_Generic_Sign(session->session_id(), clear_buffer.data(),
|
||||
clear_buffer.size(), fuzzed_structure.algorithm,
|
||||
nullptr, &signature_length);
|
||||
vector<uint8_t> signature(signature_length);
|
||||
OEMCrypto_Generic_Sign(session->session_id(), clear_buffer.data(),
|
||||
clear_buffer.size(), fuzzed_structure.algorithm,
|
||||
signature.data(), &signature_length);
|
||||
OEMCrypto_Generic_Sign(key_handle.data(), key_handle.size(),
|
||||
clear_buffer.data(), clear_buffer.size(),
|
||||
fuzzed_structure.algorithm, nullptr,
|
||||
&signature_length);
|
||||
std::vector<uint8_t> signature(signature_length);
|
||||
OEMCrypto_Generic_Sign(key_handle.data(), key_handle.size(),
|
||||
clear_buffer.data(), clear_buffer.size(),
|
||||
fuzzed_structure.algorithm, signature.data(),
|
||||
&signature_length);
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -2,66 +2,130 @@
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
#include "oemcrypto_fuzz_structs.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec {
|
||||
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();
|
||||
|
||||
OEMCrypto_Generic_Verify_Fuzz fuzzed_structure;
|
||||
if (size < sizeof(fuzzed_structure)) {
|
||||
return 0;
|
||||
// Properties deserialized from fuzzed data.
|
||||
struct FuzzedProperties {
|
||||
OEMCrypto_Generic_Api_Fuzz structure;
|
||||
std::vector<uint8_t> buffer;
|
||||
std::vector<uint8_t> signature;
|
||||
};
|
||||
|
||||
// Contains value only if has_value is true.
|
||||
struct OptionalFuzzedProperties {
|
||||
FuzzedProperties value;
|
||||
bool has_value;
|
||||
};
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
|
||||
OptionalFuzzedProperties DeserializeFuzzedData(const uint8_t* data,
|
||||
size_t size) {
|
||||
OptionalFuzzedProperties fuzzed_properties;
|
||||
const std::vector<FuzzedData> inputs = SplitFuzzedData(data, size);
|
||||
if (inputs.size() < 2 ||
|
||||
inputs[0].size < sizeof(fuzzed_properties.value.structure)) {
|
||||
fuzzed_properties.has_value = false;
|
||||
return fuzzed_properties;
|
||||
}
|
||||
// Copy OEMCrypto_Generic_Verify_Fuzz from input data.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
FuzzedDataProvider fuzzed_data(inputs[0].data, inputs[0].size);
|
||||
fuzzed_data.ConsumeData(&fuzzed_properties.value.structure,
|
||||
sizeof(fuzzed_properties.value.structure));
|
||||
ConvertDataToValidEnum(OEMCrypto_CipherMode_MaxValue,
|
||||
&fuzzed_structure.cipher_mode);
|
||||
&fuzzed_properties.value.structure.cipher_mode);
|
||||
ConvertDataToValidEnum(OEMCrypto_Algorithm_MaxValue,
|
||||
&fuzzed_structure.algorithm);
|
||||
&fuzzed_properties.value.structure.algorithm);
|
||||
fuzzed_properties.value.buffer = fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
fuzzed_properties.value.signature.assign(inputs[1].data,
|
||||
inputs[1].data + inputs[1].size);
|
||||
fuzzed_properties.has_value = true;
|
||||
return fuzzed_properties;
|
||||
}
|
||||
|
||||
size_t in_buffer_size = size - sizeof(fuzzed_structure);
|
||||
if (in_buffer_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
// Copy clear buffer from input data.
|
||||
vector<uint8_t> in_buffer(in_buffer_size);
|
||||
memcpy(in_buffer.data(), data + sizeof(fuzzed_structure), in_buffer_size);
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Load license and call generic_verify API.
|
||||
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||
RedirectStdoutToFile();
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCrypto_SelectKey(session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
OEMCrypto_CipherMode_CENC);
|
||||
// Calculate signature for in buffer.
|
||||
size_t signature_length = 0;
|
||||
OEMCrypto_Generic_Sign(session->session_id(), in_buffer.data(),
|
||||
in_buffer.size(), fuzzed_structure.algorithm, nullptr,
|
||||
&signature_length);
|
||||
vector<uint8_t> signature(signature_length);
|
||||
OEMCrypto_Generic_Sign(session->session_id(), in_buffer.data(),
|
||||
in_buffer.size(), fuzzed_structure.algorithm,
|
||||
signature.data(), &signature_length);
|
||||
|
||||
OEMCrypto_SelectKey(session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_structure.cipher_mode);
|
||||
signature_length =
|
||||
std::min(MAX_FUZZ_SIGNATURE_LENGTH, fuzzed_structure.signature_length);
|
||||
signature.resize(signature_length);
|
||||
OEMCrypto_Generic_Verify(session->session_id(), in_buffer.data(),
|
||||
in_buffer.size(), fuzzed_structure.algorithm,
|
||||
signature.data(), signature_length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||
size_t max_size, unsigned int seed) {
|
||||
// Deserialize fuzzed data.
|
||||
OptionalFuzzedProperties fuzzed_properties =
|
||||
DeserializeFuzzedData(data, size);
|
||||
if (!fuzzed_properties.has_value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Select key and perform verification.
|
||||
Session* const session = license_api_fuzz.session();
|
||||
vector<uint8_t> key_handle;
|
||||
GetKeyHandleIntoVector(
|
||||
session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_properties.value.structure.cipher_mode, key_handle);
|
||||
if (OEMCrypto_Generic_Verify(key_handle.data(), key_handle.size(),
|
||||
fuzzed_properties.value.buffer.data(),
|
||||
fuzzed_properties.value.buffer.size(),
|
||||
fuzzed_properties.value.structure.algorithm,
|
||||
fuzzed_properties.value.signature.data(),
|
||||
fuzzed_properties.value.signature.size()) !=
|
||||
OEMCrypto_SUCCESS) {
|
||||
// Generate a new signature.
|
||||
size_t signature_length = 0;
|
||||
OEMCrypto_Generic_Sign(key_handle.data(), key_handle.size(),
|
||||
fuzzed_properties.value.buffer.data(),
|
||||
fuzzed_properties.value.buffer.size(),
|
||||
fuzzed_properties.value.structure.algorithm, nullptr,
|
||||
&signature_length);
|
||||
fuzzed_properties.value.signature.resize(signature_length);
|
||||
OEMCrypto_Generic_Sign(key_handle.data(), key_handle.size(),
|
||||
fuzzed_properties.value.buffer.data(),
|
||||
fuzzed_properties.value.buffer.size(),
|
||||
fuzzed_properties.value.structure.algorithm,
|
||||
fuzzed_properties.value.signature.data(),
|
||||
&signature_length);
|
||||
const size_t signature_offset = sizeof(fuzzed_properties.value.structure) +
|
||||
fuzzed_properties.value.buffer.size();
|
||||
size = signature_offset + signature_length;
|
||||
if (size > max_size) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data + signature_offset, fuzzed_properties.value.signature.data(),
|
||||
signature_length);
|
||||
}
|
||||
return LLVMFuzzerMutate(data, size, max_size);
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Deserialize fuzzed data.
|
||||
const OptionalFuzzedProperties fuzzed_properties =
|
||||
DeserializeFuzzedData(data, size);
|
||||
if (!fuzzed_properties.has_value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Select key and perform verification.
|
||||
Session* const session = license_api_fuzz.session();
|
||||
vector<uint8_t> key_handle;
|
||||
GetKeyHandleIntoVector(
|
||||
session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
fuzzed_properties.value.structure.cipher_mode, key_handle);
|
||||
OEMCrypto_Generic_Verify(key_handle.data(), key_handle.size(),
|
||||
fuzzed_properties.value.buffer.data(),
|
||||
fuzzed_properties.value.buffer.size(),
|
||||
fuzzed_properties.value.structure.algorithm,
|
||||
fuzzed_properties.value.signature.data(),
|
||||
fuzzed_properties.value.signature.size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
@@ -7,8 +12,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// reduce noise
|
||||
RedirectStdoutToFile();
|
||||
|
||||
size_t pst_buffer_length = 0;
|
||||
if (size <= sizeof(pst_buffer_length)) {
|
||||
if (size < sizeof(OEMCrypto_PrivateKeyType)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,17 +21,21 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Open a session, create a usage entry.
|
||||
Session* session = entry.license_messages().session();
|
||||
session->open();
|
||||
entry.InstallTestRSAKey(session);
|
||||
entry.InstallTestDrmKey(session);
|
||||
session->GenerateNonce();
|
||||
session->CreateNewUsageEntry();
|
||||
vector<uint8_t> encrypted_usage_header;
|
||||
std::vector<uint8_t> encrypted_usage_header;
|
||||
session->UpdateUsageEntry(&encrypted_usage_header);
|
||||
std::vector<uint8_t> wrapped_private_key(size);
|
||||
memcpy(wrapped_private_key.data(), data, size);
|
||||
OEMCrypto_PrivateKeyType key_type = OEMCrypto_RSA_Private_Key;
|
||||
OEMCrypto_InstallOemPrivateKey(session->session_id(), key_type, wrapped_private_key.data(), size);
|
||||
FuzzedDataProvider fuzzed_data(data, size);
|
||||
const OEMCrypto_PrivateKeyType key_type =
|
||||
ConvertDataToValidEnum(fuzzed_data, OEMCrypto_PrivateKeyType_MaxValue);
|
||||
const std::vector<uint8_t> wrapped_private_key =
|
||||
fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
OEMCrypto_InstallOemPrivateKey(session->session_id(), key_type,
|
||||
wrapped_private_key.data(),
|
||||
wrapped_private_key.size());
|
||||
session->close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
#include "oemcrypto_fuzz_structs.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
@@ -17,34 +15,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// message buffer with key data | entitled content key object array with
|
||||
// offsets and lengths to read key data from message buffer.
|
||||
// Split data using separator.
|
||||
auto inputs = SplitInput(data, size);
|
||||
const std::vector<FuzzedData> inputs = SplitFuzzedData(data, size);
|
||||
if (inputs.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FuzzedDataProvider fuzzed_entitled_content_key_array(inputs[1].data(),
|
||||
inputs[1].size());
|
||||
|
||||
// Message to be verified. Return 0 if key data buffer is empty.
|
||||
if (inputs[0].size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy data to OEMCrypto_EntitledContentKeyObject array.
|
||||
size_t entitled_content_key_object_size =
|
||||
sizeof(OEMCrypto_EntitledContentKeyObject);
|
||||
size_t entitled_content_key_array_length =
|
||||
fuzzed_entitled_content_key_array.remaining_bytes() /
|
||||
entitled_content_key_object_size;
|
||||
if (entitled_content_key_array_length == 0) {
|
||||
return 0;
|
||||
}
|
||||
OEMCrypto_EntitledContentKeyObject* entitled_content_key_array =
|
||||
new OEMCrypto_EntitledContentKeyObject[entitled_content_key_array_length];
|
||||
|
||||
for (size_t i = 0; i < entitled_content_key_array_length; i++) {
|
||||
fuzzed_entitled_content_key_array.ConsumeData(
|
||||
&entitled_content_key_array[i], entitled_content_key_object_size);
|
||||
std::vector<OEMCrypto_EntitledContentKeyObject> entitled_content_keys(
|
||||
inputs[1].size / sizeof(OEMCrypto_EntitledContentKeyObject));
|
||||
if (!entitled_content_keys.empty()) {
|
||||
memcpy(entitled_content_keys.data(), inputs[1].data,
|
||||
entitled_content_keys.size() *
|
||||
sizeof(OEMCrypto_EntitledContentKeyObject));
|
||||
}
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
@@ -54,13 +36,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
OEMCrypto_EntitlementLicense);
|
||||
license_api_fuzz.LoadLicense();
|
||||
// Call OEMCrypto_LoadEntitledContentKeys with fuzzed buffers.
|
||||
Session* session = license_api_fuzz.session();
|
||||
uint8_t* fuzzed_key_data = inputs[0].data();
|
||||
size_t fuzzed_key_data_size = inputs[0].size();
|
||||
const std::vector<uint8_t> message(inputs[0].data,
|
||||
inputs[0].data + inputs[0].size);
|
||||
OEMCrypto_LoadEntitledContentKeys(
|
||||
session->session_id(), fuzzed_key_data, fuzzed_key_data_size,
|
||||
entitled_content_key_array_length, entitled_content_key_array);
|
||||
delete[] entitled_content_key_array;
|
||||
license_api_fuzz.session()->session_id(), message.data(), message.size(),
|
||||
entitled_content_keys.size(), entitled_content_keys.data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -2,33 +2,50 @@
|
||||
// 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"
|
||||
|
||||
namespace wvoec {
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
|
||||
OEMCryptoResult LoadUsageEntryWithFuzzedData(OEMCrypto_SESSION session,
|
||||
const uint8_t* data, size_t size) {
|
||||
if (size < sizeof(uint32_t)) {
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
|
||||
FuzzedDataProvider fuzzed_data(data, size);
|
||||
const uint32_t usage_entry_number = fuzzed_data.ConsumeIntegral<uint32_t>();
|
||||
const std::vector<uint8_t> buffer =
|
||||
fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
return OEMCrypto_LoadUsageEntry(session, usage_entry_number, buffer.data(),
|
||||
buffer.size());
|
||||
}
|
||||
|
||||
// The custom mutator to mutate created encrypted usage entry.
|
||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||
size_t max_size, unsigned int seed) {
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
entry.CreateUsageTableHeader();
|
||||
Session* s = entry.license_messages().session();
|
||||
s->open();
|
||||
entry.InstallTestRSAKey(s);
|
||||
uint32_t usage_entry_number = 0;
|
||||
memcpy(&usage_entry_number, data, sizeof(uint32_t));
|
||||
if (OEMCrypto_LoadUsageEntry(s->session_id(), usage_entry_number,
|
||||
data + sizeof(uint32_t),
|
||||
size - sizeof(uint32_t)) != OEMCrypto_SUCCESS) {
|
||||
entry.InstallTestDrmKey(s);
|
||||
if (LoadUsageEntryWithFuzzedData(s->session_id(), data, size) !=
|
||||
OEMCrypto_SUCCESS) {
|
||||
s->CreateNewUsageEntry();
|
||||
vector<uint8_t> encrypted_usage_header;
|
||||
std::vector<uint8_t> encrypted_usage_header;
|
||||
s->UpdateUsageEntry(&encrypted_usage_header);
|
||||
vector<uint8_t> encrypted_usage_entry = s->encrypted_usage_entry();
|
||||
usage_entry_number = s->usage_entry_number();
|
||||
const uint32_t usage_entry_number = s->usage_entry_number();
|
||||
const std::vector<uint8_t>& encrypted_usage_entry =
|
||||
s->encrypted_usage_entry();
|
||||
size = sizeof(usage_entry_number) + encrypted_usage_entry.size();
|
||||
if (size > max_size) {
|
||||
return 0;
|
||||
}
|
||||
// Copy created usage entry number and usage entry to data and mutate it.
|
||||
memcpy(data, &usage_entry_number, sizeof(uint32_t));
|
||||
memcpy(data + sizeof(uint32_t), encrypted_usage_entry.data(),
|
||||
memcpy(data, &usage_entry_number, sizeof(usage_entry_number));
|
||||
memcpy(data + sizeof(usage_entry_number), encrypted_usage_entry.data(),
|
||||
encrypted_usage_entry.size());
|
||||
size = sizeof(uint32_t) + encrypted_usage_entry.size();
|
||||
}
|
||||
s->close();
|
||||
return LLVMFuzzerMutate(data, size, max_size);
|
||||
@@ -39,23 +56,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// reduce noise
|
||||
RedirectStdoutToFile();
|
||||
|
||||
uint32_t usage_entry_number = 0;
|
||||
if (size < sizeof(usage_entry_number)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&usage_entry_number, data, sizeof(usage_entry_number));
|
||||
const uint8_t* extra_data = data + sizeof(usage_entry_number);
|
||||
size_t extra_data_size = size - sizeof(usage_entry_number);
|
||||
if (extra_data_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Session s;
|
||||
s.open();
|
||||
OEMCrypto_LoadUsageEntry(s.session_id(), usage_entry_number, extra_data,
|
||||
extra_data_size);
|
||||
LoadUsageEntryWithFuzzedData(s.session_id(), data, size);
|
||||
s.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -13,13 +13,13 @@ extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
if (OEMCrypto_LoadUsageTableHeader(data, size) != OEMCrypto_SUCCESS) {
|
||||
entry.CreateUsageTableHeader();
|
||||
if (size < entry.encrypted_usage_header().size()) {
|
||||
size = entry.encrypted_usage_header().size();
|
||||
if (size > max_size) {
|
||||
return 0;
|
||||
}
|
||||
// Copy created usage table header to data and mutate it.
|
||||
memcpy(data, entry.encrypted_usage_header().data(),
|
||||
entry.encrypted_usage_header().size());
|
||||
size = entry.encrypted_usage_header().size();
|
||||
}
|
||||
return LLVMFuzzerMutate(data, size, max_size);
|
||||
}
|
||||
@@ -33,4 +33,5 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
OEMCrypto_LoadUsageTableHeader(data, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -20,14 +20,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
entry.CreateUsageTableHeader();
|
||||
Session* s = entry.license_messages().session();
|
||||
s->open();
|
||||
entry.InstallTestRSAKey(s);
|
||||
entry.InstallTestDrmKey(s);
|
||||
memcpy(&usage_entry_number, data, sizeof(uint32_t));
|
||||
s->CreateNewUsageEntry();
|
||||
vector<uint8_t> encrypted_usage_header;
|
||||
s->UpdateUsageEntry(&encrypted_usage_header);
|
||||
OEMCrypto_MoveEntry(s->session_id(), usage_entry_number);
|
||||
s ->close();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -1,40 +1,38 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include "opk_dispatcher.h"
|
||||
#include "opk_init.h"
|
||||
#include "tos_transport_interface.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
void OpenOEMCryptoTASession() {
|
||||
ODK_Message request;
|
||||
ODK_Message response;
|
||||
uint8_t response_buffer[0x1000];
|
||||
uint8_t request_body[] = {
|
||||
0x06, // TAG_UINT32
|
||||
0x09, 0x00, 0x00, 0x00, // API value (0x09)
|
||||
0x01, // TAG_BOOL
|
||||
0x00, // value (false)
|
||||
0x0a // TAG_EOM
|
||||
0x06, // TAG_UINT32
|
||||
0x09, 0x00, 0x00, 0x00, // API value (0x09)
|
||||
0x07, // TAG_UINT64
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||
0x01, // TAG_BOOL
|
||||
0x00, // value (false)
|
||||
0x0a // TAG_EOM
|
||||
};
|
||||
request = ODK_Message_Create(request_body, sizeof(request_body));
|
||||
ODK_Message request = ODK_Message_Create(request_body, sizeof(request_body));
|
||||
ODK_Message_SetSize(&request, sizeof(request_body));
|
||||
ODK_Message response;
|
||||
OPK_DispatchMessage(&request, &response);
|
||||
}
|
||||
|
||||
void InitializeOEMCryptoTA() {
|
||||
ODK_Message init_request;
|
||||
ODK_Message init_response;
|
||||
uint8_t response_buffer[0x1000];
|
||||
uint8_t init_request_body[] = {
|
||||
0x06, // TAG_UINT32
|
||||
0x01, 0x00, 0x00, 0x00, // API value(0x01)
|
||||
0x0a // TAG_EOM
|
||||
uint8_t request_body[] = {
|
||||
0x06, // TAG_UINT32
|
||||
0x01, 0x00, 0x00, 0x00, // API value (0x01)
|
||||
0x07, // TAG_UINT64
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||
0x0a // TAG_EOM
|
||||
};
|
||||
|
||||
init_request =
|
||||
ODK_Message_Create(init_request_body, sizeof(init_request_body));
|
||||
OPK_DispatchMessage(&init_request, &init_response);
|
||||
ODK_Message request = ODK_Message_Create(request_body, sizeof(request_body));
|
||||
ODK_Message_SetSize(&request, sizeof(request_body));
|
||||
ODK_Message response;
|
||||
OPK_DispatchMessage(&request, &response);
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||
@@ -45,17 +43,12 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
ODK_Message request;
|
||||
std::vector<uint8_t> request_body(data, data + size);
|
||||
ODK_Message request =
|
||||
ODK_Message_Create(request_body.data(), request_body.size());
|
||||
ODK_Message_SetSize(&request, request_body.size());
|
||||
ODK_Message response;
|
||||
unsigned char response_buffer[0x1000];
|
||||
|
||||
uint8_t* input = new uint8_t[size];
|
||||
memcpy(input, data, size);
|
||||
|
||||
request = ODK_Message_Create(input, size);
|
||||
OPK_DispatchMessage(&request, &response);
|
||||
|
||||
delete[] input;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
@@ -11,8 +12,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// reduce noise
|
||||
RedirectStdoutToFile();
|
||||
|
||||
size_t pst_buffer_length = 0;
|
||||
if (size <= sizeof(pst_buffer_length)) {
|
||||
if (size < sizeof(size_t)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Open a session, create a usage entry.
|
||||
Session* session = entry.license_messages().session();
|
||||
session->open();
|
||||
entry.InstallTestRSAKey(session);
|
||||
entry.InstallTestDrmKey(session);
|
||||
session->CreateNewUsageEntry();
|
||||
session->GenerateNonce();
|
||||
vector<uint8_t> encrypted_usage_header;
|
||||
@@ -29,17 +29,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// Sets pst for usage entry.
|
||||
entry.LoadLicense();
|
||||
|
||||
memcpy(&pst_buffer_length, data, sizeof(pst_buffer_length));
|
||||
const uint8_t* extra_data = data + sizeof(pst_buffer_length);
|
||||
size_t extra_data_size = size - sizeof(pst_buffer_length);
|
||||
// We cannot allocate a huge buffer, hence limiting buffer size to
|
||||
// MAX_FUZZ_PST_REPORT_BUFFER_LENGTH.
|
||||
pst_buffer_length =
|
||||
std::min(MAX_FUZZ_PST_REPORT_BUFFER_LENGTH, pst_buffer_length);
|
||||
vector<uint8_t> pst_report_buffer(pst_buffer_length);
|
||||
FuzzedDataProvider fuzzed_data(data, size);
|
||||
size_t pst_report_buffer_length = fuzzed_data.ConsumeIntegralInRange<size_t>(
|
||||
0, MAX_FUZZ_PST_REPORT_BUFFER_LENGTH);
|
||||
const std::vector<uint8_t> pst = fuzzed_data.ConsumeRemainingBytes<uint8_t>();
|
||||
std::vector<uint8_t> pst_report_buffer(pst_report_buffer_length);
|
||||
// Call API with fuzzed pst_buffer_length, pst.
|
||||
OEMCrypto_ReportUsage(session->session_id(), extra_data, extra_data_size,
|
||||
pst_report_buffer.data(), &pst_buffer_length);
|
||||
OEMCrypto_ReportUsage(session->session_id(), pst.data(), pst.size(),
|
||||
pst_report_buffer.data(), &pst_report_buffer_length);
|
||||
session->close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
entry.CreateUsageTableHeader();
|
||||
Session* s = entry.license_messages().session();
|
||||
s->open();
|
||||
entry.InstallTestRSAKey(s);
|
||||
entry.InstallTestDrmKey(s);
|
||||
s->CreateNewUsageEntry();
|
||||
s->close();
|
||||
s->open();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "FuzzedDataProvider.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
@@ -11,15 +12,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
// reduce noise
|
||||
RedirectStdoutToFile();
|
||||
|
||||
if (size < sizeof(uint32_t)) {
|
||||
if (size < sizeof(uint32_t) + sizeof(size_t)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
uint32_t new_entry_count = 0;
|
||||
memcpy(&new_entry_count, data, sizeof(uint32_t));
|
||||
std::vector<uint8_t> header_buffer(size - sizeof(uint32_t));
|
||||
size_t header_buffer_length = header_buffer.size();
|
||||
entry.CreateUsageTableHeader();
|
||||
FuzzedDataProvider fuzzed_data(data, size);
|
||||
const uint32_t new_entry_count = fuzzed_data.ConsumeIntegral<uint32_t>();
|
||||
size_t header_buffer_length =
|
||||
fuzzed_data.ConsumeIntegralInRange<size_t>(0, MAX_FUZZ_OUTPUT_LENGTH);
|
||||
std::vector<uint8_t> header_buffer(header_buffer_length);
|
||||
OEMCrypto_ShrinkUsageTableHeader(new_entry_count, header_buffer.data(),
|
||||
&header_buffer_length);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user