blob: b1409ba19452b01ab4672067fe164465c5d1c420 [file] [log] [blame]
Andrey Pronin9b10e512021-04-13 11:18:53 -07001/* Copyright 2018 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Andrey Pronin59bce7c2021-04-14 00:52:09 -07006#ifndef __PINWEAVER_PINWEAVER_H
7#define __PINWEAVER_PINWEAVER_H
Andrey Pronin9b10e512021-04-13 11:18:53 -07008
9/* This is required before pinweaver_types.h to provide __packed and __aligned
10 * while preserving the ability of pinweaver_types.h to be used in code outside
Andrey Pronin59bce7c2021-04-14 00:52:09 -070011 * of src/platform.
Andrey Pronin9b10e512021-04-13 11:18:53 -070012 */
Andrey Pronin59bce7c2021-04-14 00:52:09 -070013#ifndef __aligned
14#define __aligned(n) __attribute__((aligned(n)))
15#endif
16
17#ifndef __packed
18#define __packed __attribute__((packed))
19#endif
20
Andrey Pronin9b10e512021-04-13 11:18:53 -070021#include <pinweaver_types.h>
22
Andrey Pronin59bce7c2021-04-14 00:52:09 -070023#ifndef BUILD_ASSERT
24/* Test an important condition at compile time, not run time */
25#define _BA1_(cond, file, line, msg) \
26 _Static_assert(cond, file ":" #line ": " msg)
27#define _BA0_(c, f, l, msg) _BA1_(c, f, l, msg)
28/* Pass in an option message to display after condition */
29#define BUILD_ASSERT(cond, ...) _BA0_(cond, __FILE__, __LINE__, __VA_ARGS__)
30#endif
31
32#ifndef ARRAY_SIZE
33#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
34#endif
35
Andrey Pronin9b10e512021-04-13 11:18:53 -070036#ifdef __cplusplus
37extern "C" {
38#endif
39
40#define PW_STORAGE_VERSION 0
41
42#define BITS_PER_LEVEL_MIN 1
43#define BITS_PER_LEVEL_MAX 5
44#define HEIGHT_MIN 1
45/* This will crash for logk == 0 so that condition must not be allowed when
46 * using this.
47 */
48#define HEIGHT_MAX(logk) ((sizeof(struct label_t) * 8) / logk)
49
50#define PW_LOG_ENTRY_COUNT 2
51
52/* Persistent information used by this feature. */
53struct merkle_tree_t {
54 /* log2(Fan out). */
55 struct bits_per_level_t bits_per_level;
56 /* Height of the tree or param_l / bits_per_level. */
57 struct height_t height;
58
59 /* Root hash of the Merkle tree. */
60 uint8_t root[PW_HASH_SIZE];
61
62 /* Random bits used as part of the key derivation process. */
63 uint8_t key_derivation_nonce[16];
64
65 /* Key used to compute the HMACs of the metadata of the leaves. */
66 uint8_t PW_ALIGN_TO_WRD hmac_key[32];
67
68 /* Key used to encrypt and decrypt the metadata of the leaves. */
69 uint8_t PW_ALIGN_TO_WRD wrap_key[32];
70};
71
72/* Long term flash storage for tree metadata. */
73struct PW_PACKED pw_long_term_storage_t {
74 uint16_t storage_version;
75
76 /* log2(Fan out). */
77 struct bits_per_level_t bits_per_level;
78 /* Height of the tree or param_l / bits_per_level. */
79 struct height_t height;
80
81 /* Random bits used as part of the key derivation process. */
82 uint8_t key_derivation_nonce[16];
83};
84
85struct PW_PACKED pw_log_storage_t {
86 uint16_t storage_version;
87 uint32_t restart_count;
88 struct pw_get_log_entry_t entries[PW_LOG_ENTRY_COUNT];
89};
90
91/* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */
92/* Encrypted part of the leaf data.
93 */
Edward Hillcb73fa72022-05-12 21:33:05 +000094struct PW_ALIGN_TO_BLK leaf_sensitive_data_t {
Andrey Pronin9b10e512021-04-13 11:18:53 -070095 uint8_t low_entropy_secret[PW_SECRET_SIZE];
96 uint8_t high_entropy_secret[PW_SECRET_SIZE];
97 uint8_t reset_secret[PW_SECRET_SIZE];
98};
99
100/* Represents leaf data in a form that can be exported for storage. */
101struct PW_PACKED wrapped_leaf_data_t {
102 /* This is first so that head.leaf_version will be the first field
103 * in the struct to keep the meaning of the struct from becoming
104 * ambiguous across versions.
105 */
106 struct leaf_header_t head;
107 /* Covers .head, .pub, and .cipher_text. */
108 uint8_t hmac[PW_HASH_SIZE];
109 uint8_t iv[PW_WRAP_BLOCK_SIZE];
110 struct leaf_public_data_t pub;
111 uint8_t cipher_text[sizeof(struct leaf_sensitive_data_t)];
112};
113
114/* Represents encrypted leaf data after the lengths and version in the header
115 * have been validated.
116 */
117struct imported_leaf_data_t {
118 /* This is first so that head.leaf_version will be the first field
119 * in the struct to keep the meaning of the struct from becoming
120 * ambiguous across versions.
121 */
122 const struct leaf_header_t *head;
123 /* Covers .head, .pub, and .cipher_text. */
124 const uint8_t *hmac;
125 const uint8_t *iv;
126 const struct leaf_public_data_t *pub;
127 const uint8_t *cipher_text;
128 const uint8_t (*hashes)[PW_HASH_SIZE];
129};
130
131/* The leaf data in a clear text working format. */
132struct leaf_data_t {
133 struct leaf_public_data_t pub;
134 struct leaf_sensitive_data_t sec;
135};
136
137/* Key names for nvmem_vars */
138#define PW_TREE_VAR "pwT0"
139#define PW_LOG_VAR0 "pwL0"
140/* The maximum key-value pair space allowed for the values of PinWeaver until
141 * the Cr50 NVRAM implementation is updated to use a separate object per
142 * key value pair.
143 */
144#define PW_MAX_VAR_USAGE 192
145
146/* Initializes the PinWeaver feature.
147 *
148 * This needs to be called prior to handling any messages.
149 */
150void pinweaver_init(void);
151
Andrey Pronin59bce7c2021-04-14 00:52:09 -0700152/* Handler for raw incoming messages.
153 *
154 * Supports the case when request_buf and response_buf point to the same
155 * memory location---are backed by the same buffer.
156 */
157enum pinweaver_command_res_t {
158 PW_CMD_RES_SUCCESS = 0,
159 PW_CMD_RES_TOO_SMALL,
160 PW_CMD_RES_SIZE,
161};
162enum pinweaver_command_res_t pinweaver_command(void *request_buf,
163 size_t request_size,
164 void *response_buf,
165 size_t *response_size);
166
Andrey Pronin9b10e512021-04-13 11:18:53 -0700167/* Handler for incoming messages after they have been reconstructed.
168 *
169 * merkle_tree->root needs to be updated with new_root outside of this function.
170 */
171int pw_handle_request(struct merkle_tree_t *merkle_tree,
172 struct pw_request_t *request,
173 struct pw_response_t *response);
174
175/******************************************************************************/
176/* Struct helper functions.
177 */
178
179/* Sets up pointers to the relevant fields inside an wrapped leaf based on the
180 * length fields in the header. These fields should be validated prior to
181 * calling this function.
182 */
183void import_leaf(const struct unimported_leaf_data_t *unimported,
184 struct imported_leaf_data_t *imported);
185
186/* Calculate how much is needed to add to the size of structs containing
187 * an struct unimported_leaf_data_t because the variable length fields at the
188 * end of the struct are not included by sizeof().
189 */
190#define PW_LEAF_PAYLOAD_SIZE (sizeof(struct wrapped_leaf_data_t) - \
191 sizeof(struct unimported_leaf_data_t))
192
193
194/******************************************************************************/
195/* Utility functions exported for better test coverage.
196 */
197
198/* Computes the total number of the sibling hashes along a path. */
199int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree);
200
201/* Computes the parent hash for an array of child hashes. */
Leo Lai86ce69d2021-08-11 19:18:29 +0800202int compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
203 struct index_t location,
204 const uint8_t child_hash[PW_HASH_SIZE],
205 uint8_t result[PW_HASH_SIZE]);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700206
207/* This should only be used in tests. */
208void force_restart_count(uint32_t mock_value);
209
210/* NV RAM log functions exported for use in test code. */
211int store_log_data(const struct pw_log_storage_t *log);
212int store_merkle_tree(const struct merkle_tree_t *merkle_tree);
213int log_insert_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE],
214 const uint8_t hmac[PW_HASH_SIZE]);
215int log_remove_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE]);
216int log_auth(struct label_t label, const uint8_t root[PW_HASH_SIZE], int code,
Howard Yangaa7a8972022-07-26 16:39:36 +0800217 struct pw_timestamp_t last_access_ts,
218 struct pw_timestamp_t expiration_ts);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700219
220#ifdef __cplusplus
221}
222#endif
223
Andrey Pronin59bce7c2021-04-14 00:52:09 -0700224#endif /* __PINWEAVER_PINWEAVER_H */