Update fuzz tests
Several updates to fuzz tests, including http://go/wvgerrit/124043 Add documentation for partners to run fuzzing http://go/wvgerrit/128224 Fix generic verify fuzz script http://go/wvgerrit/120507 Fuzzing: Add fuzzer for reportusage API http://go/wvgerrit/120503 Fuzzing: Add fuzzer for deactivate usageentry API http://go/wvgerrit/120463 Fuzzing: Add logic to exit fuzzer script http://go/wvgerrit/120444 Fuzzing: Add fuzzer for loadusageentry API Bug: 183154879 Bug: 202994773 Bug: 186785830 Test: test only code Change-Id: I877681461824c51bc82f0766a9973378aafadba7
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# OEMCRYPTO Fuzzing
|
||||
|
||||
Refer to [Setting up Clusterfuzz](build_clusterfuzz.md) if you are interested
|
||||
in setting up a local instance of cluster fuzz to run fuzzing on your own
|
||||
OEMCrypto implementations on linux.
|
||||
|
||||
## Objective
|
||||
|
||||
* Run fuzzing on OEMCrypto public APIs on linux using google supported
|
||||
@@ -76,13 +80,31 @@
|
||||
$ export PATH_TO_CDM_DIR=..
|
||||
$ gyp --format=ninja --depth=$(pwd) oemcrypto/oemcrypto_unittests.gyp
|
||||
$ ninja -C out/Default/
|
||||
$ ./out/Default/oemcrypto_unittests --generate_corpus
|
||||
$ mkdir oemcrypto/test/fuzz_tests/corpus/<fuzzername>_seed_corpus
|
||||
# Generate corpus by excluding buffer overflow tests.
|
||||
$ ./out/Default/oemcrypto_unittests --generate_corpus \
|
||||
--gtest_filter=-"*Huge*"
|
||||
```
|
||||
|
||||
* To avoid uploading huge binary files to git repository, the corpus files
|
||||
will be saved in fuzzername_seed_corpus.zip format in blockbuster project's
|
||||
oemcrypto_fuzzing_corpus GCS bucket using gsutil. If you need permissions
|
||||
for blockbuster project, contact widevine-engprod@google.com.
|
||||
* There can be lot of duplicate corpus files that are generated from unit
|
||||
tests. We can minimize the corpus files to only a subset of files that
|
||||
cover unique paths within the API when run using fuzzer. Run following
|
||||
command to minimize corpus.
|
||||
|
||||
```shell
|
||||
$ cd /path/to/cdm/repo
|
||||
# build fuzzer binaries
|
||||
$ ./oemcrypto/test/fuzz_tests/build_oemcrypto_fuzztests
|
||||
$ mkdir /tmp/minimized_corpus
|
||||
# minimize corpus
|
||||
$ ./out/Default/<fuzz_target_binary> -merge=1 /tmp/minimized_corpus \
|
||||
<FULL_CORPUS_DIR>
|
||||
```
|
||||
|
||||
* To avoid uploading huge binary files to git repository, the minimized corpus
|
||||
files will be saved in fuzzername_seed_corpus.zip format in blockbuster
|
||||
project's oemcrypto_fuzzing_corpus GCS bucket using gsutil. If you need
|
||||
permissions for blockbuster project, contact widevine-engprod@google.com.
|
||||
|
||||
```shell
|
||||
$ gsutil cp gs://oemcrypto_fuzzing_corpus/<fuzzername_seed_corpus.zip> \
|
||||
@@ -106,7 +128,7 @@
|
||||
|
||||
* Build and test fuzz scripts locally using following commands. The build
|
||||
script builds fuzz binaries for both oemcrypto reference implementation
|
||||
as well as odkitee implementation.
|
||||
as well as opk implementation.
|
||||
|
||||
```shell
|
||||
$ cd PATH_TO_CDM_DIR
|
||||
|
||||
174
libwvdrmengine/oemcrypto/test/fuzz_tests/build_clusterfuzz.md
Normal file
174
libwvdrmengine/oemcrypto/test/fuzz_tests/build_clusterfuzz.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# OEMCRYPTO Fuzzing - Build clustefuzz and run fuzzing
|
||||
|
||||
## Objective
|
||||
|
||||
* Run fuzzing on OEMCrypto public APIs on linux by building open sourced
|
||||
clusterfuzz source code in order to find security vulnerabilities.
|
||||
|
||||
[Clusterfuzz][1]
|
||||
|
||||
* Partners who implement OEMCrypto can follow these instructions to build
|
||||
clusterfuzz, the fuzzing framework and run fuzzing using fuzzer scripts
|
||||
provided by the Widevine team at Google.
|
||||
|
||||
## Glossary
|
||||
|
||||
* Fuzzing - Fuzzing is a methodology where random, interesting, unexpected
|
||||
inputs are fed to APIs in order to crash those, thereby catching any
|
||||
security vulnerabilities with the code.
|
||||
|
||||
* Fuzzing engines - [libfuzzer][4], afl, honggfuzz are the actual fuzzing
|
||||
engines that get the coverage information from API, use that to generate
|
||||
more interesting inputs which can be passed to fuzzer.
|
||||
|
||||
* Seed corpus - Fuzzing engine trying to generate interesting inputs from an
|
||||
empty file is not efficient. Seed corpus is the initial input that a fuzzer
|
||||
can accept and call the API with that. Fuzzing engine can then mutate this
|
||||
seed corpus to generate more inputs to fuzzer.
|
||||
|
||||
* Clusterfuzz - ClusterFuzz is a scalable fuzzing infrastructure that finds
|
||||
security and stability issues in software. Google uses ClusterFuzz to fuzz
|
||||
all Google products. Clusterfuzz provides us with the capability, tools to
|
||||
upload fuzz binaries and make use of the fuzzing engines to run fuzzing,
|
||||
find crashes and organizes the information. Clusterfuzz framework is open
|
||||
sourced, the source code can be downloaded and framework can be built
|
||||
locally or by using google cloud.
|
||||
|
||||
* Fuzzing output - Fuzzing is used to pass random inputs to API in order to
|
||||
ensure that API is crash resistant. We are not testing functionality via
|
||||
fuzzing. Fuzz scripts run continuously until they find a crash with the API
|
||||
under test.
|
||||
|
||||
## Building fuzz scripts
|
||||
|
||||
This section outlines the steps to build fuzz binaries that can be run
|
||||
continuously using clusterfuzz.
|
||||
|
||||
> **Note:** All the directories mentioned below are relative to cdm repository
|
||||
> root directory.
|
||||
|
||||
1. Fuzz scripts for OEMCrypto APIs are provided by the Widevine team at Google
|
||||
located under `oemcrypto/test/fuzz_tests` directory.
|
||||
|
||||
> **Note:** Prerequisites to run the following step are [here][10]. We also need
|
||||
> to install ninja.
|
||||
|
||||
2. Build a static library of your OEMCrypto implementation.
|
||||
* Compile and link your OEMCrypto implementation source with
|
||||
`-fsanitize=address,fuzzer` flag as per these [instructions][9] when
|
||||
building a static library.
|
||||
|
||||
* Run `./oemcrypto/test/fuzz_tests/build_partner_oemcrypto_fuzztests
|
||||
<oemcrypto_static_library_path>` script from cdm repository root
|
||||
directory.
|
||||
|
||||
* This will generate fuzz binaries under the `out/Default` directory.
|
||||
|
||||
|
||||
|
||||
> **Note:** Alternatively, you can use your own build systems, for which you
|
||||
> will need to define your own build files with the OEMCrypto fuzz source files
|
||||
> included. You can find the the fuzz source files in
|
||||
> `oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gyp` and
|
||||
> `oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gypi`.
|
||||
|
||||
3. Seed corpus for each fuzz script can be found under
|
||||
`oemcrypto/test/fuzz_tests/corpus` directory. Some fuzzers are simple and do
|
||||
not have seed corpus associated with them.
|
||||
|
||||
4. Create a zip file `oemcrypto_fuzzers_yyyymmddhhmmss.zip` with fuzz binaries
|
||||
and respective seed corpus zip files. Structure of a sample zip file with
|
||||
fuzzer binaries and seed corpus would look like following:
|
||||
|
||||
```
|
||||
* fuzzerA
|
||||
* fuzzerA_seed_corpus.zip
|
||||
* fuzzerB
|
||||
* fuzzerB_seed_corpus.zip
|
||||
* fuzzerC (fuzzerC doesn't have seed corpus associated with it)
|
||||
```
|
||||
|
||||
## Building clusterfuzz
|
||||
|
||||
* OEMCrypto implementation can be fuzzed by building clusterfuzz code which is
|
||||
open sourced and using it to run fuzzing. Use a Linux VM to build
|
||||
clusterfuzz.
|
||||
|
||||
> **Note:** You may see some issues with python modules missing, please install
|
||||
> those modules if you see errors. If you have multiple versions of python on
|
||||
> the VM, then use `python<version> -m pipenv shell` when you are at [this][3]
|
||||
> step.
|
||||
|
||||
* Follow these [instructions][2] in order to download clusterfuzz repository,
|
||||
build it locally or create a continuous fuzz infrastructure setup using
|
||||
google cloud.
|
||||
|
||||
## Running fuzzers on local clusterfuzz instance
|
||||
|
||||
* If you prefer to run fuzzing on a local machine instead of having a
|
||||
production setup using google cloud, then follow these [instructions][6] to
|
||||
add a job to the local clusterfuzz instance.
|
||||
|
||||
> **Note:** Job name should have a fuzzing engine and sanitizer as part of it. A
|
||||
> libfuzzer and asan jobs should have libfuzzer_asan in the job name.
|
||||
|
||||
* Create a job e:g:`libfuzzer_asan_oemcrypto` and upload previously created
|
||||
`oemcrypto_fuzzers_yyyymmddhhmmss.zip` as a custom build. Future uploads of
|
||||
zip file should have a name greater than current name. Following the above
|
||||
naming standard will ensure zip file names are always in ascending order.
|
||||
|
||||
* Once the job is added and clusterfuzz bot is running, fuzzing should be up
|
||||
and running. Results can be monitored as mentioned [here][6].
|
||||
|
||||
* On a local clusterfuzz instance, only one fuzzer is being fuzzed at a time.
|
||||
|
||||
> **Note:** Fuzzing is time consuming. Finding issues as well as clusterfuzz
|
||||
> regressing and fixing the issues can take time. We need fuzzing to run at
|
||||
> least for a couple of weeks to have good coverage.
|
||||
|
||||
## Finding fuzz crashes
|
||||
|
||||
Once the clusterfuzz finds an issue, it logs crash information such as the
|
||||
build, test case and stack trace for the crash.
|
||||
|
||||
* Test cases tab should show the fuzz crash and test case that caused the
|
||||
crash. Run `./fuzz_binary <test_case>` in order to debug the crash locally.
|
||||
|
||||
More information about different types of logs is as below:
|
||||
|
||||
* [Bot logs][7] will show information related to fuzzing, number of crashes
|
||||
that a particular fuzzer finds, number of new crashes, number of known
|
||||
crashes etc.
|
||||
|
||||
* [Local GCS][8] in your clusterfuzz checkout folder will store the fuzz
|
||||
binaries that are being fuzzed, seed corpus etc.
|
||||
|
||||
* `local_gcs/test-fuzz-logs-bucket` will store information related to fuzz
|
||||
crashes if any were found by the fuzzing engine. It will store crash
|
||||
information categorized by fuzzer and by each day. It will also store test
|
||||
case that caused the crash.
|
||||
|
||||
* `/path/to/my-bot/clusterfuzz/log.txt` will have any log information from
|
||||
fuzzer script and OEMCrypto implementation.
|
||||
|
||||
## Fixing issues
|
||||
|
||||
* Once you are able to debug using the crash test case, apply fix to the
|
||||
implementation, create `oemcrypto_fuzzers_yyyymmddhhmmss.zip` with latest
|
||||
fuzz binaries.
|
||||
|
||||
* Upload the latest fuzz binary to the fuzz job that was created earlier.
|
||||
Fuzzer will recognize the fix and mark the crash as fixed in test cases tab
|
||||
once the regression finishes. You do not need to update crashes as fixed,
|
||||
clusterfuzz will do that.
|
||||
|
||||
[1]: https://google.github.io/clusterfuzz/
|
||||
[2]: https://google.github.io/clusterfuzz/getting-started/
|
||||
[3]: https://google.github.io/clusterfuzz/getting-started/prerequisites/#loading-pipenv
|
||||
[4]: https://llvm.org/docs/LibFuzzer.html
|
||||
[5]: https://google.github.io/clusterfuzz/setting-up-fuzzing/libfuzzer-and-afl/
|
||||
[6]: https://google.github.io/clusterfuzz/setting-up-fuzzing/libfuzzer-and-afl/#checking-results
|
||||
[7]: https://google.github.io/clusterfuzz/getting-started/local-instance/#viewing-logs
|
||||
[8]: https://google.github.io/clusterfuzz/getting-started/local-instance/#local-google-cloud-storage
|
||||
[9]: https://google.github.io/clusterfuzz/setting-up-fuzzing/libfuzzer-and-afl/#libfuzzer
|
||||
[10]: https://google.github.io/clusterfuzz/setting-up-fuzzing/libfuzzer-and-afl/#prerequisites
|
||||
@@ -10,10 +10,10 @@ export PYTHONPATH="$PYTHONPATH:$PATH_TO_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_odkitee_fuzztests.gypi has flags to instrument all the gyp targets
|
||||
# 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 \
|
||||
--depth=$(pwd) \
|
||||
--include=oemcrypto/test/fuzz_tests/oemcrypto_odkitee_fuzztests.gypi \
|
||||
oemcrypto/test/fuzz_tests/oemcrypto_odkitee_fuzztests.gyp
|
||||
--include=oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gypi \
|
||||
oemcrypto/test/fuzz_tests/oemcrypto_opk_fuzztests.gyp
|
||||
ninja -C out/Default
|
||||
15
libwvdrmengine/oemcrypto/test/fuzz_tests/build_partner_oemcrypto_fuzztests
Executable file
15
libwvdrmengine/oemcrypto/test/fuzz_tests/build_partner_oemcrypto_fuzztests
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# For use by partners to generate fuzz binaries for their OEMCrypto
|
||||
# implementation on linux.
|
||||
|
||||
export CXX=clang++
|
||||
export CC=clang
|
||||
export GYP_DEFINES="$GYP_DEFINES clang=1 oemcrypto_static_library=$1"
|
||||
export PATH_TO_CDM_DIR=.
|
||||
export PYTHONPATH="$PYTHONPATH:$PATH_TO_CDM_DIR/third_party"
|
||||
|
||||
python3 $PATH_TO_CDM_DIR/third_party/gyp/__init__.py --format=ninja \
|
||||
--depth=$(pwd) oemcrypto/test/fuzz_tests/partner_oemcrypto_fuzztests.gyp
|
||||
ninja -C out/Default
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,30 @@
|
||||
// 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 "oemcrypto_fuzz_helper.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();
|
||||
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
entry.CreateUsageTableHeader();
|
||||
// Open a session, create a usage entry.
|
||||
Session* session = entry.license_messages().session();
|
||||
session->open();
|
||||
entry.InstallTestRSAKey(session);
|
||||
session->GenerateNonce();
|
||||
session->CreateNewUsageEntry();
|
||||
vector<uint8_t> encrypted_usage_header;
|
||||
session->UpdateUsageEntry(&encrypted_usage_header);
|
||||
// LoadLicense sets the pst for usage entry.
|
||||
entry.LoadLicense();
|
||||
|
||||
OEMCrypto_DeactivateUsageEntry(session->session_id(), data, size);
|
||||
session->close();
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -95,7 +95,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
// Read subsamples from fuzzed data.
|
||||
vector<OEMCrypto_SubSampleDescription> subsamples;
|
||||
while (fuzzed_subsample_data.remaining_bytes() >
|
||||
while (fuzzed_subsample_data.remaining_bytes() >=
|
||||
sizeof(OEMCrypto_SubSampleDescription)) {
|
||||
OEMCrypto_SubSampleDescription subsample;
|
||||
fuzzed_subsample_data.ConsumeData(&subsample,
|
||||
@@ -138,9 +138,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
// Copy sub sample data.
|
||||
sample_descriptions[i].subsamples = &subsamples[input_subsample_index];
|
||||
if (AddOverflowUX(input_subsample_index,
|
||||
sample_descriptions[i].subsamples_length,
|
||||
&input_subsample_index)) {
|
||||
if (OPK_AddOverflowUX(input_subsample_index,
|
||||
sample_descriptions[i].subsamples_length,
|
||||
&input_subsample_index)) {
|
||||
return 0;
|
||||
}
|
||||
if (input_subsample_index > subsamples.size()) return 0;
|
||||
|
||||
@@ -22,4 +22,45 @@ std::vector<std::vector<uint8_t>> SplitInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void OEMCryptoLicenseAPIFuzz::LoadLicense() {
|
||||
license_messages_.SignAndVerifyRequest();
|
||||
license_messages_.CreateDefaultResponse();
|
||||
license_messages_.EncryptAndSignResponse();
|
||||
OEMCryptoResult sts = license_messages_.LoadResponse();
|
||||
CheckStatusAndExitFuzzerOnFailure(sts, OEMCrypto_SUCCESS);
|
||||
}
|
||||
|
||||
void OEMCryptoProvisioningAPIFuzz::LoadProvisioning() {
|
||||
provisioning_messages_.SignAndVerifyRequest();
|
||||
provisioning_messages_.CreateDefaultResponse();
|
||||
provisioning_messages_.EncryptAndSignResponse();
|
||||
OEMCryptoResult sts = provisioning_messages_.LoadResponse();
|
||||
CheckStatusAndExitFuzzerOnFailure(sts, OEMCrypto_SUCCESS);
|
||||
}
|
||||
|
||||
void LicenseWithUsageEntryFuzz::CreateUsageTableHeader() {
|
||||
size_t header_buffer_length = 0;
|
||||
OEMCryptoResult sts =
|
||||
OEMCrypto_CreateUsageTableHeader(nullptr, &header_buffer_length);
|
||||
encrypted_usage_header_.resize(header_buffer_length);
|
||||
sts = OEMCrypto_CreateUsageTableHeader(encrypted_usage_header_.data(),
|
||||
&header_buffer_length);
|
||||
CheckStatusAndExitFuzzerOnFailure(sts, OEMCrypto_SUCCESS);
|
||||
}
|
||||
|
||||
void LicenseWithUsageEntryFuzz::LoadLicense() {
|
||||
license_messages_.SignAndVerifyRequest();
|
||||
license_messages_.CreateDefaultResponse();
|
||||
license_messages_.EncryptAndSignResponse();
|
||||
OEMCryptoResult sts = license_messages_.LoadResponse();
|
||||
CheckStatusAndExitFuzzerOnFailure(sts, OEMCrypto_SUCCESS);
|
||||
}
|
||||
|
||||
void CheckStatusAndExitFuzzerOnFailure(OEMCryptoResult result,
|
||||
OEMCryptoResult expected_status) {
|
||||
if (result != expected_status) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -13,6 +13,16 @@
|
||||
#include "oemcrypto_session_tests_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
// Forward-declare the libFuzzer's mutator callback. Mark it weak so that
|
||||
// the program links successfully even outside of --config=asan-fuzzer
|
||||
// (apparently the only config in which LLVM uses our custom mutator).
|
||||
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;
|
||||
// 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.
|
||||
@@ -42,12 +52,7 @@ class OEMCryptoLicenseAPIFuzz : public InitializeFuzz {
|
||||
|
||||
Session* session() { return &session_; }
|
||||
|
||||
void LoadLicense() {
|
||||
license_messages_.SignAndVerifyRequest();
|
||||
license_messages_.CreateDefaultResponse();
|
||||
license_messages_.EncryptAndSignResponse();
|
||||
license_messages_.LoadResponse();
|
||||
}
|
||||
void LoadLicense();
|
||||
|
||||
private:
|
||||
Session session_;
|
||||
@@ -64,9 +69,11 @@ class OEMCryptoProvisioningAPIFuzz : public InitializeFuzz {
|
||||
|
||||
~OEMCryptoProvisioningAPIFuzz() { session_.close(); }
|
||||
|
||||
void LoadProvisioning();
|
||||
ProvisioningRoundTrip& provisioning_messages() {
|
||||
return provisioning_messages_;
|
||||
}
|
||||
Session* session() { return &session_; }
|
||||
|
||||
private:
|
||||
Session session_;
|
||||
@@ -85,6 +92,25 @@ class OEMCryptoRenewalAPIFuzz : public OEMCryptoLicenseAPIFuzz {
|
||||
RenewalRoundTrip renewal_messages_;
|
||||
};
|
||||
|
||||
class LicenseWithUsageEntryFuzz : public InitializeFuzz {
|
||||
public:
|
||||
LicenseWithUsageEntryFuzz() : license_messages_(&session_) {
|
||||
license_messages_.set_pst("my_pst");
|
||||
}
|
||||
|
||||
void CreateUsageTableHeader();
|
||||
LicenseRoundTrip& license_messages() { return license_messages_; }
|
||||
const vector<uint8_t>& encrypted_usage_header() {
|
||||
return encrypted_usage_header_;
|
||||
}
|
||||
void LoadLicense();
|
||||
|
||||
private:
|
||||
vector<uint8_t> encrypted_usage_header_;
|
||||
LicenseRoundTrip license_messages_;
|
||||
Session session_;
|
||||
};
|
||||
|
||||
// Convert data to valid enum value.
|
||||
template <typename T>
|
||||
void ConvertDataToValidEnum(T max_enum_value, T* t) {
|
||||
@@ -99,6 +125,10 @@ void RedirectStdoutToFile();
|
||||
|
||||
// Function to split fuzzer input using delimiter "-_^_".
|
||||
std::vector<std::vector<uint8_t>> SplitInput(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,
|
||||
OEMCryptoResult expected_status);
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // OEMCRYPTO_FUZZ_HELPER_H_
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#ifndef OEMCRYPTO_FUZZ_STRUCTS_H_
|
||||
#define OEMCRYPTO_FUZZ_STRUCTS_H_
|
||||
|
||||
#include "core_message_types.h"
|
||||
#include "odk.h"
|
||||
|
||||
namespace wvoec {
|
||||
struct OEMCrypto_Renewal_Response_Fuzz {
|
||||
// Timer limits in core license response needs to be fuzzed as load renewal
|
||||
@@ -37,6 +40,34 @@ struct OEMCrypto_Decrypt_Cenc_Fuzz {
|
||||
// Sample data and subsample data are of variable length and not included in
|
||||
// this structure.
|
||||
};
|
||||
|
||||
struct OEMCrypto_Generic_Api_Fuzz {
|
||||
// Corpus format is as below, let | be separator.
|
||||
// cipher_mode + algorithm + iv | buffer with actual data
|
||||
OEMCryptoCipherMode cipher_mode;
|
||||
OEMCrypto_Algorithm algorithm;
|
||||
// iv and buffer data are of variable length and not included in
|
||||
// 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
|
||||
RSA_Padding_Scheme padding_scheme;
|
||||
size_t signature_length;
|
||||
// input buffer data is of variable length and not included in
|
||||
// this structure.
|
||||
};
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // OEMCRYPTO_FUZZ_STRUCTS_H_
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_fuzz_helper.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_Generate_RSA_Signature_Fuzz fuzzed_structure;
|
||||
if (size <= sizeof(OEMCrypto_Generate_RSA_Signature_Fuzz)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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);
|
||||
OEMCrypto_GenerateRSASignature(
|
||||
license_api_fuzz.session()->session_id(), data + sizeof(fuzzed_structure),
|
||||
size - sizeof(fuzzed_structure), signature.data(), &signature_length,
|
||||
fuzzed_structure.padding_scheme);
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2020 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 "log.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();
|
||||
|
||||
// Split data using separator.
|
||||
auto inputs = SplitInput(data, size);
|
||||
if (inputs.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OEMCrypto_Generic_Api_Fuzz 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));
|
||||
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);
|
||||
|
||||
// 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());
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Load license and call generic_decrypt API.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCryptoResult sts = OEMCrypto_SelectKey(
|
||||
session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length, fuzzed_structure.cipher_mode);
|
||||
CheckStatusAndExitFuzzerOnFailure(sts, OEMCrypto_SUCCESS);
|
||||
OEMCrypto_Generic_Decrypt(session->session_id(), encrypted_buffer.data(),
|
||||
encrypted_buffer.size(), iv.data(),
|
||||
fuzzed_structure.algorithm, clear_buffer.data());
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2020 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 "log.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();
|
||||
|
||||
// Split data using separator.
|
||||
auto inputs = SplitInput(data, size);
|
||||
if (inputs.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OEMCrypto_Generic_Api_Fuzz 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));
|
||||
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);
|
||||
|
||||
// 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());
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Load license and call generic_encrypt API.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCryptoResult sts = OEMCrypto_SelectKey(
|
||||
session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length, fuzzed_structure.cipher_mode);
|
||||
CheckStatusAndExitFuzzerOnFailure(sts, OEMCrypto_SUCCESS);
|
||||
OEMCrypto_Generic_Encrypt(
|
||||
session->session_id(), clear_buffer.data(), clear_buffer.size(),
|
||||
iv.data(), fuzzed_structure.algorithm, encrypted_buffer.data());
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.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_Api_Fuzz fuzzed_structure;
|
||||
if (size < sizeof(fuzzed_structure)) {
|
||||
return 0;
|
||||
}
|
||||
// Copy OEMCrypto_Generic_Api_Fuzz from input data.
|
||||
memcpy(&fuzzed_structure, data, 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);
|
||||
|
||||
OEMCryptoLicenseAPIFuzz license_api_fuzz;
|
||||
Session* session = license_api_fuzz.session();
|
||||
// Load license and call generic_sign API.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCryptoResult sts = OEMCrypto_SelectKey(
|
||||
session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length, fuzzed_structure.cipher_mode);
|
||||
CheckStatusAndExitFuzzerOnFailure(sts, OEMCrypto_SUCCESS);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.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;
|
||||
}
|
||||
// Copy OEMCrypto_Generic_Verify_Fuzz from input data.
|
||||
memcpy(&fuzzed_structure, data, sizeof(fuzzed_structure));
|
||||
ConvertDataToValidEnum(OEMCrypto_CipherMode_MaxValue,
|
||||
&fuzzed_structure.cipher_mode);
|
||||
ConvertDataToValidEnum(OEMCrypto_Algorithm_MaxValue,
|
||||
&fuzzed_structure.algorithm);
|
||||
|
||||
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.
|
||||
license_api_fuzz.LoadLicense();
|
||||
OEMCrypto_SelectKey(session->session_id(), session->license().keys[0].key_id,
|
||||
session->license().keys[0].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
// 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;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -0,0 +1,61 @@
|
||||
// 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 "oemcrypto_fuzz_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
// 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) {
|
||||
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) {
|
||||
s->CreateNewUsageEntry();
|
||||
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();
|
||||
// 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(),
|
||||
encrypted_usage_entry.size());
|
||||
size = sizeof(uint32_t) + encrypted_usage_entry.size();
|
||||
}
|
||||
s->close();
|
||||
return LLVMFuzzerMutate(data, size, max_size);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
s.close();
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine
|
||||
// License Agreement.
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_fuzz_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// The custom mutator to mutate created encrypted usage table header.
|
||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
|
||||
size_t max_size, unsigned int seed) {
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
if (OEMCrypto_LoadUsageTableHeader(data, size) != OEMCrypto_SUCCESS) {
|
||||
entry.CreateUsageTableHeader();
|
||||
if (size < entry.encrypted_usage_header().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);
|
||||
}
|
||||
|
||||
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();
|
||||
// Initialize OEMCrypto and call API.
|
||||
InitializeFuzz initialize_fuzz;
|
||||
OEMCrypto_LoadUsageTableHeader(data, size);
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -1,23 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dispatcher.h"
|
||||
#include "marshaller_base.h"
|
||||
#include "transport_interface.h"
|
||||
#include "opk_dispatcher.h"
|
||||
#include "opk_init.h"
|
||||
#include "tos_transport_interface.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
void InitializeODKMessage(ODK_Message* message, uint8_t* data, size_t size) {
|
||||
ODK_Message_Impl* impl = (ODK_Message_Impl*)message;
|
||||
impl->base = data;
|
||||
impl->size = size;
|
||||
impl->capacity = size;
|
||||
impl->read_offset = 0;
|
||||
impl->status = MESSAGE_STATUS_OK;
|
||||
}
|
||||
|
||||
void OpenOEMCryptoTASession() {
|
||||
ODK_Message request;
|
||||
ODK_Message* response = NULL;
|
||||
ODK_Message response;
|
||||
uint8_t response_buffer[0x1000];
|
||||
uint8_t request_body[] = {
|
||||
0x06, // TAG_UINT32
|
||||
@@ -26,16 +18,13 @@ void OpenOEMCryptoTASession() {
|
||||
0x00, // value (false)
|
||||
0x0a // TAG_EOM
|
||||
};
|
||||
|
||||
InitializeODKMessage(&request, request_body, sizeof(request_body));
|
||||
|
||||
ODK_DispatchMessage(&request, &response);
|
||||
if (response != NULL) ODK_Transport_DeallocateMessage(response);
|
||||
request = ODK_Message_Create(request_body, sizeof(request_body));
|
||||
OPK_DispatchMessage(&request, &response);
|
||||
}
|
||||
|
||||
void InitializeOEMCryptoTA() {
|
||||
ODK_Message init_request;
|
||||
ODK_Message* init_response = NULL;
|
||||
ODK_Message init_response;
|
||||
uint8_t response_buffer[0x1000];
|
||||
uint8_t init_request_body[] = {
|
||||
0x06, // TAG_UINT32
|
||||
@@ -43,15 +32,13 @@ void InitializeOEMCryptoTA() {
|
||||
0x0a // TAG_EOM
|
||||
};
|
||||
|
||||
InitializeODKMessage(&init_request, init_request_body,
|
||||
sizeof(init_request_body));
|
||||
|
||||
ODK_DispatchMessage(&init_request, &init_response);
|
||||
if (init_response != NULL) ODK_Transport_DeallocateMessage(init_response);
|
||||
init_request =
|
||||
ODK_Message_Create(init_request_body, sizeof(init_request_body));
|
||||
OPK_DispatchMessage(&init_request, &init_response);
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||
ODK_InitializeDispatcher();
|
||||
OPK_Initialize();
|
||||
InitializeOEMCryptoTA();
|
||||
OpenOEMCryptoTASession();
|
||||
return 0;
|
||||
@@ -59,16 +46,14 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
ODK_Message request;
|
||||
ODK_Message* response = NULL;
|
||||
ODK_Message response;
|
||||
unsigned char response_buffer[0x1000];
|
||||
|
||||
uint8_t* input = new uint8_t[size];
|
||||
memcpy(input, data, size);
|
||||
|
||||
InitializeODKMessage(&request, input, size);
|
||||
|
||||
ODK_DispatchMessage(&request, &response);
|
||||
if (response != NULL) ODK_Transport_DeallocateMessage(response);
|
||||
request = ODK_Message_Create(input, size);
|
||||
OPK_DispatchMessage(&request, &response);
|
||||
|
||||
delete[] input;
|
||||
return 0;
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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 "oemcrypto_fuzz_helper.h"
|
||||
|
||||
namespace wvoec {
|
||||
const size_t MAX_FUZZ_PST_REPORT_BUFFER_LENGTH = 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 pst_buffer_length = 0;
|
||||
if (size <= sizeof(pst_buffer_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LicenseWithUsageEntryFuzz entry;
|
||||
entry.CreateUsageTableHeader();
|
||||
// Open a session, create a usage entry.
|
||||
Session* session = entry.license_messages().session();
|
||||
session->open();
|
||||
entry.InstallTestRSAKey(session);
|
||||
session->GenerateNonce();
|
||||
session->CreateNewUsageEntry();
|
||||
vector<uint8_t> encrypted_usage_header;
|
||||
session->UpdateUsageEntry(&encrypted_usage_header);
|
||||
// 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);
|
||||
// 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);
|
||||
session->close();
|
||||
return 0;
|
||||
}
|
||||
} // namespace wvoec
|
||||
@@ -205,13 +205,13 @@ void WriteDecryptCencCorpus(
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern, size_t samples_length) {
|
||||
const std::string file_name =
|
||||
GetFileName("oemcrypto_decrypt_cenc_fuzz_seed_corpus");
|
||||
// Cipher mode.
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(&cipher_mode),
|
||||
sizeof(OEMCryptoCipherMode));
|
||||
|
||||
// Pattern.
|
||||
AppendToFile(file_name, reinterpret_cast<const char*>(pattern),
|
||||
sizeof(OEMCrypto_CENCEncryptPatternDesc));
|
||||
OEMCrypto_Decrypt_Cenc_Fuzz decrypt_cenc_fuzz_struct;
|
||||
decrypt_cenc_fuzz_struct.cipher_mode = cipher_mode;
|
||||
decrypt_cenc_fuzz_struct.pattern = *pattern;
|
||||
// Cipher mode and Pattern.
|
||||
AppendToFile(file_name,
|
||||
reinterpret_cast<const char*>(&decrypt_cenc_fuzz_struct),
|
||||
sizeof(OEMCrypto_Decrypt_Cenc_Fuzz));
|
||||
|
||||
// Sample data for all samples.
|
||||
for (size_t i = 0; i < samples_length; i++) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "oemcrypto_fuzz_structs.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user