diff options
author | Allen Webb <allenwebb@google.com> | 2018-08-21 12:11:38 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-12-03 12:43:22 -0800 |
commit | a5e1a639e55d1c6382b4d690c6b78f6f85e8fbc9 (patch) | |
tree | 04ea72cd9750bc6b3e792550f7fd9515186a3636 /fuzz/cr50_fuzz.cc | |
parent | b343c963b38b03df97a1bc57f201e26640c89e47 (diff) | |
download | chrome-ec-a5e1a639e55d1c6382b4d690c6b78f6f85e8fbc9.tar.gz |
cr50_fuzz: Add libprotobuf-mutator support.
This uses protocol buffers to model what actions can be taken with
pinweaver at a higher level of abstraction than the raw requests to
greatly increase the coverage that can be achieved by fuzzing, while
still allowing for invalid inputs to be checked.
BRANCH=none
BUG=chromium:876582
TEST=sudo emerge libprotobuf-mutator &&
make -j buildfuzztests && ./build/host/cr50_fuzz/cr50_fuzz.exe
Change-Id: Ie7ce569650ca06866f277f36eae61df2684de60c
Signed-off-by: Allen Webb <allenwebb@google.com>
Reviewed-on: https://chromium-review.googlesource.com/1184107
Reviewed-by: Mattias Nissler <mnissler@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Diffstat (limited to 'fuzz/cr50_fuzz.cc')
-rw-r--r-- | fuzz/cr50_fuzz.cc | 135 |
1 files changed, 77 insertions, 58 deletions
diff --git a/fuzz/cr50_fuzz.cc b/fuzz/cr50_fuzz.cc index 90b8350fc2..dcd80e93e9 100644 --- a/fuzz/cr50_fuzz.cc +++ b/fuzz/cr50_fuzz.cc @@ -1,78 +1,97 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Fuzzer for the TPM2 and vendor specific Cr50 commands. - */ +// Copyright 2018 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Fuzzer for the TPM2 and vendor specific Cr50 commands. #include <unistd.h> #include <cstdint> -#include <cstdlib> #include <cstring> +#include <unordered_map> +#include <vector> + +#include <src/libfuzzer/libfuzzer_macro.h> +#include <src/mutator.h> #define HIDE_EC_STDLIB -#include "fuzz_config.h" -#include "nvmem.h" -#include "nvmem_vars.h" -#include "persistence.h" -#include "pinweaver.h" - -#define NVMEM_TPM_SIZE ((sizeof((struct nvmem_partition *)0)->buffer) \ - - NVMEM_CR50_SIZE) - -extern "C" uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = { - NVMEM_TPM_SIZE, - NVMEM_CR50_SIZE -}; - -extern "C" void rand_bytes(void *buffer, size_t len) -{ - size_t x = 0; - - for (; x < len; ++x) - ((uint8_t *)buffer)[x] = rand(); +#include "chip/host/persistence.h" +#include "fuzz/cr50_fuzz.pb.h" +#include "fuzz/fuzz_config.h" +#include "fuzz/pinweaver_model.h" +#include "fuzz/span.h" +#include "include/nvmem.h" +#include "include/nvmem_vars.h" +#include "include/pinweaver.h" + +using protobuf_mutator::libfuzzer::LoadProtoInput; + +namespace { +constexpr size_t kBufferAlignment = alignof(pw_request_t) > + alignof(pw_response_t) + ? alignof(pw_request_t) + : alignof(pw_response_t); +} // namespace + +extern "C" uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {NVMEM_TPM_SIZE, + NVMEM_CR50_SIZE}; + +extern "C" void rand_bytes(void* data, size_t len) { + size_t x = 0; + + uint8_t* buffer = reinterpret_cast<uint8_t*>(data); + for (; x < len; ++x) { + buffer[x] = rand(); + } } -extern "C" void get_storage_seed(void *buf, size_t *len) -{ - memset(buf, 0x77, *len); +extern "C" void get_storage_seed(void* buf, size_t* len) { + memset(buf, 0x77, *len); } extern "C" uint8_t get_current_pcr_digest(const uint8_t bitmask[2], - uint8_t sha256_of_selected_pcr[32]) -{ - memset(sha256_of_selected_pcr, 0, 32); - return 0; + uint8_t sha256_of_selected_pcr[32]) { + memset(sha256_of_selected_pcr, 0, 32); + return 0; } -extern "C" void run_test(void) -{ -} +// Needed for test targets to build. +extern "C" void run_test(void) {} -static void assign_pw_field_from_bytes(const uint8_t *data, unsigned int size, - uint8_t *destination, size_t dest_size) -{ - if (size >= dest_size) { - memcpy(destination, data, dest_size); - } else { - memcpy(destination, data, size); - memset(destination + size, 0, dest_size - size); - } +void InitializeFuzzerRun() { + memset(__host_flash, 0xff, sizeof(__host_flash)); + nvmem_init(); + nvmem_enable_commits(); + initvars(); + srand(0); } -/* Prevent this from being stack allocated. */ -static uint8_t tpm_io_buffer[PW_MAX_MESSAGE_SIZE]; +DEFINE_CUSTOM_PROTO_MUTATOR_IMPL(false, fuzz::Cr50FuzzerInput) +DEFINE_CUSTOM_PROTO_CROSSOVER_IMPL(false, fuzz::Cr50FuzzerInput) + +extern "C" int test_fuzz_one_input(const uint8_t* data, unsigned int size) { + fuzz::Cr50FuzzerInput input; + if (!LoadProtoInput(false, data, size, &input)) { + return 0; + } -extern "C" int test_fuzz_one_input(const uint8_t *data, unsigned int size) -{ - struct merkle_tree_t merkle_tree = {}; - struct pw_request_t *request = (struct pw_request_t *)tpm_io_buffer; - struct pw_response_t *response = (struct pw_response_t *)tpm_io_buffer; + InitializeFuzzerRun(); - memset(__host_flash, 0xff, sizeof(__host_flash)); - pinweaver_init(); - assign_pw_field_from_bytes(data, size, tpm_io_buffer, sizeof(tpm_io_buffer)); - pw_handle_request(&merkle_tree, request, response); - return 0; + PinweaverModel pinweaver_model; + alignas(kBufferAlignment) uint8_t buffer[PW_MAX_MESSAGE_SIZE] = {}; + fuzz::span<uint8_t> buffer_view(buffer, sizeof(buffer)); + for (const fuzz::Cr50SubAction& action : input.sub_actions()) { + switch (action.sub_action_case()) { + case fuzz::Cr50SubAction::kRandomBytes: + fuzz::CopyWithPadding(action.random_bytes().value(), buffer_view, 0); + pinweaver_model.SendBuffer(buffer_view); + break; + case fuzz::Cr50SubAction::kPinweaver: + pinweaver_model.ApplyRequest(action.pinweaver(), buffer_view); + break; + case fuzz::Cr50SubAction::SUB_ACTION_NOT_SET: + break; + } + } + return 0; } |