summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fuzz/build.mk18
-rw-r--r--fuzz/cr50_fuzz.cc148
-rw-r--r--fuzz/cr50_fuzz.owners5
-rw-r--r--fuzz/cr50_fuzz.proto31
-rw-r--r--fuzz/cr50_fuzz.tasklist9
-rw-r--r--fuzz/mem_hash_tree.cc130
-rw-r--r--fuzz/mem_hash_tree.h58
-rw-r--r--fuzz/nvmem_tpm2_mock.c229
-rw-r--r--fuzz/pinweaver/pinweaver.proto64
-rw-r--r--fuzz/pinweaver_model.cc474
-rw-r--r--fuzz/pinweaver_model.h123
-rw-r--r--test/build.mk7
-rw-r--r--test/nvmem.c1569
-rw-r--r--test/nvmem.tasklist11
-rw-r--r--test/nvmem_tpm2_mock.c377
15 files changed, 1 insertions, 3252 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
diff --git a/test/build.mk b/test/build.mk
index c7462da559..2b84ffe907 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -56,7 +56,6 @@ test-list-host += motion_lid
test-list-host += motion_sense_fifo
test-list-host += mutex
test-list-host += newton_fit
-test-list-host += nvmem
test-list-host += pingpong
test-list-host += pinweaver
test-list-host += power_button
@@ -140,7 +139,6 @@ motion_sense_fifo-y=motion_sense_fifo.o
kasa-y=kasa.o
mutex-y=mutex.o
newton_fit-y=newton_fit.o
-nvmem-y=nvmem.o nvmem_tpm2_mock.o
pingpong-y=pingpong.o
pinweaver-y=pinweaver.o
power_button-y=power_button.o
@@ -188,11 +186,6 @@ fp-y=fp.o
x25519-y=x25519.o
stillness_detector-y=stillness_detector.o
-TPM2_ROOT := $(CROS_WORKON_SRCROOT)/src/third_party/tpm2
-$(out)/RO/common/new_nvmem.o: CFLAGS += -I$(TPM2_ROOT) -I chip/g
-$(out)/RO/test/nvmem.o: CFLAGS += -I$(TPM2_ROOT)
-$(out)/RO/test/nvmem_tpm2_mock.o: CFLAGS += -I$(TPM2_ROOT)
-
host-is_enabled_error: TEST_SCRIPT=is_enabled_error.sh
is_enabled_error-y=is_enabled_error.o.cmd
diff --git a/test/nvmem.c b/test/nvmem.c
deleted file mode 100644
index c07637e8de..0000000000
--- a/test/nvmem.c
+++ /dev/null
@@ -1,1569 +0,0 @@
-/* Copyright 2016 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.
- *
- * Test Cr-50 Non-Voltatile memory module
- */
-
-#include "nvmem_test.h"
-
-#include "common.h"
-#include "console.h"
-#include "crc.h"
-#include "flash.h"
-#include "flash_log.h"
-#include "new_nvmem.h"
-#include "nvmem.h"
-#include "printf.h"
-#include "shared_mem.h"
-#include "task.h"
-#include "test_util.h"
-#include "timer.h"
-#include "util.h"
-
-#define WRITE_SEGMENT_LEN 200
-#define WRITE_READ_SEGMENTS 4
-
-enum test_failure_mode failure_mode;
-
-static const uint8_t legacy_nvmem_image[] = {
-#include "legacy_nvmem_dump.h"
-};
-
-BUILD_ASSERT(sizeof(legacy_nvmem_image) == NVMEM_PARTITION_SIZE);
-
-static uint8_t write_buffer[NVMEM_PARTITION_SIZE];
-static int flash_write_fail;
-
-struct nvmem_test_result {
- int var_count;
- int reserved_obj_count;
- int evictable_obj_count;
- int deleted_obj_count;
- int delimiter_count;
- int unexpected_count;
- size_t valid_data_size;
- size_t erased_data_size;
- size_t tuple_data_size;
-};
-
-static struct nvmem_test_result test_result;
-
-int app_cipher(const void *salt_p, void *out_p, const void *in_p, size_t size)
-{
-
- const uint8_t *in = in_p;
- uint8_t *out = out_p;
- const uint8_t *salt = salt_p;
- size_t i;
-
- for (i = 0; i < size; i++)
- out[i] = in[i] ^ salt[i % CIPHER_SALT_SIZE];
-
- return 1;
-}
-
-void app_compute_hash(uint8_t *p_buf, size_t num_bytes,
- uint8_t *p_hash, size_t hash_bytes)
-{
- uint32_t crc;
- uint32_t *p_data;
- int n;
- size_t tail_size;
-
- crc32_init();
- /* Assuming here that buffer is 4 byte aligned. */
- p_data = (uint32_t *)p_buf;
- for (n = 0; n < num_bytes / 4; n++)
- crc32_hash32(*p_data++);
-
- tail_size = num_bytes % 4;
- if (tail_size) {
- uint32_t tail;
-
- tail = 0;
- memcpy(&tail, p_data, tail_size);
- crc32_hash32(tail);
- }
-
- /*
- * Crc32 of 0xffffffff is 0xffffffff. Let's spike the results to avoid
- * this unfortunate Crc32 property.
- */
- crc = crc32_result() ^ 0x55555555;
-
- for (n = 0; n < hash_bytes; n += sizeof(crc)) {
- size_t copy_bytes = MIN(sizeof(crc), hash_bytes - n);
-
- memcpy(p_hash + n, &crc, copy_bytes);
- }
-}
-
-int crypto_enabled(void)
-{
- return 1;
-}
-
-/* Used to allow/prevent Flash erase/write operations */
-int flash_pre_op(void)
-{
- return flash_write_fail ? EC_ERROR_UNKNOWN : EC_SUCCESS;
-}
-
-static void dump_nvmem_state(const char *title,
- const struct nvmem_test_result *tr)
-{
- ccprintf("\n%s:\n", title);
- ccprintf("var_count: %d\n", tr->var_count);
- ccprintf("reserved_obj_count: %d\n", tr->reserved_obj_count);
- ccprintf("evictable_obj_count: %d\n", tr->evictable_obj_count);
- ccprintf("deleted_obj_count: %d\n", tr->deleted_obj_count);
- ccprintf("deimiter_count: %d\n", tr->delimiter_count);
- ccprintf("unexpected_count: %d\n", tr->unexpected_count);
- ccprintf("valid_data_size: %zd\n", tr->valid_data_size);
- ccprintf("tuple_data_size: %zd\n", tr->tuple_data_size);
- ccprintf("erased_data_size: %zd\n\n", tr->erased_data_size);
-}
-
-static void wipe_out_nvmem_cache(void)
-{
- memset(nvmem_cache_base(NVMEM_TPM), 0, nvmem_user_sizes[NVMEM_TPM]);
-}
-
-static int prepare_nvmem_contents(void)
-{
- struct nvmem_tag *tag;
-
- memcpy(write_buffer, legacy_nvmem_image, sizeof(write_buffer));
- tag = (struct nvmem_tag *)write_buffer;
-
- app_compute_hash(tag->padding, NVMEM_PARTITION_SIZE - NVMEM_SHA_SIZE,
- tag->sha, sizeof(tag->sha));
- app_cipher(tag->sha, tag + 1, tag + 1,
- NVMEM_PARTITION_SIZE - sizeof(struct nvmem_tag));
-
- return flash_physical_write(CONFIG_FLASH_NVMEM_BASE_A -
- CONFIG_PROGRAM_MEMORY_BASE,
- sizeof(write_buffer), write_buffer);
-}
-
-static int iterate_over_flash(void)
-{
- enum ec_error_list rv;
- struct nn_container *ch;
- struct access_tracker at = {};
- uint8_t buf[CONFIG_FLASH_BANK_SIZE];
-
- memset(&test_result, 0, sizeof(test_result));
- ch = (struct nn_container *)buf;
-
- while ((rv = get_next_object(&at, ch, 1)) == EC_SUCCESS)
- switch (ch->container_type) {
- case NN_OBJ_OLD_COPY:
- if (ch->container_type_copy == NN_OBJ_TRANSACTION_DEL) {
- test_result.delimiter_count++;
- } else {
- test_result.deleted_obj_count++;
- test_result.erased_data_size += ch->size;
- }
- break;
-
- case NN_OBJ_TUPLE:
- test_result.var_count++;
- test_result.valid_data_size += ch->size;
- test_result.tuple_data_size += ch->size -
- sizeof(struct tuple);
- break;
-
- case NN_OBJ_TPM_RESERVED:
- test_result.reserved_obj_count++;
- test_result.valid_data_size += ch->size;
- break;
-
- case NN_OBJ_TPM_EVICTABLE:
- test_result.evictable_obj_count++;
- test_result.valid_data_size += ch->size;
- break;
-
- case NN_OBJ_TRANSACTION_DEL:
- test_result.delimiter_count++;
- break;
- default:
- test_result.unexpected_count++;
- break;
- }
-
- if (rv != EC_ERROR_MEMORY_ALLOCATION) {
- ccprintf("\n%s:%d - unexpected return value %d\n", __func__,
- __LINE__, rv);
- return rv;
- }
-
- /* Verify that there is a delimiter at the top of the flash. */
- if (at.mt.data_offset > sizeof(*at.mt.ph)) {
- if ((at.mt.ph == at.dt.ph) &&
- (((at.mt.data_offset - sizeof(struct nn_container))) ==
- at.dt.data_offset)) {
- return EC_SUCCESS;
- }
- } else {
- if ((at.dt.ph == list_element_to_ph(at.list_index)) &&
- (at.dt.data_offset ==
- (CONFIG_FLASH_BANK_SIZE - sizeof(struct nn_container)))) {
- ccprintf("%s:%d edge delimiter case OK\n", __func__,
- __LINE__);
- return EC_SUCCESS;
- }
- }
- ccprintf("%s:%d bad delimiter location: ph %pP, "
- "dt.ph %pP, offset %d, delim offset %d\n",
- __func__, __LINE__, at.mt.ph, at.dt.ph, at.mt.data_offset,
- at.dt.data_offset);
-
- return EC_ERROR_INVAL;
-}
-
-static void *page_to_flash_addr(int page_num)
-{
- uint32_t base_offset = CONFIG_FLASH_NEW_NVMEM_BASE_A;
-
- if (page_num > NEW_NVMEM_TOTAL_PAGES)
- return NULL;
-
- if (page_num >= (NEW_NVMEM_TOTAL_PAGES / 2)) {
- page_num -= (NEW_NVMEM_TOTAL_PAGES / 2);
- base_offset = CONFIG_FLASH_NEW_NVMEM_BASE_B;
- }
-
- return (void *)((uintptr_t)base_offset +
- page_num * CONFIG_FLASH_BANK_SIZE);
-}
-
-static int post_init_from_scratch(uint8_t flash_value)
-{
- int i;
- void *flash_p;
-
- memset(write_buffer, flash_value, sizeof(write_buffer));
-
- /* Overwrite nvmem flash space with junk value. */
- flash_physical_write(
- CONFIG_FLASH_NEW_NVMEM_BASE_A - CONFIG_PROGRAM_MEMORY_BASE,
- NEW_FLASH_HALF_NVMEM_SIZE, (const char *)write_buffer);
- flash_physical_write(
- CONFIG_FLASH_NEW_NVMEM_BASE_B - CONFIG_PROGRAM_MEMORY_BASE,
- NEW_FLASH_HALF_NVMEM_SIZE, (const char *)write_buffer);
-
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- TEST_ASSERT(test_result.var_count == 0);
- TEST_ASSERT(test_result.reserved_obj_count == 38);
- TEST_ASSERT(test_result.evictable_obj_count == 0);
- TEST_ASSERT(test_result.deleted_obj_count == 0);
- TEST_ASSERT(test_result.unexpected_count == 0);
- TEST_ASSERT(test_result.valid_data_size == 1088);
- TEST_ASSERT(total_var_space == 0);
-
- for (i = 0; i < (NEW_NVMEM_TOTAL_PAGES - 1); i++) {
- flash_p = page_to_flash_addr(i);
-
- TEST_ASSERT(!!flash_p);
- TEST_ASSERT(is_uninitialized(flash_p, CONFIG_FLASH_BANK_SIZE));
- }
-
- flash_p = page_to_flash_addr(i);
- TEST_ASSERT(!is_uninitialized(flash_p, CONFIG_FLASH_BANK_SIZE));
-
- return EC_SUCCESS;
-}
-
-/*
- * The purpose of this test is to check NvMem initialization when NvMem is
- * completely erased (i.e. following SpiFlash write of program). In this case,
- * nvmem_init() is expected to create initial flash storage containing
- * reserved objects only.
- */
-static int test_fully_erased_nvmem(void)
-{
-
- return post_init_from_scratch(0xff);
-}
-
-/*
- * The purpose of this test is to check nvmem_init() in the case when no valid
- * pages exist but flash space is garbled as opposed to be fully erased. In
- * this case, the initialization is expected to create one new valid page and
- * erase the rest of the pages.
- */
-static int test_corrupt_nvmem(void)
-{
- return post_init_from_scratch(0x55);
-}
-
-static int prepare_new_flash(void)
-{
- TEST_ASSERT(test_fully_erased_nvmem() == EC_SUCCESS);
-
- /* Now copy sensible information into the nvmem cache. */
- memcpy(nvmem_cache_base(NVMEM_TPM),
- legacy_nvmem_image + sizeof(struct nvmem_tag),
- nvmem_user_sizes[NVMEM_TPM]);
-
- dump_nvmem_state("after first save", &test_result);
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
-
- TEST_ASSERT(test_result.deleted_obj_count == 24);
- TEST_ASSERT(test_result.var_count == 0);
- TEST_ASSERT(test_result.reserved_obj_count == 40);
- TEST_ASSERT(test_result.evictable_obj_count == 9);
- TEST_ASSERT(test_result.unexpected_count == 0);
- TEST_ASSERT(test_result.valid_data_size == 5128);
- TEST_ASSERT(test_result.erased_data_size == 698);
-
- return EC_SUCCESS;
-}
-
-static int test_nvmem_save(void)
-{
- const char *key = "var1";
- const char *value = "value of var 1";
- size_t total_var_size;
- struct nvmem_test_result old_result;
-
- TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
-
- /*
- * Verify that saving without changing the cache does not affect flash
- * contents.
- */
- old_result = test_result;
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
-
- /*
- * Save of unmodified cache does not modify the flash contents and
- * does not set the delimiter.
- */
-
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- TEST_ASSERT(!memcmp(&test_result, &old_result, sizeof(test_result)));
-
- wipe_out_nvmem_cache();
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- TEST_ASSERT(!memcmp(&test_result, &old_result, sizeof(test_result)));
-
- /*
- * Total size test variable storage takes in flash (container header
- * size not included).
- */
- total_var_size = strlen(key) + strlen(value) + sizeof(struct tuple);
-
- /* Verify that we can add a variable to nvmem. */
- TEST_ASSERT(setvar(key, strlen(key), value, strlen(value)) ==
- EC_SUCCESS);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
-
- /* Remove changes caused by the new var addition. */
- test_result.delimiter_count -= 1;
- test_result.valid_data_size -= total_var_size;
- test_result.tuple_data_size -= total_var_size -
- sizeof(struct tuple) * test_result.var_count;
- test_result.var_count -= 1;
-
- TEST_ASSERT(memcmp(&test_result, &old_result, sizeof(test_result)) ==
- 0);
-
- /* Verify that we can delete a variable from nvmem. */
- TEST_ASSERT(setvar(key, strlen(key), NULL, 0) == EC_SUCCESS);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- test_result.deleted_obj_count -= 1;
- test_result.erased_data_size -= total_var_size;
- test_result.delimiter_count -= 1;
- TEST_ASSERT(memcmp(&test_result, &old_result, sizeof(test_result)) ==
- 0);
-
- return EC_SUCCESS;
-}
-
-static size_t get_free_nvmem_room(void)
-{
- size_t free_room;
- size_t free_pages;
- /* Compaction kicks in when 3 pages or less are left. */
- const size_t max_pages = NEW_NVMEM_TOTAL_PAGES - 3;
-
- ccprintf("list index %d, data offset 0x%x\n", master_at.list_index,
- master_at.mt.data_offset);
-
- if (master_at.list_index >= max_pages)
- return 0;
-
- free_pages = max_pages - master_at.list_index;
- free_room = (free_pages - 1) * (CONFIG_FLASH_BANK_SIZE -
- sizeof(struct nn_page_header)) +
- CONFIG_FLASH_BANK_SIZE - master_at.mt.data_offset;
- ccprintf("free pages %zd, data offset 0x%x\n", free_pages,
- master_at.mt.data_offset);
- return free_room;
-}
-
-static int test_nvmem_compaction(void)
-{
- char value[100]; /* Definitely more than enough. */
- const char *key = "var 1";
- int i;
- size_t key_len;
- size_t val_len;
- size_t free_room;
- size_t real_var_size;
- size_t var_space;
- int max_vars;
- int erased_data_size;
- const size_t alignment_mask = CONFIG_FLASH_WRITE_SIZE - 1;
-
- key_len = strlen(key);
- val_len = snprintf(value, sizeof(value), "variable value is %04d", 0);
-
- TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
-
- /*
- * Remember how much room was erased before flooding nvmem with erased
- * values.
- */
- erased_data_size = test_result.erased_data_size;
-
- /* Let's see how much free room there is. */
- free_room = get_free_nvmem_room();
- TEST_ASSERT(free_room);
-
- /* How much room (key, value) pair takes in a container. */
- real_var_size = val_len + key_len + sizeof(struct tuple);
- /*
- * See how many vars including containers should be able to fit there.
- *
- * First calculate rounded up space a var will take. Apart from the
- * var itself there will be a container header and a delimiter.
- */
- var_space = (real_var_size + 2 * sizeof(struct nn_container) +
- alignment_mask) & ~alignment_mask;
-
- max_vars = free_room / var_space;
-
- /*
- * And now flood the NVMEM with erased values (each new setvar()
- * invocation erases the previous instance.
- */
- for (i = 0; i <= max_vars; i++) {
- snprintf(value, sizeof(value), "variable value is %04d", i);
- TEST_ASSERT(setvar(key, key_len, value, val_len) == EC_SUCCESS);
- }
-
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- /* Make sure there was no compaction yet. */
- TEST_ASSERT(test_result.erased_data_size > erased_data_size);
-
- /* This is how much the erased space grew as a result of flooding. */
- erased_data_size = test_result.erased_data_size - erased_data_size;
- TEST_ASSERT(erased_data_size == max_vars * real_var_size);
-
- /* This will take it over the compaction limit. */
- val_len = snprintf(value, sizeof(value), "variable value is %03d", i);
- TEST_ASSERT(setvar(key, key_len, value, val_len) == EC_SUCCESS);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- TEST_ASSERT(test_result.erased_data_size < var_space);
-
- return EC_SUCCESS;
-}
-
-static int test_configured_nvmem(void)
-{
- /*
- * The purpose of this test is to check how nvmem_init() initializes
- * from previously saved flash contents.
- */
- TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
-
- /*
- * This is initialization from legacy flash contents which replaces
- * legacy flash image with the new format flash image
- */
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /* And this is initialization from the new flash layout. */
- return nvmem_init();
-}
-
-static uint8_t find_lb(const void *data)
-{
- return (const uint8_t *)memchr(data, '#', 256) - (const uint8_t *)data;
-}
-
-/*
- * Helper function, depending on the argument value either writes variables
- * into nvmem and verifies their presence, or deletes them and verifies that
- * they indeed disappear.
- */
-static int var_read_write_delete_helper(int do_write)
-{
- size_t i;
- uint16_t saved_total_var_space;
- uint32_t coverage_map;
-
- const struct {
- uint8_t *key;
- uint8_t *value;
- } kv_pairs[] = {
- /* Use # as the delimiter to allow \0 in keys/values. */
- {"\0key\00#", "value of key2#"}, {"key1#", "value of key1#"},
- {"key2#", "value of key2#"}, {"key3#", "value of\0 key3#"},
- {"ke\04#", "value\0 of\0 key4#"},
- };
-
- coverage_map = 0;
- saved_total_var_space = total_var_space;
-
- /*
- * Read all vars, one at a time, verifying that they shows up in
- * getvar results when appropriate but not before.
- */
- for (i = 0; i <= ARRAY_SIZE(kv_pairs); i++) {
- size_t j;
- uint8_t key_len;
- uint8_t val_len;
- const void *value;
-
- for (j = 0; j < ARRAY_SIZE(kv_pairs); j++) {
- const struct tuple *t;
-
- coverage_map |= 1;
-
- key_len = find_lb(kv_pairs[j].key);
- t = getvar(kv_pairs[j].key, key_len);
-
- if ((j >= i) ^ !do_write) {
- TEST_ASSERT(t == NULL);
- continue;
- }
-
- coverage_map |= 2;
-
- TEST_ASSERT(saved_total_var_space == total_var_space);
-
- /* Confirm that what we found is the right variable. */
- val_len = find_lb(kv_pairs[j].value);
-
- TEST_ASSERT(t->key_len == key_len);
- TEST_ASSERT(t->val_len == val_len);
- TEST_ASSERT(
- !memcmp(kv_pairs[j].key, t->data_, key_len));
- TEST_ASSERT(!memcmp(kv_pairs[j].value,
- t->data_ + key_len, val_len));
- freevar(t);
- }
-
- if (i == ARRAY_SIZE(kv_pairs)) {
- coverage_map |= 4;
- /* All four variables have been processed. */
- break;
- }
-
- val_len = find_lb(kv_pairs[i].value);
- key_len = find_lb(kv_pairs[i].key);
- value = kv_pairs[i].value;
- if (!do_write) {
-
- coverage_map |= 8;
-
- saved_total_var_space -= val_len + key_len;
- /*
- * Make sure all val_len == 0 and val == NULL
- * combinations are exercised.
- */
- switch (i) {
- case 0:
- val_len = 0;
- coverage_map |= 0x10;
- break;
-
- case 1:
- coverage_map |= 0x20;
- value = NULL;
- break;
- default:
- coverage_map |= 0x40;
- val_len = 0;
- value = NULL;
- break;
- }
- } else {
- coverage_map |= 0x80;
- saved_total_var_space += val_len + key_len;
- }
- key_len = find_lb(kv_pairs[i].key);
- TEST_ASSERT(setvar(kv_pairs[i].key, key_len, value, val_len) ==
- EC_SUCCESS);
-
- TEST_ASSERT(saved_total_var_space == total_var_space);
- }
-
- if (do_write)
- TEST_ASSERT(coverage_map == 0x87);
- else
- TEST_ASSERT(coverage_map == 0x7f);
-
- return EC_SUCCESS;
-}
-
-static int test_var_read_write_delete(void)
-{
- TEST_ASSERT(post_init_from_scratch(0xff) == EC_SUCCESS);
-
- ccprintf("\n%s: starting write cycle\n", __func__);
- TEST_ASSERT(var_read_write_delete_helper(1) == EC_SUCCESS);
-
- ccprintf("%s: starting delete cycle\n", __func__);
- TEST_ASSERT(var_read_write_delete_helper(0) == EC_SUCCESS);
-
- return EC_SUCCESS;
-}
-
-static int test_nvmem_tuple_capacity(void)
-{
- char key[5];
- char value[18];
- int rv;
-
- /* Does not matter, but for consistency let's init key and value. */
- memset(key, 0, sizeof(key));
- memset(value, 0, sizeof(value));
-
- TEST_ASSERT(post_init_from_scratch(0xff) == EC_SUCCESS);
-
- /* Fill up var space until it is full. */
- while (1) {
- rv = setvar(key, sizeof(key), value, sizeof(value) - 1);
- if (rv != EC_SUCCESS)
- break;
- key[0]++;
- }
- TEST_ASSERT(rv == EC_ERROR_OVERFLOW);
- iterate_over_flash();
-
- /*
- * Verify that total variable size is as expected. We know that the
- * allotted space will not exactly fit a number of tuples, so the
- * check is that the total tuple data size is smaller than the space.
- *
- * If some parameters change in the future such that this assumption
- * becomes wrong, the test in the next line would fail.
- */
- TEST_ASSERT(test_result.tuple_data_size < MAX_VAR_TOTAL_SPACE);
- TEST_ASSERT((MAX_VAR_TOTAL_SPACE - test_result.tuple_data_size) <
- (sizeof(key) + sizeof(value) - 1));
-
- /*
- * Verify that it is still possible to modify a variable when storage
- * is almost full and the new value is larger than the old value.
- */
- key[0]--;
- value[0]++;
- TEST_ASSERT(setvar(key, sizeof(key),
- value, sizeof(value)) == EC_SUCCESS);
-
- return EC_SUCCESS;
-}
-
-/* Verify that nvmem_erase_user_data only erases the given user's data. */
-static int test_nvmem_erase_tpm_data(void)
-{
- TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- browse_flash_contents(1);
- TEST_ASSERT(nvmem_erase_tpm_data() == EC_SUCCESS);
- browse_flash_contents(1);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- TEST_ASSERT(test_result.deleted_obj_count == 0);
- TEST_ASSERT(test_result.var_count == 3);
- TEST_ASSERT(test_result.reserved_obj_count == 38);
- TEST_ASSERT(test_result.evictable_obj_count == 0);
- TEST_ASSERT(test_result.unexpected_count == 0);
- TEST_ASSERT(test_result.valid_data_size == 1174);
- TEST_ASSERT(test_result.erased_data_size == 0);
-
- return EC_SUCCESS;
-}
-
-static size_t fill_obj_offsets(uint16_t *offsets, size_t max_objects)
-{
- size_t i;
- size_t obj_count;
-
- obj_count = init_object_offsets(offsets, max_objects);
-
- ccprintf("%zd objects\n", obj_count);
- for (i = 0; i < obj_count; i++) {
- uint32_t *op;
-
- op = evictable_offs_to_addr(offsets[i]);
- ccprintf("offs %04x:%08x:%08x:%08x addr %pP size %zd\n",
- offsets[i], op[-1], op[0], op[1], op,
- (uintptr_t)nvmem_cache_base(NVMEM_TPM) + op[-1] -
- (uintptr_t)op);
- }
-
- return obj_count;
-}
-
-static size_t fill_cache_offsets(const void *cache, uint16_t *offsets,
- size_t max_objects)
-{
- uint8_t buf[nvmem_user_sizes[NVMEM_TPM]];
- void *real_cache;
- size_t num_offsets;
-
- real_cache = nvmem_cache_base(NVMEM_TPM);
- memcpy(buf, real_cache, sizeof(buf));
-
- memcpy(real_cache, cache, sizeof(buf));
- memset(offsets, 0, sizeof(*offsets) * max_objects);
- num_offsets = fill_obj_offsets(offsets, max_objects);
-
- /* Restore the real cache. */
- memcpy(real_cache, buf, sizeof(buf));
-
- return num_offsets;
-}
-#define MAX_OFFSETS 20
-
-static uint32_t get_evict_size(const uint8_t *cache, uint16_t offset)
-{
- uint32_t next_addr;
- uint32_t cache_offset;
-
- cache_offset = s_evictNvStart + offset;
- memcpy(&next_addr, cache + cache_offset - sizeof(next_addr),
- sizeof(next_addr));
-
- return next_addr - cache_offset;
-}
-
-/* Returns zero if the two objects are identical. */
-static int compare_objects(const uint8_t *cache1, uint16_t offset1,
- const uint8_t *cache2, uint16_t offset2)
-{
- uint32_t size1;
- uint32_t size2;
-
- size1 = get_evict_size(cache1, offset1);
- size2 = get_evict_size(cache2, offset2);
-
- if (size1 == size2)
- return memcmp(cache1 + s_evictNvStart + offset1,
- cache2 + s_evictNvStart + offset2, size1);
-
- return 1;
-}
-/*
- * Compare two instances of NVMEM caches. Reserved spaces should be exactly
- * the same for the match, but evictable objects could be rearranged due to
- * compaction, updating, etc.
- *
- * For the two cache instances to be considered the same the sets and contents
- * of the evictable object spaces must also match object to object.
- */
-static int caches_match(const uint8_t *cache1, const uint8_t *cache2)
-{
- int failed_count;
- size_t cache1_offs_count;
- size_t cache2_offs_count;
- size_t i;
- uint16_t cache1_offsets[MAX_OFFSETS];
- uint16_t cache2_offsets[MAX_OFFSETS];
-
- for (failed_count = i = 0; i < NV_PSEUDO_RESERVE_LAST; i++) {
- NV_RESERVED_ITEM ri;
- struct {
- uint32_t offset;
- uint32_t size;
- } ranges[3];
- size_t j;
-
- NvGetReserved(i, &ri);
-
- ranges[0].offset = ri.offset;
-
- if (i != NV_STATE_CLEAR) {
- ranges[0].size = ri.size;
- ranges[1].size = 0;
- } else {
- ranges[0].size = offsetof(STATE_CLEAR_DATA, pcrSave);
- ranges[1].offset = ranges[0].offset + ranges[0].size;
- ranges[1].size = sizeof(PCR_SAVE);
- ranges[2].offset = ranges[1].offset + ranges[1].size;
- ranges[2].size = sizeof(PCR_AUTHVALUE);
- }
-
- for (j = 0; j < ARRAY_SIZE(ranges); j++) {
-
- uint32_t offset;
- uint32_t size;
- uint32_t k;
-
- size = ranges[j].size;
- if (!size)
- break;
-
- offset = ranges[j].offset;
-
- if (!memcmp(cache1 + offset, cache2 + offset, size))
- continue;
-
- ccprintf("%s:%d failed comparing %zd:%zd:\n", __func__,
- __LINE__, i, j);
- for (k = offset; k < (offset + size); k++)
- if (cache1[k] != cache2[k])
- ccprintf(" %3d:%02x", k - offset,
- cache1[k]);
- ccprintf("\n");
- for (k = offset; k < (offset + size); k++)
- if (cache1[k] != cache2[k])
- ccprintf(" %3d:%02x", k - offset,
- cache2[k]);
- ccprintf("\n");
-
- failed_count++;
- }
- }
-
- TEST_ASSERT(!failed_count);
-
- cache1_offs_count = fill_cache_offsets(cache1, cache1_offsets,
- ARRAY_SIZE(cache1_offsets));
- cache2_offs_count = fill_cache_offsets(cache2, cache2_offsets,
- ARRAY_SIZE(cache2_offsets));
-
- TEST_ASSERT(cache1_offs_count == cache2_offs_count);
-
- for (i = 0; (i < ARRAY_SIZE(cache1_offsets)) && cache2_offs_count;
- i++) {
- size_t j;
-
- for (j = 0; j < cache2_offs_count; j++) {
- if (compare_objects(cache1, cache1_offsets[i], cache2,
- cache2_offsets[j]))
- continue;
- /* Remove object from the cache2 offsets. */
- cache2_offsets[j] = cache2_offsets[--cache2_offs_count];
- break;
- }
- }
-
- TEST_ASSERT(cache2_offs_count == 0);
- return EC_SUCCESS;
-}
-
-static int prepare_post_migration_nvmem(void)
-{
- TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- return EC_SUCCESS;
-}
-/*
- * This test creates various failure conditions related to interrupted nvmem
- * save operations and verifies that transaction integrity is maintained -
- * i.e. either all variables get updated,
- */
-static int test_nvmem_incomplete_transaction(void)
-{
- /*
- * Will be more than enough, we can't store more than 15 objects or so
- * anyways.
- */
- uint16_t offsets[MAX_OFFSETS];
- size_t num_objects;
- uint8_t buf[nvmem_user_sizes[NVMEM_TPM]];
- uint8_t *p;
- size_t object_size;
- union entry_u e;
-
- TEST_ASSERT(prepare_post_migration_nvmem() == EC_SUCCESS);
- num_objects = fill_obj_offsets(offsets, ARRAY_SIZE(offsets));
- TEST_ASSERT(num_objects == 9);
-
- /* Save cache state before deleting objects. */
- memcpy(buf, nvmem_cache_base(NVMEM_TPM), sizeof(buf));
-
- drop_evictable_obj(evictable_offs_to_addr(offsets[4]));
- drop_evictable_obj(evictable_offs_to_addr(offsets[3]));
-
- failure_mode = TEST_FAIL_WHEN_SAVING;
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- wipe_out_nvmem_cache();
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- TEST_ASSERT(caches_match(buf, nvmem_cache_base(NVMEM_TPM)) ==
- EC_SUCCESS);
- drop_evictable_obj(evictable_offs_to_addr(offsets[4]));
- drop_evictable_obj(evictable_offs_to_addr(offsets[3]));
-
- /* Check if failure when invalidating is recovered after restart. */
- failure_mode = TEST_FAIL_WHEN_INVALIDATING;
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- ccprintf("%s:%d\n", __func__, __LINE__);
- wipe_out_nvmem_cache();
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- ccprintf("%s:%d\n", __func__, __LINE__);
- num_objects = fill_obj_offsets(offsets, ARRAY_SIZE(offsets));
- TEST_ASSERT(num_objects == 7);
-
- /*
- * Now, let's modify an object and introduce corruption when saving
- * it.
- */
- p = evictable_offs_to_addr(offsets[4]);
- p[10] ^= 0x55;
- failure_mode = TEST_FAILED_HASH;
- new_nvmem_save();
- failure_mode = TEST_NO_FAILURE;
-
- /* And verify that nvmem can still successfully initialize. */
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /*
- * Now let's interrupt saving an object spanning two pages.
- *
- * First, fill up the current page to get close to the limit such that
- * the next save will have to span two flash pages.
- */
- object_size = offsets[4] - offsets[3];
- p = (uint8_t *)evictable_offs_to_addr(offsets[3]) + object_size - 10;
- while ((master_at.mt.data_offset + object_size +
- sizeof(struct nn_container)) <= CONFIG_FLASH_BANK_SIZE) {
- (*p)++;
- new_nvmem_save();
- }
-
- /* This will trigger spilling over the page boundary. */
- (*p)++;
- failure_mode = TEST_SPANNING_PAGES;
- new_nvmem_save();
- failure_mode = TEST_NO_FAILURE;
-
- /* Drain the event log. */
- e.r.timestamp = 0;
- while (flash_log_dequeue_event(e.r.timestamp, e.entry, sizeof(e)) > 0)
- ;
-
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /* Let's verify that a container mismatch event has been added. */
- TEST_ASSERT(flash_log_dequeue_event(e.r.timestamp, e.entry, sizeof(e))
- > 0);
- TEST_ASSERT(e.r.type == FE_LOG_NVMEM);
- TEST_ASSERT(e.r.payload[0] == NVMEMF_CONTAINER_HASH_MISMATCH);
- return EC_SUCCESS;
-}
-
-/*
- * Verify that interrupted compaction results in a consistent state of the
- * NVMEM cache.
- */
-static int test_nvmem_interrupted_compaction(void)
-{
- uint8_t buf[nvmem_user_sizes[NVMEM_TPM]];
- uint8_t target_list_index;
- uint8_t filler = 1;
-
- TEST_ASSERT(prepare_post_migration_nvmem() == EC_SUCCESS);
-
- /* Let's fill up a couple of pages with erased objects. */
- target_list_index = master_at.list_index + 2;
-
- do {
- /*
- * A few randomly picked reserved objects to modify to create
- * need for compaction.
- */
- const uint8_t objs_to_modify[] = {1, 3, 19, 42};
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(objs_to_modify); i++) {
- NV_RESERVED_ITEM ri;
-
- NvGetReserved(i, &ri);
-
- /* Direct access to the object. */
- memset((uint8_t *)nvmem_cache_base(NVMEM_TPM) +
- ri.offset,
- filler++, ri.size);
- }
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- } while (master_at.list_index != target_list_index);
-
- /* Save the state of NVMEM cache. */
- memcpy(buf, nvmem_cache_base(NVMEM_TPM), sizeof(buf));
- failure_mode = TEST_FAIL_WHEN_COMPACTING;
- compact_nvmem();
- wipe_out_nvmem_cache();
- ccprintf("%s:%d\n", __func__, __LINE__);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- TEST_ASSERT(caches_match(buf, nvmem_cache_base(NVMEM_TPM)) ==
- EC_SUCCESS);
- return EC_SUCCESS;
-}
-
-int nvmem_first_task(void *unused)
-{
- return EC_SUCCESS;
-}
-
-int nvmem_second_task(void *unused)
-{
- return EC_SUCCESS;
-}
-
-static void run_test_setup(void)
-{
- /* Allow Flash erase/writes */
- flash_write_fail = 0;
- test_reset();
-}
-
-void nvmem_wipe_cache(void)
-{
-}
-
-int DCRYPTO_ladder_is_enabled(void)
-{
- return 1;
-}
-
-static int test_migration(void)
-{
- /*
- * This purpose of this test is to verify migration of the 'legacy'
- * TPM NVMEM format to the new scheme where each element is stored in
- * flash in its own container.
- */
- TEST_ASSERT(prepare_nvmem_contents() == EC_SUCCESS);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- TEST_ASSERT(iterate_over_flash() == EC_SUCCESS);
- TEST_ASSERT(test_result.var_count == 3);
- TEST_ASSERT(test_result.reserved_obj_count == 40);
- TEST_ASSERT(test_result.evictable_obj_count == 9);
- TEST_ASSERT(test_result.delimiter_count == 1);
- TEST_ASSERT(test_result.deleted_obj_count == 0);
- TEST_ASSERT(test_result.unexpected_count == 0);
- TEST_ASSERT(test_result.valid_data_size == 5214);
- TEST_ASSERT(total_var_space == 77);
- /* Container pointer not yet set. */
- TEST_ASSERT(!master_at.ct.data_offset && !master_at.ct.ph);
- return EC_SUCCESS;
-}
-
-/*
- * The purpose of this test is to verify variable storage limits, both per
- * object and total.
- */
-static int test_var_boundaries(void)
-{
- const size_t max_size = 255; /* Key and value must fit in a byte. */
- const uint8_t *key;
- const uint8_t *val;
- size_t key_len;
- size_t val_len;
- uint16_t saved_total_var_space;
- uint32_t coverage_map;
- uint8_t var_key[10];
-
- TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
- saved_total_var_space = total_var_space;
- coverage_map = 0;
-
- /*
- * Let's use the legacy NVMEM image as a source of fairly random but
- * reproducible data.
- */
- key = legacy_nvmem_image;
- val = legacy_nvmem_image;
-
- /*
- * Test limit of max variable body space, use keys and values of
- * different sizes, below and above the limit.
- */
- for (key_len = 1; key_len < max_size; key_len += 20) {
-
- coverage_map |= 1;
-
- val_len = MIN(max_size, MAX_VAR_BODY_SPACE - key_len);
- TEST_ASSERT(setvar(key, key_len, val, val_len) == EC_SUCCESS);
- TEST_ASSERT(total_var_space ==
- saved_total_var_space + key_len + val_len);
-
- /* Now drop the variable from the storage. */
- TEST_ASSERT(setvar(key, key_len, NULL, 0) == EC_SUCCESS);
- TEST_ASSERT(total_var_space == saved_total_var_space);
-
- /* And if key length allows it, try to write too much. */
- if (val_len == max_size)
- continue;
-
- coverage_map |= 2;
- /*
- * Yes, let's try writing one byte too many and see that the
- * attempt is rejected.
- */
- val_len++;
- TEST_ASSERT(setvar(key, key_len, val, val_len) ==
- EC_ERROR_INVAL);
- TEST_ASSERT(total_var_space == saved_total_var_space);
- }
-
- /*
- * Test limit of max total variable space, use keys and values of
- * different sizes, below and above the limit.
- */
- key_len = sizeof(var_key);
- val_len = 20; /* Anything below 256 would work. */
- memset(var_key, 'x', key_len);
-
- while (1) {
- int rv;
-
- /*
- * Change the key so that a new variable is added to the
- * storage.
- */
- rv = setvar(var_key, key_len, val, val_len);
-
- if (rv == EC_ERROR_OVERFLOW)
- break;
-
- coverage_map |= 4;
- TEST_ASSERT(rv == EC_SUCCESS);
- var_key[0]++;
- saved_total_var_space += key_len + val_len;
- }
-
- TEST_ASSERT(saved_total_var_space == total_var_space);
- TEST_ASSERT(saved_total_var_space <= MAX_VAR_TOTAL_SPACE);
- TEST_ASSERT((saved_total_var_space + key_len + val_len) >
- MAX_VAR_TOTAL_SPACE);
-
- TEST_ASSERT(coverage_map == 7);
- return EC_SUCCESS;
-}
-
-static int verify_ram_index_space(size_t verify_size)
-{
- NV_RESERVED_ITEM ri;
- size_t i;
- uint32_t casted_size;
- uint8_t byte;
- uint8_t fill_byte = 0x55;
-
- if (verify_size > RAM_INDEX_SPACE)
- return EC_ERROR_INVAL;
-
- NvGetReserved(NV_RAM_INDEX_SPACE, &ri);
-
- /*
- * Save the size of the index space, needed on machines where size_t
- * is a 64 bit value.
- */
- casted_size = verify_size;
-
- /*
- * Now write index space in the cache, we write the complete space,
- * but on read back only verify_size bytes are expected to be set.
- */
- nvmem_write(ri.offset, sizeof(casted_size), &casted_size, NVMEM_TPM);
-
- for (i = 0; i < RAM_INDEX_SPACE; i++)
- nvmem_write(ri.offset + sizeof(casted_size) + i,
- sizeof(fill_byte), &fill_byte, NVMEM_TPM);
-
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- wipe_out_nvmem_cache();
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /* Make sure read back size matches. */
- nvmem_read(ri.offset, sizeof(casted_size), &casted_size, NVMEM_TPM);
- TEST_ASSERT(casted_size == verify_size);
-
- /*
- * Now check spaces which were supposed to be written (up to
- * verify_size) and left intact.
- */
- for (i = 0; i < RAM_INDEX_SPACE; i++) {
- nvmem_read(ri.offset + sizeof(casted_size) + i, sizeof(byte),
- &byte, NVMEM_TPM);
- if (i < verify_size)
- TEST_ASSERT(byte == fill_byte);
- else
- TEST_ASSERT(byte == 0);
- }
-
- return EC_SUCCESS;
-}
-
-static int test_tpm_nvmem_modify_reserved_objects(void)
-{
- NV_RESERVED_ITEM ri;
- /* Some random reserved objects' indices. */
- const uint8_t res_obj_ids[] = {1, 4, 9, 20};
- size_t i;
- static uint8_t cache_copy[12 * 1024];
- struct nvmem_test_result old_result;
- uint64_t new_values[ARRAY_SIZE(res_obj_ids)];
- size_t erased_size;
-
- TEST_ASSERT(sizeof(cache_copy) >= nvmem_user_sizes[NVMEM_TPM]);
- TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- iterate_over_flash();
- old_result = test_result;
-
- /* Preserve NVMEM cache for future comparison. */
- memcpy(cache_copy, nvmem_cache_base(NVMEM_TPM),
- nvmem_user_sizes[NVMEM_TPM]);
-
- erased_size = 0;
- /* Modify several reserved objects in the cache. */
- for (i = 0; i < ARRAY_SIZE(res_obj_ids); i++) {
- size_t copy_size;
- uint8_t *addr_in_cache;
- size_t k;
-
- NvGetReserved(res_obj_ids[i], &ri);
- copy_size = MIN(sizeof(new_values[0]), ri.size);
- addr_in_cache =
- (uint8_t *)nvmem_cache_base(NVMEM_TPM) + ri.offset;
-
- /* Prepare a new value for the variable. */
- memcpy(new_values + i, addr_in_cache, copy_size);
- for (k = 0; k < copy_size; k++)
- ((uint8_t *)(new_values + i))[k] ^= 0x55;
-
- /* Update value in the cache. */
- memcpy(addr_in_cache, new_values + i, copy_size);
-
- /* And in the cache copy. */
- memcpy(cache_copy + ri.offset, new_values + i, copy_size);
-
- /*
- * This much will be added to the erased space, object size
- * plus index size.
- */
- erased_size += ri.size + 1;
- }
-
- /* Save it into flash. */
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
-
- /* Wipe out the cache to be sure. */
- wipe_out_nvmem_cache();
-
- /* Read NVMEM contents from flash. */
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /* Verify that the cache matches expectations. */
- TEST_ASSERT(!memcmp(cache_copy, nvmem_cache_base(NVMEM_TPM),
- nvmem_user_sizes[NVMEM_TPM]));
-
- iterate_over_flash();
-
- /* Update previous results with our expectations. */
- old_result.deleted_obj_count += ARRAY_SIZE(res_obj_ids);
- old_result.erased_data_size += erased_size;
- old_result.delimiter_count++;
-
- TEST_ASSERT(!memcmp(&test_result, &old_result, sizeof(test_result)));
-
- /* Verify several index space cases. */
- for (i = 0; i <= RAM_INDEX_SPACE; i += (RAM_INDEX_SPACE / 2))
- TEST_ASSERT(verify_ram_index_space(i) == EC_SUCCESS);
-
- return EC_SUCCESS;
-}
-
-static int compare_object(uint16_t obj_offset, size_t obj_size, const void *obj)
-{
- uint32_t next_addr;
-
- memcpy(&next_addr,
- evictable_offs_to_addr(obj_offset - sizeof(next_addr)),
- sizeof(next_addr));
-
- ccprintf("next_addr %x, sum %zx size %zd\n", next_addr,
- (s_evictNvStart + obj_offset + obj_size), obj_size);
- TEST_ASSERT(next_addr == (s_evictNvStart + obj_offset + obj_size));
-
- if (!memcmp(evictable_offs_to_addr(obj_offset), obj, obj_size))
- return EC_SUCCESS;
-
- return EC_ERROR_INVAL;
-}
-
-static int test_tpm_nvmem_modify_evictable_objects(void)
-{
- size_t num_objects;
- uint16_t offsets[MAX_OFFSETS];
- uint32_t handles[ARRAY_SIZE(offsets)];
- uint32_t new_evictable_object[30];
- size_t i;
- const uint32_t new_obj_handle = 0x100;
- static uint8_t modified_obj[CONFIG_FLASH_BANK_SIZE];
- size_t modified_obj_size;
- uint32_t modified_obj_handle;
- uint32_t deleted_obj_handle;
- uint8_t *obj_cache_addr;
- size_t num_handles;
- int new_obj_index;
- int modified_obj_index;
-
- TEST_ASSERT(prepare_new_flash() == EC_SUCCESS);
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- iterate_over_flash();
-
- /* Verify that all evictable objects are there. */
- num_objects = fill_obj_offsets(offsets, ARRAY_SIZE(offsets));
- TEST_ASSERT(num_objects == 9);
- num_handles = num_objects;
-
- /* Save handles of all objects there are. */
- for (i = 0; i < num_objects; i++) {
- memcpy(handles + i, evictable_offs_to_addr(offsets[i]),
- sizeof(handles[i]));
- ccprintf("obj %zd handle %08x\n", i, handles[i]);
- }
- /*
- * Let's modify the object which currently is stored second in the
- * stack.
- */
- modified_obj_size = offsets[3] - offsets[2] - sizeof(uint32_t);
-
- /* Modify the object and copy modified value into local buffer. */
- obj_cache_addr = evictable_offs_to_addr(offsets[2]);
- memcpy(&modified_obj_handle, obj_cache_addr,
- sizeof(modified_obj_handle));
-
- for (i = 0; i < modified_obj_size; i++) {
- uint8_t c;
-
- c = obj_cache_addr[i];
-
- if (i >= sizeof(uint32_t)) { /* Preserve the 4 byte handle. */
- c ^= 0x55;
- obj_cache_addr[i] = c;
- }
- modified_obj[i] = c;
- }
-
- /* Save its handle and then drop the object at offset 5. */
- memcpy(&deleted_obj_handle, evictable_offs_to_addr(offsets[5]),
- sizeof(deleted_obj_handle));
- drop_evictable_obj(evictable_offs_to_addr(offsets[5]));
-
- /* Prepare the new evictable object, first four bytes are the handle. */
- for (i = 0; i < ARRAY_SIZE(new_evictable_object); i++)
- new_evictable_object[i] = new_obj_handle + i;
-
- /* Add it to the cache. */
- add_evictable_obj(new_evictable_object, sizeof(new_evictable_object));
-
- /* Save the new cache state in the flash. */
- TEST_ASSERT(new_nvmem_save() == EC_SUCCESS);
-
- /* Wipe out NVMEM cache just in case. */
- wipe_out_nvmem_cache();
-
- /* Read back from flash into cache. */
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /* One object removed, one added, the number should have not changed. */
- TEST_ASSERT(num_objects ==
- fill_obj_offsets(offsets, ARRAY_SIZE(offsets)));
-
- new_obj_index = 0;
- modified_obj_index = 0;
- for (i = 0; i < num_objects; i++) {
- uint32_t handle;
- size_t j;
-
- memcpy(&handle, evictable_offs_to_addr(offsets[i]),
- sizeof(handles[i]));
- ASSERT(handle != deleted_obj_handle);
-
- if (handle == new_obj_handle)
- new_obj_index = i;
- else if (handle == modified_obj_handle)
- modified_obj_index = i;
- /*
- * Remove the found handle from the set of handles which were
- * there originally.
- */
- for (j = 0; j < num_handles; j++)
- if (handles[j] == handle) {
- num_handles--;
- handles[j] = handles[num_handles];
- break;
- }
- }
-
- /*
- * Removed object's handle is still in the array, and it should be the
- * only remaining element.
- */
- TEST_ASSERT(num_handles == 1);
- TEST_ASSERT(handles[0] == deleted_obj_handle);
- TEST_ASSERT(new_obj_index >= 0); /* New handle was seen in the cache. */
- TEST_ASSERT(modified_obj_index >=
- 0); /* Modified object was seen in the cache. */
-
- TEST_ASSERT(compare_object(offsets[new_obj_index],
- sizeof(new_evictable_object),
- new_evictable_object) == EC_SUCCESS);
- TEST_ASSERT(compare_object(offsets[modified_obj_index],
- modified_obj_size,
- modified_obj) == EC_SUCCESS);
- return EC_SUCCESS;
-}
-
-static int test_nvmem_tuple_updates(void)
-{
- size_t i;
- const char *modified_var1 = "var one after";
- const struct tuple *t;
-
- const struct {
- uint8_t *key;
- uint8_t *value;
- } kv_pairs[] = {
- /* Use # as the delimiter to allow \0 in keys/values. */
- {"key0", "var zero before"},
- {"key1", "var one before"}
- };
-
- TEST_ASSERT(post_init_from_scratch(0xff) == EC_SUCCESS);
-
- /* Save vars in the nvmem. */
- for (i = 0; i < ARRAY_SIZE(kv_pairs); i++)
- TEST_ASSERT(setvar(kv_pairs[i].key, strlen(kv_pairs[i].key),
- kv_pairs[i].value,
- strlen(kv_pairs[i].value)) == EC_SUCCESS);
-
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- /* Verify the vars are still there. */
- for (i = 0; i < ARRAY_SIZE(kv_pairs); i++) {
- const struct tuple *t;
-
- t = getvar(kv_pairs[i].key, strlen(kv_pairs[i].key));
- TEST_ASSERT(t);
- TEST_ASSERT(t->val_len == strlen(kv_pairs[i].value));
- TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[i].key),
- kv_pairs[i].value, t->val_len));
- freevar(t);
- }
-
- /*
- * Now, let's try updating variable 'key1' introducing various failure
- * modes.
- */
- failure_mode = TEST_FAIL_SAVING_VAR;
- TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
- modified_var1, strlen(modified_var1)) == EC_SUCCESS);
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- /* No change should be seen. */
- for (i = 0; i < ARRAY_SIZE(kv_pairs); i++) {
- t = getvar(kv_pairs[i].key, strlen(kv_pairs[i].key));
- TEST_ASSERT(t);
- TEST_ASSERT(t->val_len == strlen(kv_pairs[i].value));
- TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[i].key),
- kv_pairs[i].value, t->val_len));
- freevar(t);
- }
- failure_mode = TEST_FAIL_FINALIZING_VAR;
- TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
- modified_var1, strlen(modified_var1)) == EC_SUCCESS);
- failure_mode = TEST_NO_FAILURE;
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /* First variable should be still unchanged. */
- t = getvar(kv_pairs[0].key, strlen(kv_pairs[0].key));
- TEST_ASSERT(t);
- TEST_ASSERT(t->val_len == strlen(kv_pairs[0].value));
- TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[0].key),
- kv_pairs[0].value, t->val_len));
- freevar(t);
-
- /* Second variable should be updated. */
- t = getvar(kv_pairs[1].key, strlen(kv_pairs[1].key));
- TEST_ASSERT(t);
- TEST_ASSERT(t->val_len == strlen(modified_var1));
- TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[1].key), modified_var1,
- t->val_len));
- freevar(t);
-
- /* A corrupted attempt to update second variable. */
- failure_mode = TEST_FAIL_FINALIZING_VAR;
- TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
- kv_pairs[1].value, strlen(kv_pairs[1].value))
- == EC_SUCCESS);
- failure_mode = TEST_NO_FAILURE;
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
-
- /* Is there an instance of the second variable still in the flash. */
- t = getvar(kv_pairs[1].key, strlen(kv_pairs[1].key));
- TEST_ASSERT(t);
- freevar(t);
-
- /* Delete the remaining instance of the variable. */
- TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
- NULL, 0) == EC_SUCCESS);
-
- /* Verify that it is indeed deleted before and after re-init. */
- TEST_ASSERT(!getvar(kv_pairs[1].key, strlen(kv_pairs[1].key)));
- TEST_ASSERT(nvmem_init() == EC_SUCCESS);
- TEST_ASSERT(!getvar(kv_pairs[1].key, strlen(kv_pairs[1].key)));
-
- return EC_SUCCESS;
-}
-
-void run_test(void)
-{
- run_test_setup();
-
- RUN_TEST(test_migration);
- RUN_TEST(test_corrupt_nvmem);
- RUN_TEST(test_fully_erased_nvmem);
- RUN_TEST(test_configured_nvmem);
- RUN_TEST(test_nvmem_save);
- RUN_TEST(test_var_read_write_delete);
- RUN_TEST(test_nvmem_compaction);
- RUN_TEST(test_var_boundaries);
- RUN_TEST(test_nvmem_erase_tpm_data);
- RUN_TEST(test_tpm_nvmem_modify_reserved_objects);
- RUN_TEST(test_tpm_nvmem_modify_evictable_objects);
- RUN_TEST(test_nvmem_incomplete_transaction);
- RUN_TEST(test_nvmem_tuple_updates);
- failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */
- RUN_TEST(test_nvmem_tuple_capacity);
- RUN_TEST(test_nvmem_interrupted_compaction);
- failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */
-
- /*
- * more tests to come
- * RUN_TEST(test_lock);
- * RUN_TEST(test_malloc_blocking);
- */
-
- test_print_result();
-}
diff --git a/test/nvmem.tasklist b/test/nvmem.tasklist
deleted file mode 100644
index 43afb03fb5..0000000000
--- a/test/nvmem.tasklist
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Copyright 2016 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 \
- TASK_TEST(NV_1, nvmem_first_task, NULL, 384) \
- TASK_TEST(NV_2, nvmem_second_task, NULL, 384)
diff --git a/test/nvmem_tpm2_mock.c b/test/nvmem_tpm2_mock.c
deleted file mode 100644
index a6d32bcb34..0000000000
--- a/test/nvmem_tpm2_mock.c
+++ /dev/null
@@ -1,377 +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. */
-
-#include "nvmem_test.h"
-
-#include "console.h"
-#include "nvmem.h"
-#include "util.h"
-
-#define NVMEM_CR50_SIZE 272
-
-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)
-
-uint32_t nvmem_user_sizes[NVMEM_NUM_USERS] = {MOCK_NV_MEMORY_SIZE,
- 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)
-{
- uint32_t index_size;
-
- if (index >= ARRAY_SIZE(res_sizes)) {
- ri->size = 0;
- return;
- }
-
- ri->offset = res_addrs[index];
- if (index != NV_RAM_INDEX_SPACE) {
- ri->size = res_sizes[index];
- return;
- }
-
- memcpy(&index_size, nvmem_cache_base(NVMEM_TPM) + ri->offset,
- sizeof(index_size));
-
- if (index_size == ~0)
- /* Must be starting with empty flash memeory. */
- index_size = 0;
-
- ri->size = index_size + sizeof(index_size);
-}
-
-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);
-}
-
-#define ITER_INIT (~0)
-
-static void *get_cache_addr(size_t offset)
-{
- return (void *)(((uintptr_t)nvmem_cache_base(NVMEM_TPM)) + offset);
-}
-
-static void read_from_cache(size_t offset, size_t size, void *dest)
-{
- nvmem_read(offset, size, dest, NVMEM_TPM);
-}
-
-static void write_to_cache(size_t offset, size_t size, void *src)
-{
- nvmem_write(offset, size, src, NVMEM_TPM);
-}
-
-/* Copies of the appropriate functions from NV.c in TPM2 library. */
-static uint32_t nv_next(uint32_t *iter)
-{
- uint32_t currentIter;
-
- if (*iter == ITER_INIT)
- *iter = s_evictNvStart;
-
- if ((*iter + sizeof(uint32_t) > s_evictNvEnd) || !*iter)
- return 0;
-
- currentIter = *iter;
- read_from_cache(*iter, sizeof(uint32_t), iter);
- if (!*iter || (*iter == ITER_INIT))
- return 0;
-
- return currentIter + sizeof(uint32_t);
-}
-
-static uint32_t nv_get_end(void)
-{
- uint32_t iter = ITER_INIT;
- uint32_t endAddr = s_evictNvStart;
- uint32_t currentAddr;
-
- while ((currentAddr = nv_next(&iter)) != 0)
- endAddr = currentAddr;
-
- if (endAddr != s_evictNvStart) {
- /* Read offset. */
- endAddr -= sizeof(uint32_t);
- read_from_cache(endAddr, sizeof(uint32_t), &endAddr);
- }
- return endAddr;
-}
-
-size_t add_evictable_obj(void *obj, size_t obj_size)
-{
- uint32_t end_addr;
- uint32_t next_addr;
- uint32_t list_end = 0;
-
- end_addr = nv_get_end();
-
- next_addr = end_addr + sizeof(uint32_t) + obj_size;
-
- if (next_addr >= s_evictNvEnd) {
- ccprintf("%s: could not fit %zd bytes!\n", __func__, obj_size);
- return 0;
- }
-
- /* Write next pointer */
- write_to_cache(end_addr, sizeof(uint32_t), &next_addr);
- /* Write entity data. */
- write_to_cache(end_addr + sizeof(uint32_t), obj_size, obj);
-
- /* Write the end of list if it fits. */
- if (next_addr + sizeof(uint32_t) <= s_evictNvEnd)
- write_to_cache(next_addr, sizeof(list_end), &list_end);
-
- return obj_size;
-}
-
-/*
- * It is the responsibility of the caller to pass the proper address of an
- * object in the cache.
- */
-void drop_evictable_obj(void *obj)
-{
- uint32_t next_addr;
- uint32_t list_end = 0;
- uint32_t obj_addr;
-
- obj_addr = (uintptr_t)obj - (uintptr_t)nvmem_cache_base(NVMEM_TPM);
- read_from_cache(obj_addr - sizeof(next_addr), sizeof(next_addr),
- &next_addr);
- ccprintf("%s:%d dropping obj at cache addr %x, offset %x, addr %pP "
- "next addr %x aka %x (off s_evictNvStart)\n",
- __func__, __LINE__, obj_addr - s_evictNvStart, obj_addr, obj,
- next_addr, next_addr - s_evictNvStart);
-
- /*
- * Now, to make it easier to add objects behind the current one, let's
- * pretend there is no more objects.
- */
- write_to_cache(obj_addr - sizeof(next_addr), sizeof(list_end),
- &list_end);
-
- if (!next_addr || (next_addr == s_evictNvEnd))
- return;
-
- /*
- * Iterate over objects starting with next_addr, copying them into
- * obj_addr.
- */
- obj_addr = next_addr;
- while (1) {
- uint32_t next_next_addr;
- uint32_t next_obj_size;
-
- read_from_cache(next_addr, sizeof(next_next_addr),
- &next_next_addr);
-
- if (!next_next_addr || (next_next_addr == s_evictNvEnd))
- return;
-
- next_obj_size = next_next_addr - obj_addr - sizeof(uint32_t);
- add_evictable_obj(
- (void *)((uintptr_t)nvmem_cache_base(NVMEM_TPM) +
- next_addr + sizeof(uint32_t)),
- next_obj_size);
- next_addr = next_next_addr;
- obj_addr += next_obj_size + sizeof(next_obj_size);
- }
-}
-
-void *evictable_offs_to_addr(uint16_t offset)
-{
- return (void *)((uintptr_t)get_cache_addr(s_evictNvStart) + offset);
-}