diff options
author | Allen Webb <allenwebb@google.com> | 2018-01-31 11:21:20 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-04-27 12:22:25 -0700 |
commit | c61479bbd82bc33c159d09958d79d633755f8735 (patch) | |
tree | 192c37e31a277b5971aeab498387022cbd1c1be9 /include/pinweaver.h | |
parent | 6e7193c4587c13d69e8f4990252623284e84893f (diff) | |
download | chrome-ec-c61479bbd82bc33c159d09958d79d633755f8735.tar.gz |
Cr50: Added Pinweaver base implementation.
This adds some of the ground work for hardware backed brute force
resistance on Cr50. The feature is called Pinweaver. It will
initially be used to enable PIN authentication on CrOS devices
without reducing the security of the platform. A Merkle tree is
used to validate encrypted metadata used to track login attempts.
The metadata tracks counts of failed attempts, a timestamp of the
last failed attempt, the secrets, and any associated parameters.
Instead of storing the metadata on Cr50 an AES-CTR is used with an
HMAC to encrypt the data so it can be stored off-chip and loaded
when needed.
The Merkle tree is used to track the current state of all the
metadata to prevent replay attacks of previously exported copies.
It is a tree of hashes whose root hash is stored on Cr50, and whose
leaves are the HMACs of the encrypted metadata.
BRANCH=none
BUG=chromium:809730, chromium:809741, chromium:809743, chromium:809747
TEST=cd ~/src/platform/ec && V=1 make run-pinweaver -j
Change-Id: Id10bb49d8ebc5a487dd90c6093bc0f51dadbd124
Signed-off-by: Allen Webb <allenwebb@google.com>
Reviewed-on: https://chromium-review.googlesource.com/895395
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'include/pinweaver.h')
-rw-r--r-- | include/pinweaver.h | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/include/pinweaver.h b/include/pinweaver.h new file mode 100644 index 0000000000..58210fa037 --- /dev/null +++ b/include/pinweaver.h @@ -0,0 +1,142 @@ +/* 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 __CROS_EC_INCLUDE_PINWEAVER_H +#define __CROS_EC_INCLUDE_PINWEAVER_H + +/* This is required before pinweaver_types.h to provide __packed and __aligned + * while preserving the ability of pinweaver_types.h to be used in code outside + * of src/platform/ec. + */ +#include <common.h> +#include <pinweaver_types.h> + +#define PW_STORAGE_VERSION 0 + +#define BITS_PER_LEVEL_MIN 1 +#define BITS_PER_LEVEL_MAX 5 +#define HEIGHT_MIN 1 +/* This will crash for logk == 0 so that condition must not be allowed when + * using this. + */ +#define HEIGHT_MAX(logk) ((sizeof(struct label_t) * 8) / logk) + +/* Persistent information used by this feature. */ +struct merkle_tree_t { + /* log2(Fan out). */ + struct bits_per_level_t bits_per_level; + /* Height of the tree or param_l / bits_per_level. */ + struct height_t height; + + /* Root hash of the Merkle tree. */ + uint8_t root[PW_HASH_SIZE]; + + /* Random bits used as part of the key derivation process. */ + uint8_t key_derivation_nonce[16]; + + /* Key used to compute the HMACs of the metadata of the leaves. */ + uint8_t PW_ALIGN_TO_WRD hmac_key[32]; + + /* Key used to encrypt and decrypt the metadata of the leaves. */ + uint8_t PW_ALIGN_TO_WRD wrap_key[32]; +}; + +/* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */ +/* Unencrypted part of the leaf data. */ +struct PW_PACKED leaf_public_data_t { + struct label_t label; + struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT]; + + /* State used to rate limit. */ + struct pw_timestamp_t timestamp; + struct attempt_count_t attempt_count; +}; + +/* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */ +/* Encrypted part of the leaf data. */ +struct PW_PACKED PW_ALIGN_TO_BLK leaf_sensitive_data_t { + uint8_t low_entropy_secret[PW_SECRET_SIZE]; + uint8_t high_entropy_secret[PW_SECRET_SIZE]; + uint8_t reset_secret[PW_SECRET_SIZE]; +}; + +/* Represents leaf data in a form that can be exported for storage. */ +struct PW_PACKED wrapped_leaf_data_t { + /* This is first so that head.leaf_version will be the first field + * in the struct to keep the meaning of the struct from becoming + * ambiguous across versions. + */ + struct leaf_header_t head; + /* Covers .head, .pub, and .cipher_text. */ + uint8_t hmac[PW_HASH_SIZE]; + uint8_t iv[PW_WRAP_BLOCK_SIZE]; + struct leaf_public_data_t pub; + uint8_t cipher_text[sizeof(struct leaf_sensitive_data_t)]; +}; + +/* Represents encrypted leaf data after the lengths and version in the header + * have been validated. + */ +struct imported_leaf_data_t { + /* This is first so that head.leaf_version will be the first field + * in the struct to keep the meaning of the struct from becoming + * ambiguous across versions. + */ + const struct leaf_header_t *head; + /* Covers .head, .pub, and .cipher_text. */ + const uint8_t *hmac; + const uint8_t *iv; + const struct leaf_public_data_t *pub; + const uint8_t *cipher_text; + const uint8_t (*hashes)[PW_HASH_SIZE]; +}; + +/* The leaf data in a clear text working format. */ +struct leaf_data_t { + struct leaf_public_data_t pub; + struct leaf_sensitive_data_t sec; +}; + +/* Handler for incoming messages after they have been reconstructed. + * + * merkle_tree->root needs to be updated with new_root outside of this function. + */ +int pw_handle_request(struct merkle_tree_t *merkle_tree, + const struct pw_request_t *request, + struct pw_response_t *response); + +/******************************************************************************/ +/* Struct helper functions. + */ + +/* Sets up pointers to the relevant fields inside an wrapped leaf based on the + * length fields in the header. These fields should be validated prior to + * calling this function. + */ +void import_leaf(const struct unimported_leaf_data_t *unimported, + struct imported_leaf_data_t *imported); + +/* Calculate how much is needed to add to the size of structs containing + * an struct unimported_leaf_data_t because the variable length fields at the + * end of the struct are not included by sizeof(). + */ +#define PW_LEAF_PAYLOAD_SIZE (sizeof(struct wrapped_leaf_data_t) - \ + sizeof(struct unimported_leaf_data_t)) + + +/******************************************************************************/ +/* Utility functions exported for better test coverage. + */ + +/* Computes the total number of the sibling hashes along a path. */ +int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree); + +/* Computes the parent hash for an array of child hashes. */ +void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes, + struct index_t location, + const uint8_t child_hash[PW_HASH_SIZE], + uint8_t result[PW_HASH_SIZE]); + +#endif /* __CROS_EC_INCLUDE_PINWEAVER_H */ |