diff options
author | Namyoon Woo <namyoon@chromium.org> | 2020-02-10 16:03:09 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-02-12 05:00:31 +0000 |
commit | d4d347e52e4aa0357d246226fe74749311d9bf31 (patch) | |
tree | 652f295a3f2260684ba3be20f48127f31e41486e /fuzz | |
parent | 86db5fb0da4dc92a2dee55b6b0c0a815b4ac707b (diff) | |
download | chrome-ec-d4d347e52e4aa0357d246226fe74749311d9bf31.tar.gz |
fuzz: remove cr50 or TPM2 library related tests from fuzz and test
This patch removes cr50 or TPM2 related test cases from fuzz and
test directory, so that buildall or chromeos-ec package won't check
them. Those test cases are already moved to cr50_stab branch.
BUG=b:149243259
BRANCH=none
TEST=ran 'make buildall -j' and
'sudo 'FEATURES=test' 'PKGDIR=/build/eve/test-packages' \
-- /mnt/host/source/chromite/bin/parallel_emerge \
'--sysroot=/build/eve' '--jobs=10' chromeos-ec
Change-Id: Ie6f7c8622fe3e488758a814dc99ddf4587ffd973
Signed-off-by: Namyoon Woo <namyoon@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2047935
Reviewed-by: Allen Webb <allenwebb@google.com>
Diffstat (limited to 'fuzz')
-rw-r--r-- | fuzz/build.mk | 18 | ||||
-rw-r--r-- | fuzz/cr50_fuzz.cc | 148 | ||||
-rw-r--r-- | fuzz/cr50_fuzz.owners | 5 | ||||
-rw-r--r-- | fuzz/cr50_fuzz.proto | 31 | ||||
-rw-r--r-- | fuzz/cr50_fuzz.tasklist | 9 | ||||
-rw-r--r-- | fuzz/mem_hash_tree.cc | 130 | ||||
-rw-r--r-- | fuzz/mem_hash_tree.h | 58 | ||||
-rw-r--r-- | fuzz/nvmem_tpm2_mock.c | 229 | ||||
-rw-r--r-- | fuzz/pinweaver/pinweaver.proto | 64 | ||||
-rw-r--r-- | fuzz/pinweaver_model.cc | 474 | ||||
-rw-r--r-- | fuzz/pinweaver_model.h | 123 |
11 files changed, 1 insertions, 1288 deletions
diff --git a/fuzz/build.mk b/fuzz/build.mk index f2f23c9cf8..e1ed79b77b 100644 --- a/fuzz/build.mk +++ b/fuzz/build.mk @@ -9,7 +9,7 @@ fuzz-test-list-host = # Fuzzers should only be built for architectures that support sanitizers. ifeq ($(ARCH),amd64) -fuzz-test-list-host += cr50_fuzz host_command_fuzz usb_pd_fuzz usb_tcpm_v2_fuzz +fuzz-test-list-host += host_command_fuzz usb_pd_fuzz usb_tcpm_v2_fuzz endif # For fuzzing targets libec.a is built from the ro objects and hides functions @@ -24,22 +24,6 @@ endif # Does your object file need to link against cstdlib? # Yes -> use <obj_name>-rw # Otherwise use <obj_name>-y -cr50_fuzz-rw = cr50_fuzz.o pinweaver_model.o mem_hash_tree.o nvmem_tpm2_mock.o host_command_fuzz-y = host_command_fuzz.o usb_pd_fuzz-y = usb_pd_fuzz.o usb_tcpm_v2_fuzz-y = usb_pd_fuzz.o usb_tcpm_v2_fuzz.o ../test/fake_battery.o - -CR50_PROTO_HEADERS := $(out)/gen/fuzz/cr50_fuzz.pb.h \ - $(out)/gen/fuzz/pinweaver/pinweaver.pb.h -$(out)/RW/fuzz/pinweaver_model.o: ${CR50_PROTO_HEADERS} -$(out)/RW/fuzz/cr50_fuzz.o: ${CR50_PROTO_HEADERS} -$(out)/RW/fuzz/cr50_fuzz.o: CPPFLAGS+=${LIBPROTOBUF_MUTATOR_CFLAGS} - -TPM2_LIB_ROOT := $(CROS_WORKON_SRCROOT)/src/third_party/tpm2 -$(out)/RW/fuzz/nvmem_tpm2_mock.o: CFLAGS += -I$(TPM2_LIB_ROOT) - -$(out)/cr50_fuzz.exe: $(out)/cryptoc/libcryptoc.a \ - $(out)/gen/fuzz/cr50_fuzz.pb.o \ - $(out)/gen/fuzz/pinweaver/pinweaver.pb.o \ - -$(out)/cr50_fuzz.exe: LDFLAGS_EXTRA+=-lcrypto ${LIBPROTOBUF_MUTATOR_LDLIBS} diff --git a/fuzz/cr50_fuzz.cc b/fuzz/cr50_fuzz.cc deleted file mode 100644 index 186700f415..0000000000 --- a/fuzz/cr50_fuzz.cc +++ /dev/null @@ -1,148 +0,0 @@ -// 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 <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/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" 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; -} diff --git a/fuzz/cr50_fuzz.owners b/fuzz/cr50_fuzz.owners deleted file mode 100644 index 80e5dc1dee..0000000000 --- a/fuzz/cr50_fuzz.owners +++ /dev/null @@ -1,5 +0,0 @@ -# Emails to CC on clusterfuzz bugs for this target: -allenwebb@google.com -mnissler@google.com -rspangler@chromium.org -vbendeb@chromium.org diff --git a/fuzz/cr50_fuzz.proto b/fuzz/cr50_fuzz.proto deleted file mode 100644 index 0291eacd88..0000000000 --- a/fuzz/cr50_fuzz.proto +++ /dev/null @@ -1,31 +0,0 @@ -// 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. - -syntax = "proto3"; - -package fuzz; - -import public "fuzz/pinweaver/pinweaver.proto"; - -message RandomBytes { - bytes value = 1; -} - -message Cr50SubAction { - // Allows a logical representation of an action (PinWeaver) or a literal - // representation (RandomBytes). The logical representation fills out the - // expected values of particular fields when they are empty or not part of the - // proto so that the fuzzer can reach parts of the code without having to - // brute force an HMAC. The literal representation allows for the fuzzer to - // represent inputs that cannot be represented with the logical - // representation. - oneof sub_action { - RandomBytes random_bytes = 1; - pinweaver.Request pinweaver = 2; - } -} - -message Cr50FuzzerInput { - repeated Cr50SubAction sub_actions = 1; -} diff --git a/fuzz/cr50_fuzz.tasklist b/fuzz/cr50_fuzz.tasklist deleted file mode 100644 index 24870f2abb..0000000000 --- a/fuzz/cr50_fuzz.tasklist +++ /dev/null @@ -1,9 +0,0 @@ -/* 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. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TEST_TASK_LIST diff --git a/fuzz/mem_hash_tree.cc b/fuzz/mem_hash_tree.cc deleted file mode 100644 index 15c9de4142..0000000000 --- a/fuzz/mem_hash_tree.cc +++ /dev/null @@ -1,130 +0,0 @@ -// 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. - -#include "fuzz/mem_hash_tree.h" - -#include <algorithm> -#include <cassert> - -MemHashTree::MemHashTree() : bits_per_level_(0), height_(0) {} - -bool MemHashTree::GetLeaf(uint64_t label, fuzz::span<uint8_t> leaf_hash) const { - assert(leaf_hash.size() >= SHA256_DIGEST_SIZE); - auto itr = hash_tree_.find(MaskedLabel(label, 0)); - if (itr == hash_tree_.end()) { - std::fill(leaf_hash.begin(), leaf_hash.end(), 0); - return false; - } - - std::copy(itr->second.begin(), itr->second.end(), leaf_hash.begin()); - return true; -} - -size_t MemHashTree::GetPath(uint64_t label, - fuzz::span<uint8_t> path_hashes) const { - uint8_t fan_out = 1 << bits_per_level_; - uint8_t num_siblings = fan_out - 1; - assert(path_hashes.size() >= num_siblings * height_ * SHA256_DIGEST_SIZE); - // num_siblings and child_index_mask have the same value, but were named - // differently to help convey how they are used. - uint64_t child_index_mask = fan_out - 1; - uint64_t shifted_parent_label = label; - uint8_t* dest_itr = path_hashes.begin(); - for (uint8_t level = 0; level < height_; ++level) { - uint8_t label_index = shifted_parent_label & child_index_mask; - shifted_parent_label &= ~child_index_mask; - for (uint8_t index = 0; index < fan_out; ++index) { - // Only include hashes for sibling nodes. - if (index == label_index) { - continue; - } - auto src_itr = - hash_tree_.find(MaskedLabel(shifted_parent_label | index, level)); - if (src_itr == hash_tree_.end()) { - std::copy(empty_node_hashes_[level].begin(), - empty_node_hashes_[level].end(), dest_itr); - } else { - std::copy(src_itr->second.begin(), src_itr->second.end(), dest_itr); - } - dest_itr += SHA256_DIGEST_SIZE; - } - shifted_parent_label = shifted_parent_label >> bits_per_level_; - } - return dest_itr - path_hashes.begin(); -} - -void MemHashTree::UpdatePath(uint64_t label, - fuzz::span<const uint8_t> path_hash) { - std::array<uint8_t, SHA256_DIGEST_SIZE> hash; - if (path_hash.empty()) { - std::fill(hash.begin(), hash.end(), 0); - hash_tree_.erase(MaskedLabel(label, 0)); - } else { - assert(path_hash.size() == SHA256_DIGEST_SIZE); - std::copy(path_hash.begin(), path_hash.end(), hash.begin()); - hash_tree_[MaskedLabel(label, 0)] = hash; - } - - uint8_t fan_out = 1 << bits_per_level_; - uint64_t child_index_mask = fan_out - 1; - uint64_t shifted_parent_label = label; - for (int level = 0; level < height_; ++level) { - shifted_parent_label &= ~child_index_mask; - - LITE_SHA256_CTX ctx; - DCRYPTO_SHA256_init(&ctx, 1); - int empty_nodes = 0; - for (int index = 0; index < fan_out; ++index) { - auto itr = - hash_tree_.find(MaskedLabel(shifted_parent_label | index, level)); - if (itr == hash_tree_.end()) { - HASH_update(&ctx, empty_node_hashes_[level].data(), - empty_node_hashes_[level].size()); - ++empty_nodes; - } else { - HASH_update(&ctx, itr->second.data(), itr->second.size()); - } - } - shifted_parent_label = shifted_parent_label >> bits_per_level_; - - const uint8_t* temp = HASH_final(&ctx); - std::copy(temp, temp + SHA256_DIGEST_SIZE, hash.begin()); - MaskedLabel node_key(shifted_parent_label, level + 1); - if (empty_nodes == fan_out) { - hash_tree_.erase(node_key); - } else { - hash_tree_[node_key] = hash; - } - } -} - -void MemHashTree::Reset() { - bits_per_level_ = 0; - height_ = 0; - empty_node_hashes_.clear(); - hash_tree_.clear(); -} - -void MemHashTree::Reset(uint8_t bits_per_level, uint8_t height) { - bits_per_level_ = bits_per_level; - height_ = height; - hash_tree_.clear(); - empty_node_hashes_.resize(height); - - std::array<uint8_t, SHA256_DIGEST_SIZE> hash; - std::fill(hash.begin(), hash.end(), 0); - empty_node_hashes_[0] = hash; - - uint8_t fan_out = 1 << bits_per_level; - for (int level = 1; level < height; ++level) { - LITE_SHA256_CTX ctx; - DCRYPTO_SHA256_init(&ctx, 1); - for (int index = 0; index < fan_out; ++index) { - HASH_update(&ctx, hash.data(), hash.size()); - } - const uint8_t* temp = HASH_final(&ctx); - std::copy(temp, temp + SHA256_DIGEST_SIZE, hash.begin()); - empty_node_hashes_[level] = hash; - } -} diff --git a/fuzz/mem_hash_tree.h b/fuzz/mem_hash_tree.h deleted file mode 100644 index 34f4a40f9a..0000000000 --- a/fuzz/mem_hash_tree.h +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -#ifndef __FUZZ_MEM_HASH_TREE_H -#define __FUZZ_MEM_HASH_TREE_H -#include <unistd.h> - -#include <array> -#include <cstdint> -#include <unordered_map> -#include <vector> - -#define HIDE_EC_STDLIB -#include "board/host/dcrypto.h" -#include "fuzz/span.h" - -// MaskedLabel.first is the label path, this is shifted to the right by the -// (bits_per_level * level) -// MaskedLabel.second is the level of the label (0 for leaf, height for root) -typedef std::pair<uint64_t, uint8_t> MaskedLabel; - -namespace std { -template <> -struct hash<MaskedLabel> { - size_t operator()(const MaskedLabel& lbl) const { - static const auto hash_first = hash<uint64_t>(); - static const auto hash_second = hash<uint8_t>(); - return hash_first(lbl.first) * hash_second(lbl.second); - } -}; -} // namespace std - -class MemHashTree { - public: - MemHashTree(); - - bool GetLeaf(uint64_t label, fuzz::span<uint8_t> leaf_hash) const; - // Writes the result to |path_hashes| and returns the size in bytes of the - // returned path for use in serializers that report how much buffer was used. - size_t GetPath(uint64_t label, fuzz::span<uint8_t> path_hashes) const; - // Updates the hashes in the path of the specified leaf. If |path_hash| is - // empty, the entry in hash_tree_ is deleted representing an empty leaf. - void UpdatePath(uint64_t label, fuzz::span<const uint8_t> path_hash); - - void Reset(); - void Reset(uint8_t bits_per_level, uint8_t height); - - private: - uint8_t bits_per_level_; - uint8_t height_; - - // Only contains hashes for non empty paths in the tree. - std::unordered_map<MaskedLabel, std::array<uint8_t, 32>> hash_tree_; - std::vector<std::array<uint8_t, 32>> empty_node_hashes_; -}; - -#endif // __FUZZ_MEM_HASH_TREE_H diff --git a/fuzz/nvmem_tpm2_mock.c b/fuzz/nvmem_tpm2_mock.c deleted file mode 100644 index b864953b5d..0000000000 --- a/fuzz/nvmem_tpm2_mock.c +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright 2019 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. - */ -/* Stuff from tpm2 directory. */ -#define HIDE_EC_STDLIB -#define NV_C -#include "Global.h" -#undef NV_C -#include "NV_fp.h" -#include "tpm_generated.h" - -#include "nvmem.h" -#include "util.h" - -#define NVMEM_CR50_SIZE 272 - -#ifndef TEST_FUZZ -uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {MOCK_NV_MEMORY_SIZE, - NVMEM_CR50_SIZE}; -#endif - -uint32_t s_evictNvStart; -uint32_t s_evictNvEnd; - -/* Calculate size of TPM NVMEM. */ -#define MOCK_NV_MEMORY_SIZE \ - (NVMEM_PARTITION_SIZE - sizeof(struct nvmem_tag) - NVMEM_CR50_SIZE) - -/* - * Sizes of the reserved objects stored in the TPM NVMEM. Note that the second - * last object is in fact a variable size field starting with 4 bytes of size - * and then up to 512 bytes of actual index data. The array below assumes that - * the full 512 bytes of the index space are used. - */ -const uint16_t res_sizes[] = {4, 2, 2, 2, 66, 66, 66, 66, 66, 66, - 34, 34, 34, 66, 66, 66, 8, 4, 134, 28, - 3, 4, 4, 4, 4, 4, 2, 15, 2, 8, - 4, 4, 4, 96, 2844, 424, 516, 8}; - -static uint16_t res_addrs[ARRAY_SIZE(res_sizes)]; - -BOOL NvEarlyStageFindHandle(TPM_HANDLE handle) -{ - size_t i; - - res_addrs[0] = 0; - - for (i = 1; i < ARRAY_SIZE(res_addrs); i++) - res_addrs[i] = res_addrs[i - 1] + res_sizes[i - 1]; - - s_evictNvStart = res_addrs[i - 1] + res_sizes[i - 1]; - - s_evictNvEnd = MOCK_NV_MEMORY_SIZE; - return 0; -} - -void NvGetReserved(UINT32 index, NV_RESERVED_ITEM *ri) -{ - if (index < ARRAY_SIZE(res_sizes)) { - ri->size = res_sizes[index]; - ri->offset = res_addrs[index]; - } else { - ri->size = 0; - } -} - -UINT16 UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size) -{ - uint16_t value; - - if (!size || (*size < sizeof(value))) - return 0; - - value = htobe16(*source); - - memcpy(*buffer, &value, sizeof(value)); - *buffer += sizeof(value); - *size -= sizeof(value); - - return sizeof(value); -} - -UINT16 UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size) -{ - uint32_t value; - - if (!size || (*size < sizeof(value))) - return 0; - - value = htobe32(*source); - - memcpy(*buffer, &value, sizeof(value)); - *buffer += sizeof(value); - *size -= sizeof(value); - - return sizeof(value); -} - -UINT16 UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size) -{ - uint64_t value; - - if (!size || (*size < sizeof(value))) - return 0; - - value = htobe64(*source); - - memcpy(*buffer, &value, sizeof(value)); - *buffer += sizeof(value); - *size -= sizeof(value); - - return sizeof(value); -} - -UINT16 TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size) -{ - UINT16 total_size; - INT32 i; - uint8_t *p; - - total_size = UINT16_Marshal(&source->t.size, buffer, size); - p = *buffer; - - for (i = 0; (i < source->t.size) && *size; ++i) { - *p++ = source->t.buffer[i]; - *size -= 1; - } - - total_size += i; - *buffer = p; - - return total_size; -} - -uint16_t TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size) -{ - return TPM2B_DIGEST_Marshal(source, buffer, size); -} - -uint16_t TPM2B_NONCE_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size) -{ - return TPM2B_DIGEST_Marshal(source, buffer, size); -} - -TPM_RC UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size) -{ - uint16_t value; - - if (!size || *size < sizeof(value)) - return TPM_RC_INSUFFICIENT; - - memcpy(&value, *buffer, sizeof(value)); - *target = be16toh(value); - - *buffer += sizeof(value); - *size -= sizeof(value); - - return TPM_RC_SUCCESS; -} - -TPM_RC UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size) -{ - uint32_t value; - - if (!size || *size < sizeof(value)) - return TPM_RC_INSUFFICIENT; - - memcpy(&value, *buffer, sizeof(value)); - *target = be32toh(value); - - *buffer += sizeof(value); - *size -= sizeof(value); - - return TPM_RC_SUCCESS; -} - -TPM_RC UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size) -{ - uint64_t value; - - if (!size || *size < sizeof(value)) - return TPM_RC_INSUFFICIENT; - - memcpy(&value, *buffer, sizeof(value)); - *target = be64toh(value); - - *buffer += sizeof(value); - *size -= sizeof(value); - - return TPM_RC_SUCCESS; -} - -TPM_RC TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size) -{ - TPM_RC result; - INT32 i; - uint8_t *p; - - result = UINT16_Unmarshal(&target->t.size, buffer, size); - - if (result != TPM_RC_SUCCESS) - return result; - - if (target->t.size == 0) - return TPM_RC_SUCCESS; - - if ((target->t.size > sizeof(TPMU_HA)) || (target->t.size > *size)) - return TPM_RC_SIZE; - - p = *buffer; - for (i = 0; i < target->t.size; ++i) - target->t.buffer[i] = *p++; - - *buffer = p; - *size -= i; - - return TPM_RC_SUCCESS; -} - -TPM_RC TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size) -{ - return TPM2B_DIGEST_Unmarshal(target, buffer, size); -} - -TPM_RC TPM2B_NONCE_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size) -{ - return TPM2B_DIGEST_Unmarshal(target, buffer, size); -} diff --git a/fuzz/pinweaver/pinweaver.proto b/fuzz/pinweaver/pinweaver.proto deleted file mode 100644 index 40e74f71de..0000000000 --- a/fuzz/pinweaver/pinweaver.proto +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -syntax = "proto3"; - -package fuzz.pinweaver; - -import public "google/protobuf/wrappers.proto"; - -message ResetTree { - uint32 bits_per_level = 1; - uint32 height = 2; -} - -message InsertLeaf { - uint64 label = 1; - bytes delay_schedule = 2; - bytes low_entropy_secret = 3; - bytes high_entropy_secret = 4; - bytes reset_secret = 5; - bytes path_hashes = 6; -} - -message RemoveLeaf { - uint64 label = 1; - bytes leaf_hmac = 2; - bytes path_hashes = 3; -} - -message TryAuth { - uint64 label = 1; - bytes low_entropy_secret = 2; - bytes unimported_leaf_data = 3; -} - -message ResetAuth { - uint64 label = 1; - bytes reset_secret = 2; - bytes unimported_leaf_data = 3; -} - -message GetLog { - uint32 index_of_root = 1; -} - -message LogReplay { - uint32 index_of_root = 1; - bytes unimported_leaf_data = 2; -} - -message Request { - // A work around to provide the has_version() function. - google.protobuf.UInt32Value version = 1; - oneof request { - ResetTree reset_tree = 2; - InsertLeaf insert_leaf = 3; - RemoveLeaf remove_leaf = 4; - TryAuth try_auth = 5; - ResetAuth reset_auth = 6; - GetLog get_log = 7; - LogReplay log_replay = 8; - } -} diff --git a/fuzz/pinweaver_model.cc b/fuzz/pinweaver_model.cc deleted file mode 100644 index 43618e1fa4..0000000000 --- a/fuzz/pinweaver_model.cc +++ /dev/null @@ -1,474 +0,0 @@ -// 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. - -#include "fuzz/pinweaver_model.h" - -#include "board/host/dcrypto.h" - -namespace { - -struct pw_request_t* SerializeCommon(const fuzz::pinweaver::Request& pinweaver, - pw_message_type_t message_type, - fuzz::span<uint8_t> buffer) { - struct pw_request_t* request = - reinterpret_cast<struct pw_request_t*>(buffer.begin()); - if (pinweaver.has_version()) { - request->header.version = pinweaver.version().value(); - } else { - request->header.version = PW_PROTOCOL_VERSION; - } - request->header.type = message_type; - return request; -} - -void CheckBuffer(fuzz::span<uint8_t> buffer) { - uintptr_t ptr = reinterpret_cast<uintptr_t>(buffer.begin()); - assert(ptr % alignof(pw_request_t) == 0); - assert(ptr % alignof(pw_response_t) == 0); -} - -} // namespace - -//****************************************************************************** -// Public member functions. -//****************************************************************************** - -PinweaverModel::PinweaverModel() { - Reset(); -} - -void PinweaverModel::SendBuffer(fuzz::span<uint8_t> buffer) { - assert(sizeof(pw_request_t) <= buffer.size()); - assert(sizeof(pw_response_t) <= buffer.size()); - CheckBuffer(buffer); - pw_request_t* request = reinterpret_cast<pw_request_t*>(buffer.begin()); - pw_response_t* response = reinterpret_cast<pw_response_t*>(buffer.begin()); - pw_handle_request(&merkle_tree_, request, response); -} - -size_t PinweaverModel::SerializeRequest( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - assert(buffer.size() >= PW_MAX_MESSAGE_SIZE); - CheckBuffer(buffer); - switch (pinweaver.request_case()) { - case fuzz::pinweaver::Request::kResetTree: - return SerializeResetTree(pinweaver, buffer); - case fuzz::pinweaver::Request::kInsertLeaf: - return SerializeInsertLeaf(pinweaver, buffer); - case fuzz::pinweaver::Request::kRemoveLeaf: - return SerializeRemoveLeaf(pinweaver, buffer); - case fuzz::pinweaver::Request::kTryAuth: - return SerializeTryAuth(pinweaver, buffer); - case fuzz::pinweaver::Request::kResetAuth: - return SerializeResetAuth(pinweaver, buffer); - case fuzz::pinweaver::Request::kGetLog: - return SerializeGetLog(pinweaver, buffer); - case fuzz::pinweaver::Request::kLogReplay: - return SerializeLogReplay(pinweaver, buffer); - case fuzz::pinweaver::Request::REQUEST_NOT_SET: - break; - } - return 0; -} - -uint32_t PinweaverModel::ApplyRequest(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) { - SerializeRequest(pinweaver, buffer); - LeafData leaf_data; - - // Size and alignment of buffer are checked in SerializeRequest(). - pw_request_t* request = reinterpret_cast<pw_request_t*>(buffer.begin()); - pw_response_t* response = reinterpret_cast<pw_response_t*>(buffer.begin()); - - if (pinweaver.request_case() == fuzz::pinweaver::Request::kInsertLeaf) { - pw_request_insert_leaf_t& insert = request->data.insert_leaf; - std::copy(insert.low_entropy_secret, - insert.low_entropy_secret + PW_SECRET_SIZE, - leaf_data.low_entropy_secret.begin()); - std::copy(insert.reset_secret, insert.reset_secret + PW_SECRET_SIZE, - leaf_data.reset_secret.begin()); - } - - pw_handle_request(&merkle_tree_, request, response); - if (response->header.result_code != EC_SUCCESS && - pinweaver.request_case() != fuzz::pinweaver::Request::kTryAuth) { - return response->header.result_code; - } - - switch (pinweaver.request_case()) { - case fuzz::pinweaver::Request::kResetTree: - ApplyResetTree(); - break; - case fuzz::pinweaver::Request::kInsertLeaf: - ApplyInsertLeaf(pinweaver, *response, &leaf_data); - break; - case fuzz::pinweaver::Request::kRemoveLeaf: - ApplyRemoveLeaf(pinweaver, *response); - break; - case fuzz::pinweaver::Request::kTryAuth: - ApplyTryAuth(pinweaver, *response); - break; - case fuzz::pinweaver::Request::kResetAuth: - ApplyResetAuth(pinweaver, *response); - break; - // GetLog and LogReplay have no side-effects so the model doesn't need - // to be updated. - case fuzz::pinweaver::Request::kGetLog: - case fuzz::pinweaver::Request::kLogReplay: - case fuzz::pinweaver::Request::REQUEST_NOT_SET: - break; - } - return response->header.result_code; -} - -void PinweaverModel::Reset() { - memset(&merkle_tree_, 0, sizeof(merkle_tree_)); - leaf_metadata_.clear(); - mem_hash_tree_.Reset(); - root_history_.clear(); -}; - -//****************************************************************************** -// Private static fields. -//****************************************************************************** - -constexpr uint8_t PinweaverModel::kNullRootHash[PW_HASH_SIZE]; - -//****************************************************************************** -// Private member functions. -//****************************************************************************** - -void PinweaverModel::GetHmac(const std::string& fuzzer_hmac, - uint64_t label, - fuzz::span<uint8_t> hmac) const { - assert(hmac.size() == PW_HASH_SIZE); - if (!fuzzer_hmac.empty()) { - fuzz::CopyWithPadding(fuzzer_hmac, hmac, 0); - return; - } - mem_hash_tree_.GetLeaf(label, hmac); -} - -size_t PinweaverModel::CopyMetadata( - uint64_t label, - const LeafData& leaf_data, - unimported_leaf_data_t* unimported_leaf_data, - fuzz::span<uint8_t> buffer) const { - const std::vector<uint8_t>& data = leaf_data.wrapped_data; - memcpy(unimported_leaf_data, data.data(), data.size()); - - fuzz::span<uint8_t> path_hashes( - reinterpret_cast<uint8_t*>(unimported_leaf_data) + data.size(), - buffer.end()); - return data.size() + mem_hash_tree_.GetPath(label, path_hashes); -} - -size_t PinweaverModel::GetMetadata(uint64_t label, - unimported_leaf_data_t* unimported_leaf_data, - fuzz::span<uint8_t> buffer) const { - auto itr = leaf_metadata_.find(label); - if (itr == leaf_metadata_.end()) { - assert(buffer.size() >= sizeof(wrapped_leaf_data_t)); - std::fill(buffer.begin(), buffer.begin() + sizeof(wrapped_leaf_data_t), 0); - return sizeof(wrapped_leaf_data_t); - } - return CopyMetadata(label, itr->second, unimported_leaf_data, buffer); -} - -size_t PinweaverModel::GetPath(const std::string& fuzzer_hashes, - uint64_t label, - fuzz::span<uint8_t> path_hashes) const { - if (!fuzzer_hashes.empty()) { - return fuzz::CopyWithPadding(fuzzer_hashes, path_hashes, 0); - } - return mem_hash_tree_.GetPath(label, path_hashes); -} - -void PinweaverModel::LogRootHash(fuzz::span<const uint8_t> root_hash, - uint64_t label) { - assert(root_hash.size() == PW_HASH_SIZE); - std::pair<std::vector<uint8_t>, uint64_t> entry{ - {root_hash.begin(), root_hash.end()}, label}; - if (root_history_.size() == PW_LOG_ENTRY_COUNT) { - root_history_.pop_front(); - } - root_history_.emplace_back(std::array<uint8_t, PW_HASH_SIZE>{}, label); - std::copy(root_hash.begin(), root_hash.end(), - root_history_.back().first.begin()); -} - -fuzz::span<const uint8_t> PinweaverModel::GetRootHashFromLog( - size_t index) const { - if (index >= root_history_.size()) { - return fuzz::span<const uint8_t>(kNullRootHash, PW_HASH_SIZE); - } - return root_history_.rbegin()[index].first; -} - -uint64_t PinweaverModel::GetLabelFromLog(size_t index) const { - if (index >= root_history_.size()) { - return 0; - } - return root_history_.rbegin()[index].second; -} - -size_t PinweaverModel::SerializeResetTree( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - const fuzz::pinweaver::ResetTree& fuzzer_data = pinweaver.reset_tree(); - pw_request_t* request = SerializeCommon(pinweaver, {PW_RESET_TREE}, buffer); - pw_request_reset_tree_t* req_data = &request->data.reset_tree; - - request->header.data_length = sizeof(*req_data); - req_data->bits_per_level.v = fuzzer_data.bits_per_level(); - req_data->height.v = fuzzer_data.height(); - - return request->header.data_length + sizeof(request->header); -} - -size_t PinweaverModel::SerializeInsertLeaf( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - const fuzz::pinweaver::InsertLeaf& fuzzer_data = pinweaver.insert_leaf(); - pw_request_t* request = SerializeCommon(pinweaver, {PW_INSERT_LEAF}, buffer); - pw_request_insert_leaf_t* req_data = &request->data.insert_leaf; - - req_data->label.v = fuzzer_data.label(); - fuzz::CopyWithPadding( - fuzzer_data.delay_schedule(), - fuzz::span<uint8_t>(reinterpret_cast<uint8_t*>(req_data->delay_schedule), - sizeof(req_data->delay_schedule)), - 0); - fuzz::CopyWithPadding( - fuzzer_data.low_entropy_secret(), - fuzz::span<uint8_t>(req_data->low_entropy_secret, PW_SECRET_SIZE), 0); - fuzz::CopyWithPadding( - fuzzer_data.high_entropy_secret(), - fuzz::span<uint8_t>(req_data->high_entropy_secret, PW_SECRET_SIZE), 0); - fuzz::CopyWithPadding( - fuzzer_data.reset_secret(), - fuzz::span<uint8_t>(req_data->reset_secret, PW_SECRET_SIZE), 0); - - fuzz::span<uint8_t> path_hashes( - reinterpret_cast<uint8_t*>(req_data->path_hashes), buffer.end()); - size_t path_hash_size = - GetPath(fuzzer_data.path_hashes(), fuzzer_data.label(), path_hashes); - request->header.data_length = sizeof(*req_data) + path_hash_size; - - return request->header.data_length + sizeof(request->header); -} - -size_t PinweaverModel::SerializeRemoveLeaf( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - const fuzz::pinweaver::RemoveLeaf& fuzzer_data = pinweaver.remove_leaf(); - pw_request_t* request = SerializeCommon(pinweaver, {PW_REMOVE_LEAF}, buffer); - pw_request_remove_leaf_t* req_data = &request->data.remove_leaf; - - req_data->leaf_location.v = fuzzer_data.label(); - GetHmac(fuzzer_data.leaf_hmac(), fuzzer_data.label(), - fuzz::span<uint8_t>(req_data->leaf_hmac, PW_HASH_SIZE)); - - fuzz::span<uint8_t> path_hashes( - reinterpret_cast<uint8_t*>(req_data->path_hashes), buffer.end()); - size_t path_hash_size = - GetPath(fuzzer_data.path_hashes(), fuzzer_data.label(), path_hashes); - request->header.data_length = sizeof(*req_data) + path_hash_size; - - return request->header.data_length + sizeof(request->header); -} - -size_t PinweaverModel::SerializeTryAuth( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - const fuzz::pinweaver::TryAuth& fuzzer_data = pinweaver.try_auth(); - pw_request_t* request = SerializeCommon(pinweaver, {PW_TRY_AUTH}, buffer); - pw_request_try_auth_t* req_data = &request->data.try_auth; - - request->header.data_length = - sizeof(*req_data) - sizeof(req_data->unimported_leaf_data); - - auto itr = leaf_metadata_.find(fuzzer_data.label()); - if (fuzzer_data.low_entropy_secret().empty() && itr != leaf_metadata_.end()) { - const auto& low_entropy_secret = itr->second.low_entropy_secret; - std::copy(low_entropy_secret.begin(), low_entropy_secret.end(), - req_data->low_entropy_secret); - } else { - fuzz::CopyWithPadding( - fuzzer_data.low_entropy_secret(), - fuzz::span<uint8_t>(req_data->low_entropy_secret, PW_SECRET_SIZE), 0); - } - - if (fuzzer_data.unimported_leaf_data().empty() && - itr != leaf_metadata_.end()) { - request->header.data_length += - CopyMetadata(fuzzer_data.label(), itr->second, - &req_data->unimported_leaf_data, buffer); - } else { - request->header.data_length += fuzz::CopyWithPadding( - fuzzer_data.unimported_leaf_data(), - fuzz::span<uint8_t>( - reinterpret_cast<uint8_t*>(&req_data->unimported_leaf_data), - sizeof(wrapped_leaf_data_t)), - 0); - } - - return request->header.data_length + sizeof(request->header); -} - -size_t PinweaverModel::SerializeResetAuth( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - const fuzz::pinweaver::ResetAuth& fuzzer_data = pinweaver.reset_auth(); - pw_request_t* request = SerializeCommon(pinweaver, {PW_RESET_AUTH}, buffer); - pw_request_reset_auth_t* req_data = &request->data.reset_auth; - - request->header.data_length = - sizeof(*req_data) - sizeof(req_data->unimported_leaf_data); - - auto itr = leaf_metadata_.find(fuzzer_data.label()); - if (fuzzer_data.reset_secret().empty() && itr != leaf_metadata_.end()) { - const auto& reset_secret = itr->second.reset_secret; - std::copy(reset_secret.begin(), reset_secret.end(), req_data->reset_secret); - } else { - fuzz::CopyWithPadding( - fuzzer_data.reset_secret(), - fuzz::span<uint8_t>(req_data->reset_secret, PW_SECRET_SIZE), 0); - } - - if (fuzzer_data.unimported_leaf_data().empty() && - itr != leaf_metadata_.end()) { - request->header.data_length += - CopyMetadata(fuzzer_data.label(), itr->second, - &req_data->unimported_leaf_data, buffer); - } else { - request->header.data_length += fuzz::CopyWithPadding( - fuzzer_data.unimported_leaf_data(), - fuzz::span<uint8_t>( - reinterpret_cast<uint8_t*>(&req_data->unimported_leaf_data), - sizeof(wrapped_leaf_data_t)), - 0); - } - - return request->header.data_length + sizeof(request->header); -} - -size_t PinweaverModel::SerializeGetLog( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - const fuzz::pinweaver::GetLog& fuzzer_data = pinweaver.get_log(); - pw_request_t* request = SerializeCommon(pinweaver, {PW_GET_LOG}, buffer); - pw_request_get_log_t* req_data = &request->data.get_log; - - memcpy(req_data->root, - GetRootHashFromLog(fuzzer_data.index_of_root()).begin(), PW_HASH_SIZE); - request->header.data_length = sizeof(*req_data); - - return request->header.data_length + sizeof(request->header); -} - -size_t PinweaverModel::SerializeLogReplay( - const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const { - const fuzz::pinweaver::LogReplay& fuzzer_data = pinweaver.log_replay(); - pw_request_t* request = SerializeCommon(pinweaver, {PW_LOG_REPLAY}, buffer); - pw_request_log_replay_t* req_data = &request->data.log_replay; - - memcpy(req_data->log_root, - GetRootHashFromLog(fuzzer_data.index_of_root()).begin(), PW_HASH_SIZE); - request->header.data_length = - sizeof(*req_data) - sizeof(req_data->unimported_leaf_data); - - if (fuzzer_data.unimported_leaf_data().empty()) { - request->header.data_length += - GetMetadata(GetLabelFromLog(fuzzer_data.index_of_root()), - &req_data->unimported_leaf_data, buffer); - } else { - request->header.data_length += fuzz::CopyWithPadding( - fuzzer_data.unimported_leaf_data(), - fuzz::span<uint8_t>( - reinterpret_cast<uint8_t*>(&req_data->unimported_leaf_data), - sizeof(wrapped_leaf_data_t)), - 0); - } - - return request->header.data_length + sizeof(request->header); -} - -void PinweaverModel::UpdateMetadata( - uint64_t label, - const pw_response_header_t& header, - const unimported_leaf_data_t* unimported_leaf_data, - size_t unimported_leaf_data_length, - const LeafData* leaf_data) { - LogRootHash(fuzz::span<const uint8_t>(header.root, PW_HASH_SIZE), label); - if (unimported_leaf_data) { - const uint8_t* data = - reinterpret_cast<const uint8_t*>(unimported_leaf_data); - LeafData& stored_leaf_data = leaf_metadata_[label]; - if (leaf_data) { - stored_leaf_data = *leaf_data; - } - stored_leaf_data.wrapped_data.assign(data, - data + unimported_leaf_data_length); - mem_hash_tree_.UpdatePath( - label, - fuzz::span<const uint8_t>(unimported_leaf_data->hmac, PW_HASH_SIZE)); - } else { - leaf_metadata_.erase(label); - mem_hash_tree_.UpdatePath(label, fuzz::span<const uint8_t>() /*path_hash*/); - } -} - -void PinweaverModel::ApplyResetTree() { - leaf_metadata_.clear(); - mem_hash_tree_.Reset(merkle_tree_.bits_per_level.v, merkle_tree_.height.v); -} - -void PinweaverModel::ApplyInsertLeaf(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response, - const LeafData* leaf_data) { - const pw_response_insert_leaf_t* resp = &response.data.insert_leaf; - size_t unimported_leaf_data_length = response.header.data_length - - sizeof(*resp) + - sizeof(resp->unimported_leaf_data); - UpdateMetadata(pinweaver.insert_leaf().label(), response.header, - &resp->unimported_leaf_data, unimported_leaf_data_length, - leaf_data); -} - -void PinweaverModel::ApplyRemoveLeaf(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response) { - UpdateMetadata(pinweaver.remove_leaf().label(), response.header, - nullptr /*unimported_leaf_data*/, - 0 /*unimported_leaf_data_length*/, nullptr /*leaf_data*/); -} - -void PinweaverModel::ApplyTryAuth(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response) { - const pw_response_try_auth_t* resp = &response.data.try_auth; - - if (response.header.result_code != EC_SUCCESS && - response.header.result_code != PW_ERR_LOWENT_AUTH_FAILED) { - return; - } - size_t unimported_leaf_data_length = response.header.data_length - - sizeof(*resp) + - sizeof(resp->unimported_leaf_data); - UpdateMetadata(pinweaver.try_auth().label(), response.header, - &resp->unimported_leaf_data, unimported_leaf_data_length, - nullptr /*leaf_data*/); -} - -void PinweaverModel::ApplyResetAuth(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response) { - const pw_response_reset_auth_t* resp = &response.data.reset_auth; - size_t unimported_leaf_data_length = response.header.data_length - - sizeof(*resp) + - sizeof(resp->unimported_leaf_data); - UpdateMetadata(pinweaver.reset_auth().label(), response.header, - &resp->unimported_leaf_data, unimported_leaf_data_length, - nullptr /*leaf_data*/); -} diff --git a/fuzz/pinweaver_model.h b/fuzz/pinweaver_model.h deleted file mode 100644 index 84508786f3..0000000000 --- a/fuzz/pinweaver_model.h +++ /dev/null @@ -1,123 +0,0 @@ -// 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. - -// Pinweaver specific model to facilitate fuzzing. - -#ifndef __FUZZ_PINWEAVER_MODEL_H -#define __FUZZ_PINWEAVER_MODEL_H - -#include <deque> -#include <memory> -#include <unordered_map> - -#define HIDE_EC_STDLIB -#include "fuzz/cr50_fuzz.pb.h" -#include "fuzz/mem_hash_tree.h" -#include "fuzz/span.h" -#include "include/pinweaver.h" -#include "include/pinweaver_types.h" - -// Provides enough state tracking to send valid PinWeaver requests. This is -// necessary because of the authentication dependent fields used by the Merkle -// tree such as HMACs and a set of sibling path hashes that must be correct to -// reach some parts of the PinWeaver code. -class PinweaverModel { - public: - PinweaverModel(); - - void SendBuffer(fuzz::span<uint8_t> buffer); - - // Converts the logical representation of a request used in fuzzing into bytes - // that can be processed by the pinweaver code for fuzzing. - size_t SerializeRequest(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - - // Executes a request in the form of a fuzz::pinweaver::Request proto, and - // updates the model, so that future requests will be valid. - uint32_t ApplyRequest(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer); - - // Clears any state. This shoudl be called at the beginning of each fuzzing - // iteration. - void Reset(); - - private: - static constexpr uint8_t kNullRootHash[PW_HASH_SIZE] = {}; - - struct LeafData { - std::vector<uint8_t> wrapped_data; - std::array<uint8_t, PW_SECRET_SIZE> low_entropy_secret; - std::array<uint8_t, PW_SECRET_SIZE> reset_secret; - }; - - // Functions for retrieving the current state of the metadata. - void GetHmac(const std::string& fuzzer_hmac, - uint64_t label, - fuzz::span<uint8_t> hmac) const; - size_t CopyMetadata(uint64_t label, - const LeafData& leaf_data, - unimported_leaf_data_t* unimported_leaf_data, - fuzz::span<uint8_t> buffer) const; - size_t GetMetadata(uint64_t label, - unimported_leaf_data_t* unimported_leaf_data, - fuzz::span<uint8_t> buffer) const; - size_t GetPath(const std::string& fuzzer_hashes, - uint64_t label, - fuzz::span<uint8_t> path_hashes) const; - - // Store copies of the root hash of the Merkle tree, and label of the leaf - // associated with a request so that valid get log requests can be generated. - void LogRootHash(fuzz::span<const uint8_t> root_hash, uint64_t label); - // Retrieve a root hash from the log at the given index. - fuzz::span<const uint8_t> GetRootHashFromLog(size_t index) const; - // Retrieve a leaf label from the log at the given index. - uint64_t GetLabelFromLog(size_t index) const; - - // Helper functions used by SerializePinweaver to convert - size_t SerializeResetTree(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - size_t SerializeInsertLeaf(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - size_t SerializeRemoveLeaf(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - size_t SerializeTryAuth(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - size_t SerializeResetAuth(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - size_t SerializeGetLog(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - size_t SerializeLogReplay(const fuzz::pinweaver::Request& pinweaver, - fuzz::span<uint8_t> buffer) const; - - // Updates the metadata storage for a particular leaf. |leaf_data| is only - // required for insert operations so the metadata, low_entropy_secret, - // and reset_secret for the leaf can be retrieved to generate valid - // authentication requests. - void UpdateMetadata(uint64_t label, - const pw_response_header_t& header, - const unimported_leaf_data_t* unimported_leaf_data, - size_t unimported_leaf_data_length, - const LeafData* leaf_data); - - // Helper functions for updating the state when responses are received. - void ApplyResetTree(); - void ApplyInsertLeaf(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response, - const LeafData* leaf_data); - void ApplyRemoveLeaf(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response); - void ApplyTryAuth(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response); - void ApplyResetAuth(const fuzz::pinweaver::Request& pinweaver, - const pw_response_t& response); - - merkle_tree_t merkle_tree_; - - MemHashTree mem_hash_tree_; - std::deque<std::pair<std::array<uint8_t, PW_HASH_SIZE>, uint64_t>> - root_history_; - std::unordered_map<uint64_t, LeafData> leaf_metadata_; -}; - -#endif // __FUZZ_PINWEAVER_MODEL_H |