diff options
Diffstat (limited to 'fuzz/pinweaver_model.h')
-rw-r--r-- | fuzz/pinweaver_model.h | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/fuzz/pinweaver_model.h b/fuzz/pinweaver_model.h new file mode 100644 index 0000000000..84508786f3 --- /dev/null +++ b/fuzz/pinweaver_model.h @@ -0,0 +1,123 @@ +// 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 |