mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-14 08:36:39 +00:00
In order to be able to recover from the AP and Cr50 getting out of sync, this logging functionality gives Cr50 a way to track the state changes of the merkle tree so that the AP can be updated to the current state as long as it has a recent enough copy. This involves packing the important information so it can be stored efficiently on flash, and adding the necessary messages for the replay. CQ-DEPEND=CL:895395,CL:929430 BRANCH=none BUG=chromium:809729, chromium:809745 TEST=cd ~/src/platform/ec && V=1 make run-weaver_ng -j Change-Id: I40f98de2c8e9706cccb5b922215699f2132fa121 Signed-off-by: Allen Webb <allenwebb@google.com> Reviewed-on: https://chromium-review.googlesource.com/963773 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
193 lines
6.2 KiB
C
193 lines
6.2 KiB
C
/* 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)
|
|
|
|
#define PW_LOG_ENTRY_COUNT 2
|
|
|
|
/* 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];
|
|
};
|
|
|
|
/* Long term flash storage for tree metadata. */
|
|
struct PW_PACKED pw_long_term_storage_t {
|
|
uint16_t storage_version;
|
|
|
|
/* 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;
|
|
|
|
/* Random bits used as part of the key derivation process. */
|
|
uint8_t key_derivation_nonce[16];
|
|
};
|
|
|
|
struct PW_PACKED pw_log_storage_t {
|
|
uint16_t storage_version;
|
|
uint32_t restart_count;
|
|
struct pw_get_log_entry_t entries[PW_LOG_ENTRY_COUNT];
|
|
};
|
|
|
|
/* 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;
|
|
};
|
|
|
|
/* Key names for nvmem_vars */
|
|
#define PW_TREE_VAR "pwT0"
|
|
#define PW_LOG_VAR0 "pwL0"
|
|
/* The maximum key-value pair space allowed for the values of PinWeaver until
|
|
* the Cr50 NVRAM implementation is updated to use a separate object per
|
|
* key value pair.
|
|
*/
|
|
#define PW_MAX_VAR_USAGE 192
|
|
|
|
/* Initializes the PinWeaver feature.
|
|
*
|
|
* This needs to be called prior to handling any messages.
|
|
*/
|
|
void pinweaver_init(void);
|
|
|
|
/* 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]);
|
|
|
|
/* This should only be used in tests. */
|
|
void force_restart_count(uint32_t mock_value);
|
|
|
|
/* NV RAM log functions exported for use in test code. */
|
|
int store_log_data(const struct pw_log_storage_t *log);
|
|
int store_merkle_tree(const struct merkle_tree_t *merkle_tree);
|
|
int log_insert_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE],
|
|
const uint8_t hmac[PW_HASH_SIZE]);
|
|
int log_remove_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE]);
|
|
int log_auth(struct label_t label, const uint8_t root[PW_HASH_SIZE], int code,
|
|
struct pw_timestamp_t timestamp);
|
|
|
|
#endif /* __CROS_EC_INCLUDE_PINWEAVER_H */
|