summaryrefslogtreecommitdiff
path: root/fuzz/pinweaver_fuzz.cc
diff options
context:
space:
mode:
Diffstat (limited to 'fuzz/pinweaver_fuzz.cc')
-rw-r--r--fuzz/pinweaver_fuzz.cc148
1 files changed, 148 insertions, 0 deletions
diff --git a/fuzz/pinweaver_fuzz.cc b/fuzz/pinweaver_fuzz.cc
new file mode 100644
index 0000000000..853c4341fc
--- /dev/null
+++ b/fuzz/pinweaver_fuzz.cc
@@ -0,0 +1,148 @@
+// 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 Cr50 commands related to Pinweaver.
+
+#include <unistd.h>
+
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <unordered_map>
+#include <vector>
+
+#include <src/libfuzzer/libfuzzer_macro.h>
+#include <src/mutator.h>
+
+#define HIDE_EC_STDLIB
+#include "chip/host/persistence.h"
+#include "fuzz/pinweaver_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" 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;
+}
+
+extern "C" int DCRYPTO_ladder_is_enabled(void) {
+ return 1;
+}
+
+extern "C" void nvmem_wipe_cache(void) {
+ // Nothing to do since there is no cache in this implementation.
+}
+
+// Needed for test targets to build.
+extern "C" void run_test(void) {}
+
+void InitializeFuzzerRun() {
+ memset(__host_flash, 0xff, sizeof(__host_flash));
+ nvmem_init();
+ nvmem_enable_commits();
+ srand(0);
+}
+
+// Used to verify the model hasn't become out of sync with the implementation.
+// The usefulness of this fuzzer comes from its ability to reach all the code
+// paths.
+bool SelfTest() {
+ InitializeFuzzerRun();
+
+ PinweaverModel pinweaver_model;
+ alignas(kBufferAlignment) uint8_t buffer[PW_MAX_MESSAGE_SIZE] = {};
+ fuzz::span<uint8_t> buffer_view(buffer, sizeof(buffer));
+ fuzz::pinweaver::Request request;
+
+ fuzz::pinweaver::ResetTree* reset_tree = request.mutable_reset_tree();
+ reset_tree->set_height(2);
+ reset_tree->set_bits_per_level(2);
+ assert(pinweaver_model.ApplyRequest(request, buffer_view) == EC_SUCCESS);
+
+ fuzz::pinweaver::InsertLeaf* insert_leaf = request.mutable_insert_leaf();
+ constexpr char delay_schedule[] = "\000\000\000\005\377\377\377\377";
+ insert_leaf->mutable_delay_schedule()->assign(
+ delay_schedule, delay_schedule + sizeof(delay_schedule));
+ assert(pinweaver_model.ApplyRequest(request, buffer_view) == EC_SUCCESS);
+
+ request.mutable_try_auth();
+ assert(pinweaver_model.ApplyRequest(request, buffer_view) == EC_SUCCESS);
+
+ request.mutable_get_log();
+ assert(pinweaver_model.ApplyRequest(request, buffer_view) == EC_SUCCESS);
+
+ request.mutable_log_replay();
+ assert(pinweaver_model.ApplyRequest(request, buffer_view) == EC_SUCCESS);
+
+ request.mutable_reset_auth();
+ assert(pinweaver_model.ApplyRequest(request, buffer_view) == EC_SUCCESS);
+
+ request.mutable_remove_leaf();
+ assert(pinweaver_model.ApplyRequest(request, buffer_view) == EC_SUCCESS);
+
+ return true;
+}
+
+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) {
+ static bool initialized = SelfTest();
+ assert(initialized);
+
+ fuzz::Cr50FuzzerInput input;
+ if (!LoadProtoInput(false, data, size, &input)) {
+ return 0;
+ }
+
+ InitializeFuzzerRun();
+
+ 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;
+}