blob: 7831f706e71d7fead5d98476101e70d4ef0b5b51 [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 Pronincd7bcce2021-04-14 00:54:12 -07006#include <string.h>
7
Andrey Pronin04db55a2021-04-26 22:09:34 -07008#include "pinweaver.h"
9#include "pinweaver_eal.h"
10
Andrey Pronincd7bcce2021-04-14 00:54:12 -070011/* TODO(apronin): get rid of temporary #defines */
12
13#ifndef SHA256_DIGEST_SIZE
14#define SHA256_DIGEST_SIZE (256/8)
15#endif
16
17#ifndef AES256_BLOCK_CIPHER_KEY_SIZE
18#define AES256_BLOCK_CIPHER_KEY_SIZE (256/8)
19#endif
20
21#ifndef EC_SUCCESS
22#define EC_SUCCESS 0
23#endif
24
25#ifndef MIN
26#define MIN(a,b) ((a) < (b) ? (a) : (b))
27#endif
Andrey Pronin9b10e512021-04-13 11:18:53 -070028
29/* Compile time sanity checks. */
30/* Make sure the hash size is consistent with dcrypto. */
31BUILD_ASSERT(PW_HASH_SIZE >= SHA256_DIGEST_SIZE);
32
33/* sizeof(struct leaf_data_t) % 16 should be zero */
34BUILD_ASSERT(sizeof(struct leaf_sensitive_data_t) % PW_WRAP_BLOCK_SIZE == 0);
35
36BUILD_ASSERT(sizeof(((struct merkle_tree_t *)0)->wrap_key) ==
37 AES256_BLOCK_CIPHER_KEY_SIZE);
38
39/* Verify that the nvmem_vars log entries have the correct sizes. */
40BUILD_ASSERT(sizeof(struct pw_long_term_storage_t) +
41 sizeof(struct pw_log_storage_t) <= PW_MAX_VAR_USAGE);
42
43/* Verify that the request structs will fit into the message. */
44BUILD_ASSERT(PW_MAX_MESSAGE_SIZE >=
45 sizeof(struct pw_request_header_t) +
46 sizeof(union {struct pw_request_insert_leaf_t insert_leaf;
47 struct pw_request_remove_leaf_t remove_leaf;
48 struct pw_request_try_auth_t try_auth;
49 struct pw_request_reset_auth_t reset_auth;
50 struct pw_request_get_log_t get_log;
51 struct pw_request_log_replay_t log_replay; }) +
52 sizeof(struct leaf_public_data_t) +
53 sizeof(struct leaf_sensitive_data_t) +
54 PW_MAX_PATH_SIZE);
55
56#define PW_MAX_RESPONSE_SIZE (sizeof(struct pw_response_header_t) + \
57 sizeof(union {struct pw_response_insert_leaf_t insert_leaf; \
58 struct pw_response_try_auth_t try_auth; \
59 struct pw_response_reset_auth_t reset_auth; \
60 struct pw_response_log_replay_t log_replay; }) + \
61 PW_LEAF_PAYLOAD_SIZE)
62#define PW_VALID_PCR_CRITERIA_SIZE \
63 (sizeof(struct valid_pcr_value_t) * PW_MAX_PCR_CRITERIA_COUNT)
64/* Verify that the request structs will fit into the message. */
65BUILD_ASSERT(PW_MAX_MESSAGE_SIZE >= PW_MAX_RESPONSE_SIZE);
Andrey Pronin9b10e512021-04-13 11:18:53 -070066
67/* PW_MAX_PATH_SIZE should not change unless PW_LEAF_MAJOR_VERSION changes too.
68 * Update these statements whenever these constants are changed to remind future
69 * maintainers about this requirement.
70 *
71 * This requirement helps guarantee that forward compatibility across the same
72 * PW_LEAF_MAJOR_VERSION doesn't break because of a path length becoming too
73 * long after new fields are added to struct wrapped_leaf_data_t or its sub
74 * fields.
75 */
76BUILD_ASSERT(PW_LEAF_MAJOR_VERSION == 0);
77BUILD_ASSERT(PW_MAX_PATH_SIZE == 1024);
78
79/* If fields are appended to struct leaf_sensitive_data_t, an encryption
80 * operation should be performed on them reusing the same IV since the prefix
81 * won't change.
82 *
83 * If any data in the original struct leaf_sensitive_data_t changes, a new IV
84 * should be generated and stored as part of the log for a replay to be
85 * possible.
86 */
87BUILD_ASSERT(sizeof(struct leaf_sensitive_data_t) == 3 * PW_SECRET_SIZE);
88
Andrey Pronincd7bcce2021-04-14 00:54:12 -070089#define RESTART_TIMER_THRESHOLD (10 /* seconds */)
Andrey Pronin9b10e512021-04-13 11:18:53 -070090
91/* This var caches the restart count so the nvram log structure doesn't need to
92 * be walked every time try_auth request is made.
93 */
94uint32_t pw_restart_count;
95
96/******************************************************************************/
97/* Struct helper functions.
98 */
99
100void import_leaf(const struct unimported_leaf_data_t *unimported,
101 struct imported_leaf_data_t *imported)
102{
103 imported->head = &unimported->head;
104 imported->hmac = unimported->hmac;
105 imported->iv = unimported->iv;
106 imported->pub = (const struct leaf_public_data_t *)unimported->payload;
107 imported->cipher_text = unimported->payload + unimported->head.pub_len;
108 imported->hashes = (const uint8_t (*)[PW_HASH_SIZE])(
109 imported->cipher_text + unimported->head.sec_len);
110}
111
112/******************************************************************************/
113/* Basic operations required by the Merkle tree.
114 */
115
Andrey Pronin9b10e512021-04-13 11:18:53 -0700116/* Creates an empty merkle_tree with the given parameters. */
117static int create_merkle_tree(struct bits_per_level_t bits_per_level,
118 struct height_t height,
119 struct merkle_tree_t *merkle_tree)
120{
121 uint16_t fan_out = 1 << bits_per_level.v;
122 uint8_t temp_hash[PW_HASH_SIZE] = {};
123 uint8_t hx;
124 uint16_t kx;
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700125 pinweaver_eal_sha256_ctx_t ctx;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700126
127 merkle_tree->bits_per_level = bits_per_level;
128 merkle_tree->height = height;
129
Leo Lai788f41e2021-08-11 00:36:24 +0800130 int ret;
131
Andrey Pronin9b10e512021-04-13 11:18:53 -0700132 /* Initialize the root hash. */
133 for (hx = 0; hx < height.v; ++hx) {
Leo Lai788f41e2021-08-11 00:36:24 +0800134 ret = pinweaver_eal_sha256_init(&ctx);
135 if (ret)
136 return ret;
137 for (kx = 0; kx < fan_out; ++kx) {
138 ret = pinweaver_eal_sha256_update(&ctx, temp_hash,
139 PW_HASH_SIZE);
140 if (ret) {
141 pinweaver_eal_sha256_final(&ctx, temp_hash);
142 return ret;
143 }
144 }
145 ret = pinweaver_eal_sha256_final(&ctx, temp_hash);
146 if (ret)
147 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700148 }
Leo Laidb207912021-08-11 16:41:18 +0800149 ret = pinweaver_eal_memcpy_s(merkle_tree->root,
150 sizeof(merkle_tree->root), temp_hash,
151 PW_HASH_SIZE);
152 if (ret != EC_SUCCESS)
153 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700154
Leo Lai788f41e2021-08-11 00:36:24 +0800155 ret = pinweaver_eal_rand_bytes(
156 merkle_tree->key_derivation_nonce,
157 sizeof(merkle_tree->key_derivation_nonce));
158 if (ret)
159 return ret;
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700160 return pinweaver_eal_derive_keys(merkle_tree);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700161}
162
163/* Computes the HMAC for an encrypted leaf using the key in the merkle_tree. */
Leo Lai788f41e2021-08-11 00:36:24 +0800164static int compute_hmac(const struct merkle_tree_t *merkle_tree,
165 const struct imported_leaf_data_t *imported_leaf_data,
166 uint8_t result[PW_HASH_SIZE])
Andrey Pronin9b10e512021-04-13 11:18:53 -0700167{
Leo Lai788f41e2021-08-11 00:36:24 +0800168 int ret;
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700169 pinweaver_eal_hmac_sha256_ctx_t hmac;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700170
Leo Lai788f41e2021-08-11 00:36:24 +0800171 ret = pinweaver_eal_hmac_sha256_init(&hmac, merkle_tree->hmac_key,
172 sizeof(merkle_tree->hmac_key));
173 if (ret)
174 return ret;
175 ret = pinweaver_eal_hmac_sha256_update(
176 &hmac, imported_leaf_data->head,
177 sizeof(*imported_leaf_data->head));
178 if (ret) {
179 pinweaver_eal_hmac_sha256_final(&hmac, result);
180 return ret;
181 }
182 ret = pinweaver_eal_hmac_sha256_update(&hmac, imported_leaf_data->iv,
183 sizeof(PW_WRAP_BLOCK_SIZE));
184 if (ret) {
185 pinweaver_eal_hmac_sha256_final(&hmac, result);
186 return ret;
187 }
188 ret = pinweaver_eal_hmac_sha256_update(
189 &hmac, imported_leaf_data->pub,
190 imported_leaf_data->head->pub_len);
191 if (ret) {
192 pinweaver_eal_hmac_sha256_final(&hmac, result);
193 return ret;
194 }
195 ret = pinweaver_eal_hmac_sha256_update(
196 &hmac, imported_leaf_data->cipher_text,
197 imported_leaf_data->head->sec_len);
198 if (ret) {
199 pinweaver_eal_hmac_sha256_final(&hmac, result);
200 return ret;
201 }
202 return pinweaver_eal_hmac_sha256_final(&hmac, result);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700203}
204
205/* Computes the root hash for the specified path and child hash. */
Leo Lai788f41e2021-08-11 00:36:24 +0800206static int compute_root_hash(const struct merkle_tree_t *merkle_tree,
207 struct label_t path,
208 const uint8_t hashes[][PW_HASH_SIZE],
209 const uint8_t child_hash[PW_HASH_SIZE],
210 uint8_t new_root[PW_HASH_SIZE])
Andrey Pronin9b10e512021-04-13 11:18:53 -0700211{
212 /* This is one less than the fan out, the number of sibling hashes. */
213 const uint16_t num_aux = (1 << merkle_tree->bits_per_level.v) - 1;
214 const uint16_t path_suffix_mask = num_aux;
215 uint8_t temp_hash[PW_HASH_SIZE];
216 uint8_t hx = 0;
217 uint64_t index = path.v;
Leo Laidb207912021-08-11 16:41:18 +0800218 int ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700219
Leo Lai788f41e2021-08-11 00:36:24 +0800220 if (compute_hash(hashes, num_aux,
221 (struct index_t){ index & path_suffix_mask },
222 child_hash, temp_hash)) {
223 return PW_ERR_CRYPTO_FAILURE;
224 }
Andrey Pronin9b10e512021-04-13 11:18:53 -0700225 for (hx = 1; hx < merkle_tree->height.v; ++hx) {
226 hashes += num_aux;
227 index = index >> merkle_tree->bits_per_level.v;
Leo Lai788f41e2021-08-11 00:36:24 +0800228 if (compute_hash(hashes, num_aux,
229 (struct index_t){ index & path_suffix_mask },
230 temp_hash, temp_hash)) {
231 return PW_ERR_CRYPTO_FAILURE;
232 }
Andrey Pronin9b10e512021-04-13 11:18:53 -0700233 }
Leo Laidb207912021-08-11 16:41:18 +0800234 ret = pinweaver_eal_memcpy_s(new_root, PW_HASH_SIZE, temp_hash,
235 sizeof(temp_hash));
236 if (ret != EC_SUCCESS)
237 return PW_ERR_INTERNAL_FAILURE;
Leo Lai788f41e2021-08-11 00:36:24 +0800238 return EC_SUCCESS;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700239}
240
241/* Checks to see the specified path is valid. The length of the path should be
242 * validated prior to calling this function.
243 *
244 * Returns 0 on success or an error code otherwise.
245 */
246static int authenticate_path(const struct merkle_tree_t *merkle_tree,
247 struct label_t path,
248 const uint8_t hashes[][PW_HASH_SIZE],
249 const uint8_t child_hash[PW_HASH_SIZE])
250{
251 uint8_t parent[PW_HASH_SIZE];
252
Leo Lai788f41e2021-08-11 00:36:24 +0800253 if (compute_root_hash(merkle_tree, path, hashes, child_hash, parent) !=
254 0)
255 return PW_ERR_CRYPTO_FAILURE;
Yi Chouddf3b452021-08-11 13:40:11 +0800256 if (pinweaver_eal_safe_memcmp(parent, merkle_tree->root,
257 sizeof(parent)) != 0)
Andrey Pronin9b10e512021-04-13 11:18:53 -0700258 return PW_ERR_PATH_AUTH_FAILED;
259 return EC_SUCCESS;
260}
261
262static void init_wrapped_leaf_data(
263 struct wrapped_leaf_data_t *wrapped_leaf_data)
264{
265 wrapped_leaf_data->head.leaf_version.major = PW_LEAF_MAJOR_VERSION;
266 wrapped_leaf_data->head.leaf_version.minor = PW_LEAF_MINOR_VERSION;
267 wrapped_leaf_data->head.pub_len = sizeof(wrapped_leaf_data->pub);
268 wrapped_leaf_data->head.sec_len =
269 sizeof(wrapped_leaf_data->cipher_text);
270}
271
272/* Encrypts the leaf meta data. */
273static int encrypt_leaf_data(const struct merkle_tree_t *merkle_tree,
274 const struct leaf_data_t *leaf_data,
275 struct wrapped_leaf_data_t *wrapped_leaf_data)
276{
Leo Laidb207912021-08-11 16:41:18 +0800277 int ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700278 /* Generate a random IV.
279 *
280 * If fields are appended to struct leaf_sensitive_data_t, an encryption
281 * operation should be performed on them reusing the same IV since the
282 * prefix won't change.
283 *
284 * If any data of in the original struct leaf_sensitive_data_t changes,
285 * a new IV should be generated and stored as part of the log for a
286 * replay to be possible.
287 */
Leo Lai788f41e2021-08-11 00:36:24 +0800288 if (pinweaver_eal_rand_bytes(wrapped_leaf_data->iv,
289 sizeof(wrapped_leaf_data->iv))) {
290 return PW_ERR_CRYPTO_FAILURE;
291 }
Leo Laidb207912021-08-11 16:41:18 +0800292 ret = pinweaver_eal_memcpy_s(&wrapped_leaf_data->pub,
293 sizeof(wrapped_leaf_data->pub),
294 &leaf_data->pub, sizeof(leaf_data->pub));
295 if (ret != EC_SUCCESS)
296 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin1197a0d2021-05-14 20:18:05 -0700297 if (pinweaver_eal_aes256_ctr(merkle_tree->wrap_key,
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700298 sizeof(merkle_tree->wrap_key),
299 wrapped_leaf_data->iv,
300 &leaf_data->sec,
301 sizeof(leaf_data->sec),
302 wrapped_leaf_data->cipher_text)) {
Andrey Pronin9b10e512021-04-13 11:18:53 -0700303 return PW_ERR_CRYPTO_FAILURE;
304 }
305 return EC_SUCCESS;
306}
307
308/* Decrypts the leaf meta data. */
309static int decrypt_leaf_data(
310 const struct merkle_tree_t *merkle_tree,
311 const struct imported_leaf_data_t *imported_leaf_data,
312 struct leaf_data_t *leaf_data)
313{
Leo Laidb207912021-08-11 16:41:18 +0800314 int ret;
315 ret = pinweaver_eal_memcpy_s(&leaf_data->pub, sizeof(leaf_data->pub),
316 imported_leaf_data->pub,
317 MIN(imported_leaf_data->head->pub_len,
318 sizeof(struct leaf_public_data_t)));
319 if (ret != EC_SUCCESS)
320 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin1197a0d2021-05-14 20:18:05 -0700321 if (pinweaver_eal_aes256_ctr(merkle_tree->wrap_key,
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700322 sizeof(merkle_tree->wrap_key),
323 imported_leaf_data->iv,
324 imported_leaf_data->cipher_text,
325 sizeof(leaf_data->sec),
326 &leaf_data->sec)) {
Andrey Pronin9b10e512021-04-13 11:18:53 -0700327 return PW_ERR_CRYPTO_FAILURE;
328 }
329 return EC_SUCCESS;
330}
331
332static int handle_leaf_update(
333 const struct merkle_tree_t *merkle_tree,
334 const struct leaf_data_t *leaf_data,
335 const uint8_t hashes[][PW_HASH_SIZE],
336 struct wrapped_leaf_data_t *wrapped_leaf_data,
337 uint8_t new_root[PW_HASH_SIZE],
338 const struct imported_leaf_data_t *optional_old_wrapped_data)
339{
340 int ret;
341 struct imported_leaf_data_t ptrs;
342
343 init_wrapped_leaf_data(wrapped_leaf_data);
344 if (optional_old_wrapped_data == NULL) {
345 ret = encrypt_leaf_data(merkle_tree, leaf_data,
346 wrapped_leaf_data);
347 if (ret != EC_SUCCESS)
348 return ret;
349 } else {
Leo Laidb207912021-08-11 16:41:18 +0800350 ret = pinweaver_eal_memcpy_s(wrapped_leaf_data->iv,
351 sizeof(wrapped_leaf_data->iv),
352 optional_old_wrapped_data->iv,
353 sizeof(wrapped_leaf_data->iv));
354 if (ret != EC_SUCCESS)
355 return PW_ERR_INTERNAL_FAILURE;
356 ret = pinweaver_eal_memcpy_s(&wrapped_leaf_data->pub,
357 sizeof(wrapped_leaf_data->pub),
358 &leaf_data->pub,
359 sizeof(leaf_data->pub));
360 if (ret != EC_SUCCESS)
361 return PW_ERR_INTERNAL_FAILURE;
362 ret = pinweaver_eal_memcpy_s(
363 wrapped_leaf_data->cipher_text,
364 sizeof(wrapped_leaf_data->cipher_text),
365 optional_old_wrapped_data->cipher_text,
366 sizeof(wrapped_leaf_data->cipher_text));
367 if (ret != EC_SUCCESS)
368 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700369 }
370
371 import_leaf((const struct unimported_leaf_data_t *)wrapped_leaf_data,
372 &ptrs);
Leo Lai788f41e2021-08-11 00:36:24 +0800373 ret = compute_hmac(merkle_tree, &ptrs, wrapped_leaf_data->hmac);
374 if (ret)
375 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700376
Leo Lai788f41e2021-08-11 00:36:24 +0800377 ret = compute_root_hash(merkle_tree, leaf_data->pub.label, hashes,
378 wrapped_leaf_data->hmac, new_root);
379 if (ret)
380 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700381
382 return EC_SUCCESS;
383}
384
385/******************************************************************************/
386/* Parameter and state validation functions.
387 */
388
389static int validate_tree_parameters(struct bits_per_level_t bits_per_level,
390 struct height_t height)
391{
392 uint8_t fan_out = 1 << bits_per_level.v;
393
394 if (bits_per_level.v < BITS_PER_LEVEL_MIN ||
395 bits_per_level.v > BITS_PER_LEVEL_MAX)
396 return PW_ERR_BITS_PER_LEVEL_INVALID;
397
398 if (height.v < HEIGHT_MIN ||
399 height.v > HEIGHT_MAX(bits_per_level.v) ||
400 ((fan_out - 1) * height.v) * PW_HASH_SIZE > PW_MAX_PATH_SIZE)
401 return PW_ERR_HEIGHT_INVALID;
402
403 return EC_SUCCESS;
404}
405
406/* Verifies that merkle_tree has been initialized. */
407static int validate_tree(const struct merkle_tree_t *merkle_tree)
408{
409 if (validate_tree_parameters(merkle_tree->bits_per_level,
410 merkle_tree->height) != EC_SUCCESS)
411 return PW_ERR_TREE_INVALID;
412 return EC_SUCCESS;
413}
414
415/* Checks the following conditions:
416 * Extra index fields should be all zero.
417 */
418static int validate_label(const struct merkle_tree_t *merkle_tree,
419 struct label_t path)
420{
421 uint8_t shift_by = merkle_tree->bits_per_level.v *
422 merkle_tree->height.v;
423
424 if ((path.v >> shift_by) == 0)
425 return EC_SUCCESS;
426 return PW_ERR_LABEL_INVALID;
427}
428
429/* Checks the following conditions:
430 * Columns should be strictly increasing.
431 * Zeroes for filler at the end of the delay_schedule are permitted.
432 */
433static int validate_delay_schedule(const struct delay_schedule_entry_t
434 delay_schedule[PW_SCHED_COUNT])
435{
436 size_t x;
437
438 /* The first entry should not be useless. */
Yi Choueed2b652021-08-11 13:47:15 +0800439 if (delay_schedule[0].attempt_count.v == 0 ||
440 delay_schedule[0].time_diff.v == 0)
Andrey Pronin9b10e512021-04-13 11:18:53 -0700441 return PW_ERR_DELAY_SCHEDULE_INVALID;
442
443 for (x = PW_SCHED_COUNT - 1; x > 0; --x) {
444 if (delay_schedule[x].attempt_count.v == 0) {
445 if (delay_schedule[x].time_diff.v != 0)
446 return PW_ERR_DELAY_SCHEDULE_INVALID;
447 } else if (delay_schedule[x].attempt_count.v <=
448 delay_schedule[x - 1].attempt_count.v ||
449 delay_schedule[x].time_diff.v <=
450 delay_schedule[x - 1].time_diff.v) {
451 return PW_ERR_DELAY_SCHEDULE_INVALID;
452 }
453 }
454 return EC_SUCCESS;
455}
456
457static int validate_pcr_value(const struct valid_pcr_value_t
458 valid_pcr_criteria[PW_MAX_PCR_CRITERIA_COUNT])
459{
460 size_t index;
461 uint8_t sha256_of_selected_pcr[SHA256_DIGEST_SIZE];
462
463 for (index = 0; index < PW_MAX_PCR_CRITERIA_COUNT; ++index) {
464 /* The criteria with bitmask[0] = bitmask[1] = 0 is considered
465 * the end of list criteria. If it happens that the first
466 * bitmask is zero, we consider that no criteria has to be
467 * satisfied and return success in that case.
468 */
469 if (valid_pcr_criteria[index].bitmask[0] == 0 &&
470 valid_pcr_criteria[index].bitmask[1] == 0) {
471 if (index == 0)
472 return EC_SUCCESS;
473
474 return PW_ERR_PCR_NOT_MATCH;
475 }
476
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700477 if (pinweaver_eal_get_current_pcr_digest(
478 valid_pcr_criteria[index].bitmask,
479 sha256_of_selected_pcr)) {
480 PINWEAVER_EAL_INFO(
Andrey Pronin9b10e512021-04-13 11:18:53 -0700481 "PinWeaver: Read PCR error, bitmask: %d, %d",
482 valid_pcr_criteria[index].bitmask[0],
483 valid_pcr_criteria[index].bitmask[1]);
484 return PW_ERR_PCR_NOT_MATCH;
485 }
486
487 /* Check if the curent PCR digest is the same as expected by
488 * criteria.
489 */
Yi Chouddf3b452021-08-11 13:40:11 +0800490 if (pinweaver_eal_safe_memcmp(sha256_of_selected_pcr,
491 valid_pcr_criteria[index].digest,
492 SHA256_DIGEST_SIZE) == 0) {
Andrey Pronin9b10e512021-04-13 11:18:53 -0700493 return EC_SUCCESS;
494 }
495 }
496
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700497 PINWEAVER_EAL_INFO("PinWeaver: No criteria matches PCR values");
Andrey Pronin9b10e512021-04-13 11:18:53 -0700498 return PW_ERR_PCR_NOT_MATCH;
499}
500
Leo Lai8c9892c2021-06-22 21:32:02 +0800501static uint32_t expected_payload_len(int minor_version)
Andrey Pronin9b10e512021-04-13 11:18:53 -0700502{
503 switch (minor_version) {
504 case 0:
505 return PW_LEAF_PAYLOAD_SIZE - PW_VALID_PCR_CRITERIA_SIZE;
506 case PW_LEAF_MINOR_VERSION:
507 return PW_LEAF_PAYLOAD_SIZE;
508 default:
509 return 0;
510 }
511}
512
513static int validate_leaf_header(const struct leaf_header_t *head,
514 uint16_t payload_len, uint16_t aux_hash_len)
515{
516 uint32_t leaf_payload_len = head->pub_len + head->sec_len;
517
518 if (head->leaf_version.major != PW_LEAF_MAJOR_VERSION)
519 return PW_ERR_LEAF_VERSION_MISMATCH;
520
521 if (head->leaf_version.minor <= PW_LEAF_MINOR_VERSION &&
522 leaf_payload_len !=
523 expected_payload_len(head->leaf_version.minor)) {
524 return PW_ERR_LENGTH_INVALID;
525 }
526
527 if (payload_len != leaf_payload_len + aux_hash_len * PW_HASH_SIZE)
528 return PW_ERR_LENGTH_INVALID;
529
530 return EC_SUCCESS;
531}
532
533/* Common validation for requests that include a path to authenticate. */
534static int validate_request_with_path(const struct merkle_tree_t *merkle_tree,
535 struct label_t path,
536 const uint8_t hashes[][PW_HASH_SIZE],
537 const uint8_t hmac[PW_HASH_SIZE])
538{
539 int ret;
540
541 ret = validate_tree(merkle_tree);
542 if (ret != EC_SUCCESS)
543 return ret;
544
545 ret = validate_label(merkle_tree, path);
546 if (ret != EC_SUCCESS)
547 return ret;
548
549 return authenticate_path(merkle_tree, path, hashes, hmac);
550}
551
552/* Common validation for requests that import a leaf. */
553static int validate_request_with_wrapped_leaf(
554 const struct merkle_tree_t *merkle_tree,
555 uint16_t payload_len,
556 const struct unimported_leaf_data_t *unimported_leaf_data,
557 struct imported_leaf_data_t *imported_leaf_data,
558 struct leaf_data_t *leaf_data)
559{
560 int ret;
561 uint8_t hmac[PW_HASH_SIZE];
562
563 ret = validate_leaf_header(&unimported_leaf_data->head, payload_len,
564 get_path_auxiliary_hash_count(merkle_tree));
565 if (ret != EC_SUCCESS)
566 return ret;
567
568 import_leaf(unimported_leaf_data, imported_leaf_data);
569 ret = validate_request_with_path(merkle_tree,
570 imported_leaf_data->pub->label,
571 imported_leaf_data->hashes,
572 imported_leaf_data->hmac);
573 if (ret != EC_SUCCESS)
574 return ret;
575
Leo Lai788f41e2021-08-11 00:36:24 +0800576 ret = compute_hmac(merkle_tree, imported_leaf_data, hmac);
577 if (ret != EC_SUCCESS)
578 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700579 /* Safe memcmp is used here to prevent an attacker from being able to
580 * brute force a valid HMAC for a crafted wrapped_leaf_data.
581 * memcmp provides an attacker a timing side-channel they can use to
582 * determine how much of a prefix is correct.
583 */
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700584 if (pinweaver_eal_safe_memcmp(hmac, unimported_leaf_data->hmac,
585 sizeof(hmac)))
Andrey Pronin9b10e512021-04-13 11:18:53 -0700586 return PW_ERR_HMAC_AUTH_FAILED;
587
588 ret = decrypt_leaf_data(merkle_tree, imported_leaf_data, leaf_data);
589 if (ret != EC_SUCCESS)
590 return ret;
591
592 /* The code below handles version upgrades. */
593 if (unimported_leaf_data->head.leaf_version.minor == 0 &&
594 unimported_leaf_data->head.leaf_version.major == 0) {
595 /* Populate the leaf_data with default pcr value */
596 memset(&leaf_data->pub.valid_pcr_criteria, 0,
597 PW_VALID_PCR_CRITERIA_SIZE);
598 }
599
600 return EC_SUCCESS;
601}
602
603/* Sets the value of ts to the current notion of time. */
604static void update_timestamp(struct pw_timestamp_t *ts)
605{
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700606 ts->timer_value = pinweaver_eal_seconds_since_boot();
Andrey Pronin9b10e512021-04-13 11:18:53 -0700607 ts->boot_count = pw_restart_count;
608}
609
610/* Checks if an auth attempt can be made or not based on the delay schedule.
611 * EC_SUCCESS is returned when a new attempt can be made otherwise
612 * seconds_to_wait will be updated with the remaining wait time required.
613 */
614static int test_rate_limit(struct leaf_data_t *leaf_data,
615 struct time_diff_t *seconds_to_wait)
616{
617 uint64_t ready_time;
618 uint8_t x;
619 struct pw_timestamp_t current_time;
620 struct time_diff_t delay = {0};
621
622 /* This loop ends when x is one greater than the index that applies. */
623 for (x = 0; x < ARRAY_SIZE(leaf_data->pub.delay_schedule); ++x) {
624 /* Stop if a null entry is reached. The first part of the delay
625 * schedule has a list of increasing (attempt_count, time_diff)
626 * pairs with any unused entries zeroed out at the end.
627 */
628 if (leaf_data->pub.delay_schedule[x].attempt_count.v == 0)
629 break;
630
631 /* Stop once a delay schedule entry is reached whose
632 * threshold is greater than the current number of
633 * attempts.
634 */
635 if (leaf_data->pub.attempt_count.v <
636 leaf_data->pub.delay_schedule[x].attempt_count.v)
637 break;
638 }
639
640 /* If the first threshold was greater than the current number of
641 * attempts, there is no delay. Otherwise, grab the delay from the
642 * entry prior to the one that was too big.
643 */
644 if (x > 0)
645 delay = leaf_data->pub.delay_schedule[x - 1].time_diff;
646
647 if (delay.v == 0)
648 return EC_SUCCESS;
649
650 if (delay.v == PW_BLOCK_ATTEMPTS) {
651 seconds_to_wait->v = PW_BLOCK_ATTEMPTS;
652 return PW_ERR_RATE_LIMIT_REACHED;
653 }
654
655 update_timestamp(&current_time);
656
657 if (leaf_data->pub.timestamp.boot_count == current_time.boot_count)
658 ready_time = delay.v + leaf_data->pub.timestamp.timer_value;
659 else
660 ready_time = delay.v;
661
662 if (current_time.timer_value >= ready_time)
663 return EC_SUCCESS;
664
665 seconds_to_wait->v = ready_time - current_time.timer_value;
666 return PW_ERR_RATE_LIMIT_REACHED;
667}
668
669/******************************************************************************/
670/* Logging implementation.
671 */
672
673/* Once the storage version is incremented, the update code needs to be written
674 * to handle differences in the structs.
675 *
676 * See the two comments "Add storage format updates here." below.
677 */
678BUILD_ASSERT(PW_STORAGE_VERSION == 0);
679
680void force_restart_count(uint32_t mock_value)
681{
682 pw_restart_count = mock_value;
683}
684
685/* Returns EC_SUCCESS if the root hash was found. Sets *index to the first index
686 * of the log entry with a matching root hash, or the index of the last valid
687 * entry.
688 */
689static int find_relevant_entry(const struct pw_log_storage_t *log,
690 const uint8_t root[PW_HASH_SIZE], int *index)
691{
692 /* Find the relevant log entry. */
693 for (*index = 0; *index < PW_LOG_ENTRY_COUNT; ++*index) {
694 if (log->entries[*index].type.v == PW_MT_INVALID)
695 break;
Yi Chouddf3b452021-08-11 13:40:11 +0800696 if (pinweaver_eal_safe_memcmp(root, log->entries[*index].root,
697 PW_HASH_SIZE) == 0)
Andrey Pronin9b10e512021-04-13 11:18:53 -0700698 return EC_SUCCESS;
699 }
700 --*index;
701 return PW_ERR_ROOT_NOT_FOUND;
702}
703
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700704/* TODO(apronin): get rid of temporary redirect methods */
705
Andrey Pronin9b10e512021-04-13 11:18:53 -0700706static int load_log_data(struct pw_log_storage_t *log)
707{
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700708 return pinweaver_eal_storage_get_log(log);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700709}
710
711int store_log_data(const struct pw_log_storage_t *log)
712{
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700713 return pinweaver_eal_storage_set_log(log);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700714}
715
716static int load_merkle_tree(struct merkle_tree_t *merkle_tree)
717{
718 int ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700719
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700720 PINWEAVER_EAL_INFO("PinWeaver: Loading Tree!");
Andrey Pronin9b10e512021-04-13 11:18:53 -0700721
722 /* Handle the immutable data. */
723 {
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700724 struct pw_long_term_storage_t tree;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700725
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700726 ret = pinweaver_eal_storage_get_tree_data(&tree);
727 if (ret != EC_SUCCESS)
728 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700729
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700730 merkle_tree->bits_per_level = tree.bits_per_level;
731 merkle_tree->height = tree.height;
Leo Laidb207912021-08-11 16:41:18 +0800732 ret = pinweaver_eal_memcpy_s(
733 merkle_tree->key_derivation_nonce,
734 sizeof(merkle_tree->key_derivation_nonce),
735 tree.key_derivation_nonce,
736 sizeof(tree.key_derivation_nonce));
737 if (ret != EC_SUCCESS)
738 return ret;
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700739 ret = pinweaver_eal_derive_keys(merkle_tree);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700740 if (ret != EC_SUCCESS)
741 return ret;
742 }
743
744 /* Handle the root hash. */
745 {
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700746 ret = pinweaver_eal_storage_init_state(merkle_tree->root,
747 &pw_restart_count);
748 if (ret != EC_SUCCESS)
749 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700750 }
751
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700752 PINWEAVER_EAL_INFO("PinWeaver: Loaded Tree. restart_count = %d",
Andrey Pronin9b10e512021-04-13 11:18:53 -0700753 pw_restart_count);
754
755 return EC_SUCCESS;
756}
757
758/* This should only be called when a new tree is created. */
759int store_merkle_tree(const struct merkle_tree_t *merkle_tree)
760{
761 int ret;
762
763 /* Handle the immutable data. */
764 {
765 struct pw_long_term_storage_t data;
766
767 data.storage_version = PW_STORAGE_VERSION;
768 data.bits_per_level = merkle_tree->bits_per_level;
769 data.height = merkle_tree->height;
Leo Laidb207912021-08-11 16:41:18 +0800770 ret = pinweaver_eal_memcpy_s(data.key_derivation_nonce,
771 sizeof(data.key_derivation_nonce),
772 merkle_tree->key_derivation_nonce,
773 sizeof(data.key_derivation_nonce));
774 if (ret != EC_SUCCESS)
775 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700776
Andrey Pronincd7bcce2021-04-14 00:54:12 -0700777 ret = pinweaver_eal_storage_set_tree_data(&data);
Andrey Pronin9b10e512021-04-13 11:18:53 -0700778 if (ret != EC_SUCCESS)
779 return ret;
780 }
781
782 /* Handle the root hash. */
783 {
784 struct pw_log_storage_t log = {};
785 struct pw_get_log_entry_t *entry = log.entries;
786
787 log.storage_version = PW_STORAGE_VERSION;
788 entry->type.v = PW_RESET_TREE;
Leo Laidb207912021-08-11 16:41:18 +0800789 ret = pinweaver_eal_memcpy_s(entry->root, sizeof(entry->root),
790 merkle_tree->root,
791 sizeof(merkle_tree->root));
792 if (ret != EC_SUCCESS)
793 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700794
795 ret = store_log_data(&log);
796 if (ret == EC_SUCCESS)
797 pw_restart_count = 0;
798 return ret;
799 }
800
801}
802
803static int log_roll_for_append(struct pw_log_storage_t *log)
804{
805 int ret;
806
807 ret = load_log_data(log);
808 if (ret != EC_SUCCESS)
809 return ret;
810
811 memmove(&log->entries[1], &log->entries[0],
812 sizeof(log->entries[0]) * (PW_LOG_ENTRY_COUNT - 1));
813 memset(&log->entries[0], 0, sizeof(log->entries[0]));
814 return EC_SUCCESS;
815}
816
817int log_insert_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE],
818 const uint8_t hmac[PW_HASH_SIZE])
819{
820 int ret;
821 struct pw_log_storage_t log;
822 struct pw_get_log_entry_t *entry = log.entries;
823
824 ret = log_roll_for_append(&log);
825 if (ret != EC_SUCCESS)
826 return ret;
827
828 entry->type.v = PW_INSERT_LEAF;
829 entry->label.v = label.v;
Leo Laidb207912021-08-11 16:41:18 +0800830 ret = pinweaver_eal_memcpy_s(entry->root, sizeof(entry->root), root,
831 sizeof(entry->root));
832 if (ret != EC_SUCCESS)
833 return ret;
834 ret = pinweaver_eal_memcpy_s(entry->leaf_hmac, sizeof(entry->leaf_hmac),
835 hmac, sizeof(entry->leaf_hmac));
836 if (ret != EC_SUCCESS)
837 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700838
839 return store_log_data(&log);
840}
841
842int log_remove_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE])
843{
844 int ret;
845 struct pw_log_storage_t log;
846 struct pw_get_log_entry_t *entry = log.entries;
847
848 ret = log_roll_for_append(&log);
849 if (ret != EC_SUCCESS)
850 return ret;
851
852 entry->type.v = PW_REMOVE_LEAF;
853 entry->label.v = label.v;
Leo Laidb207912021-08-11 16:41:18 +0800854 ret = pinweaver_eal_memcpy_s(entry->root, sizeof(entry->root), root,
855 sizeof(entry->root));
856 if (ret != EC_SUCCESS)
857 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700858
859 return store_log_data(&log);
860}
861
862int log_auth(struct label_t label, const uint8_t root[PW_HASH_SIZE], int code,
863 struct pw_timestamp_t timestamp)
864{
865 int ret;
866 struct pw_log_storage_t log;
867 struct pw_get_log_entry_t *entry = log.entries;
868
869 ret = log_roll_for_append(&log);
870 if (ret != EC_SUCCESS)
871 return ret;
872
873 entry->type.v = PW_TRY_AUTH;
874 entry->label.v = label.v;
Leo Laidb207912021-08-11 16:41:18 +0800875 ret = pinweaver_eal_memcpy_s(entry->root, sizeof(entry->root), root,
876 sizeof(entry->root));
877 if (ret != EC_SUCCESS)
878 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700879 entry->return_code = code;
Leo Laidb207912021-08-11 16:41:18 +0800880 ret = pinweaver_eal_memcpy_s(&entry->timestamp,
881 sizeof(entry->timestamp), &timestamp,
882 sizeof(entry->timestamp));
883 if (ret != EC_SUCCESS)
884 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700885
886 return store_log_data(&log);
887}
888
889/******************************************************************************/
890/* Per-request-type handler implementations.
891 */
892
893static int pw_handle_reset_tree(struct merkle_tree_t *merkle_tree,
894 const struct pw_request_reset_tree_t *request,
895 uint16_t req_size)
896{
897 struct merkle_tree_t new_tree = {};
898 int ret;
899
900 if (req_size != sizeof(*request))
901 return PW_ERR_LENGTH_INVALID;
902
903 ret = validate_tree_parameters(request->bits_per_level,
904 request->height);
905 if (ret != EC_SUCCESS)
906 return ret;
907
908 ret = create_merkle_tree(request->bits_per_level, request->height,
909 &new_tree);
910 if (ret != EC_SUCCESS)
911 return ret;
912
913 ret = store_merkle_tree(&new_tree);
914 if (ret != EC_SUCCESS)
915 return ret;
916
Leo Laidb207912021-08-11 16:41:18 +0800917 ret = pinweaver_eal_memcpy_s(merkle_tree, sizeof(*merkle_tree),
918 &new_tree, sizeof(new_tree));
919 if (ret != EC_SUCCESS)
920 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700921 return EC_SUCCESS;
922}
923
924static int pw_handle_insert_leaf(struct merkle_tree_t *merkle_tree,
925 const struct pw_request_insert_leaf_t *request,
926 uint16_t req_size,
927 struct pw_response_insert_leaf_t *response,
928 uint16_t *response_size)
929{
930 int ret = EC_SUCCESS;
931 struct leaf_data_t leaf_data = {};
Leo Lai65749082021-08-10 16:32:18 +0800932 struct wrapped_leaf_data_t wrapped_leaf_data = {};
Andrey Pronin9b10e512021-04-13 11:18:53 -0700933 const uint8_t empty_hash[PW_HASH_SIZE] = {};
934 uint8_t new_root[PW_HASH_SIZE];
935
936 if (req_size != sizeof(*request) +
937 get_path_auxiliary_hash_count(merkle_tree) *
938 PW_HASH_SIZE)
939 return PW_ERR_LENGTH_INVALID;
940
941 ret = validate_request_with_path(merkle_tree, request->label,
942 request->path_hashes, empty_hash);
943 if (ret != EC_SUCCESS)
944 return ret;
945
946 ret = validate_delay_schedule(request->delay_schedule);
947 if (ret != EC_SUCCESS)
948 return ret;
949
950 memset(&leaf_data, 0, sizeof(leaf_data));
951 leaf_data.pub.label.v = request->label.v;
Leo Laidb207912021-08-11 16:41:18 +0800952 ret = pinweaver_eal_memcpy_s(&leaf_data.pub.valid_pcr_criteria,
953 sizeof(leaf_data.pub.valid_pcr_criteria),
954 request->valid_pcr_criteria,
955 sizeof(request->valid_pcr_criteria));
956 if (ret != EC_SUCCESS)
957 return PW_ERR_INTERNAL_FAILURE;
958 ret = pinweaver_eal_memcpy_s(&leaf_data.pub.delay_schedule,
959 sizeof(leaf_data.pub.delay_schedule),
960 &request->delay_schedule,
961 sizeof(request->delay_schedule));
962 if (ret != EC_SUCCESS)
963 return PW_ERR_INTERNAL_FAILURE;
964 ret = pinweaver_eal_memcpy_s(&leaf_data.sec.low_entropy_secret,
965 sizeof(leaf_data.sec.low_entropy_secret),
966 &request->low_entropy_secret,
967 sizeof(request->low_entropy_secret));
968 if (ret != EC_SUCCESS)
969 return PW_ERR_INTERNAL_FAILURE;
970 ret = pinweaver_eal_memcpy_s(&leaf_data.sec.high_entropy_secret,
971 sizeof(leaf_data.sec.high_entropy_secret),
972 &request->high_entropy_secret,
973 sizeof(request->high_entropy_secret));
974 if (ret != EC_SUCCESS)
975 return PW_ERR_INTERNAL_FAILURE;
976 ret = pinweaver_eal_memcpy_s(&leaf_data.sec.reset_secret,
977 sizeof(leaf_data.sec.reset_secret),
978 &request->reset_secret,
979 sizeof(request->reset_secret));
980 if (ret != EC_SUCCESS)
981 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700982
983 ret = handle_leaf_update(merkle_tree, &leaf_data, request->path_hashes,
984 &wrapped_leaf_data, new_root, NULL);
985 if (ret != EC_SUCCESS)
986 return ret;
987
988 ret = log_insert_leaf(request->label, new_root,
989 wrapped_leaf_data.hmac);
990 if (ret != EC_SUCCESS)
991 return ret;
992
Leo Laidb207912021-08-11 16:41:18 +0800993 ret = pinweaver_eal_memcpy_s(merkle_tree->root,
994 sizeof(merkle_tree->root), new_root,
995 sizeof(new_root));
996 if (ret != EC_SUCCESS)
997 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -0700998
Leo Laidb207912021-08-11 16:41:18 +0800999 ret = pinweaver_eal_memcpy_s(&response->unimported_leaf_data,
1000 sizeof(wrapped_leaf_data),
1001 &wrapped_leaf_data,
1002 sizeof(wrapped_leaf_data));
1003 if (ret != EC_SUCCESS)
1004 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001005
1006 *response_size = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
1007
1008 return ret;
1009}
1010
1011static int pw_handle_remove_leaf(struct merkle_tree_t *merkle_tree,
1012 const struct pw_request_remove_leaf_t *request,
1013 uint16_t req_size)
1014{
1015 int ret = EC_SUCCESS;
1016 const uint8_t empty_hash[PW_HASH_SIZE] = {};
1017 uint8_t new_root[PW_HASH_SIZE];
1018
1019 if (req_size != sizeof(*request) +
1020 get_path_auxiliary_hash_count(merkle_tree) *
1021 PW_HASH_SIZE)
1022 return PW_ERR_LENGTH_INVALID;
1023
1024 ret = validate_request_with_path(merkle_tree, request->leaf_location,
1025 request->path_hashes,
1026 request->leaf_hmac);
1027 if (ret != EC_SUCCESS)
1028 return ret;
1029
Leo Lai788f41e2021-08-11 00:36:24 +08001030 ret = compute_root_hash(merkle_tree, request->leaf_location,
1031 request->path_hashes, empty_hash, new_root);
1032 if (ret != EC_SUCCESS)
1033 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001034
1035 ret = log_remove_leaf(request->leaf_location, new_root);
1036 if (ret != EC_SUCCESS)
1037 return ret;
1038
Leo Laidb207912021-08-11 16:41:18 +08001039 ret = pinweaver_eal_memcpy_s(merkle_tree->root,
1040 sizeof(merkle_tree->root), new_root,
1041 sizeof(new_root));
1042 if (ret != EC_SUCCESS)
1043 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001044 return ret;
1045}
1046
1047/* Processes a try_auth request.
1048 *
1049 * The valid fields in response based on return code are:
1050 * EC_SUCCESS -> unimported_leaf_data and high_entropy_secret
1051 * PW_ERR_RATE_LIMIT_REACHED -> seconds_to_wait
1052 * PW_ERR_LOWENT_AUTH_FAILED -> unimported_leaf_data
1053 */
1054static int pw_handle_try_auth(struct merkle_tree_t *merkle_tree,
1055 const struct pw_request_try_auth_t *request,
1056 uint16_t req_size,
1057 struct pw_response_try_auth_t *response,
1058 uint16_t *data_length)
1059{
1060 int ret = EC_SUCCESS;
1061 struct leaf_data_t leaf_data = {};
1062 struct imported_leaf_data_t imported_leaf_data;
1063 struct wrapped_leaf_data_t wrapped_leaf_data;
1064 struct time_diff_t seconds_to_wait;
1065 uint8_t zeros[PW_SECRET_SIZE] = {};
1066 uint8_t new_root[PW_HASH_SIZE];
1067
1068 /* These variables help eliminate the possibility of a timing side
1069 * channel that would allow an attacker to prevent the log write.
1070 */
1071 volatile int auth_result;
1072
1073 volatile struct {
1074 uint32_t attempts;
1075 int ret;
1076 uint8_t *secret;
1077 uint8_t *reset_secret;
1078 } results_table[2] = {
1079 { 0, PW_ERR_LOWENT_AUTH_FAILED, zeros, zeros },
1080 { 0, EC_SUCCESS, leaf_data.sec.high_entropy_secret,
1081 leaf_data.sec.reset_secret },
1082 };
1083
1084 if (req_size < sizeof(*request))
1085 return PW_ERR_LENGTH_INVALID;
1086
1087 ret = validate_request_with_wrapped_leaf(
1088 merkle_tree, req_size - sizeof(*request),
1089 &request->unimported_leaf_data, &imported_leaf_data,
1090 &leaf_data);
1091 if (ret != EC_SUCCESS)
1092 return ret;
1093
1094 /* Check if at least one PCR criteria is satisfied if the leaf is
1095 * bound to PCR.
1096 */
1097 ret = validate_pcr_value(leaf_data.pub.valid_pcr_criteria);
1098 if (ret != EC_SUCCESS)
1099 return ret;
1100
1101 ret = test_rate_limit(&leaf_data, &seconds_to_wait);
1102 if (ret != EC_SUCCESS) {
1103 *data_length = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
1104 memset(response, 0, *data_length);
Leo Laidb207912021-08-11 16:41:18 +08001105 pinweaver_eal_memcpy_s(&response->seconds_to_wait,
1106 sizeof(response->seconds_to_wait),
1107 &seconds_to_wait,
1108 sizeof(seconds_to_wait));
Andrey Pronin9b10e512021-04-13 11:18:53 -07001109 return ret;
1110 }
1111
1112 update_timestamp(&leaf_data.pub.timestamp);
1113
1114 /* Precompute the failed attempts. */
1115 results_table[0].attempts = leaf_data.pub.attempt_count.v;
1116 if (results_table[0].attempts != UINT32_MAX)
1117 ++results_table[0].attempts;
1118
1119 /**********************************************************************/
1120 /* After this:
1121 * 1) results_table should not be changed;
1122 * 2) the runtime of the code paths for failed and successful
1123 * authentication attempts should not diverge.
1124 */
Andrey Pronincd7bcce2021-04-14 00:54:12 -07001125 auth_result = pinweaver_eal_safe_memcmp(
1126 request->low_entropy_secret,
1127 leaf_data.sec.low_entropy_secret,
1128 sizeof(request->low_entropy_secret)) == 0;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001129 leaf_data.pub.attempt_count.v = results_table[auth_result].attempts;
1130
1131 /* This has a non-constant time path, but it doesn't convey information
1132 * about whether a PW_ERR_LOWENT_AUTH_FAILED happened or not.
1133 */
1134 ret = handle_leaf_update(merkle_tree, &leaf_data,
1135 imported_leaf_data.hashes, &wrapped_leaf_data,
1136 new_root, &imported_leaf_data);
1137 if (ret != EC_SUCCESS)
1138 return ret;
1139
1140 ret = log_auth(wrapped_leaf_data.pub.label, new_root,
1141 results_table[auth_result].ret, leaf_data.pub.timestamp);
1142 if (ret != EC_SUCCESS) {
Leo Laidb207912021-08-11 16:41:18 +08001143 pinweaver_eal_memcpy_s(new_root, sizeof(new_root),
1144 merkle_tree->root,
1145 sizeof(merkle_tree->root));
Andrey Pronin9b10e512021-04-13 11:18:53 -07001146 return ret;
1147 }
1148 /**********************************************************************/
1149 /* At this point the log should be written so it should be safe for the
1150 * runtime of the code paths to diverge.
1151 */
1152
Leo Laidb207912021-08-11 16:41:18 +08001153 ret = pinweaver_eal_memcpy_s(merkle_tree->root,
1154 sizeof(merkle_tree->root), new_root,
1155 sizeof(new_root));
1156 if (ret != EC_SUCCESS)
1157 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001158
1159 *data_length = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
1160 memset(response, 0, *data_length);
1161
Leo Laidb207912021-08-11 16:41:18 +08001162 ret = pinweaver_eal_memcpy_s(&response->unimported_leaf_data,
1163 sizeof(wrapped_leaf_data),
1164 &wrapped_leaf_data,
1165 sizeof(wrapped_leaf_data));
1166 if (ret != EC_SUCCESS)
1167 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001168
Leo Laidb207912021-08-11 16:41:18 +08001169 ret = pinweaver_eal_memcpy_s(&response->high_entropy_secret,
1170 sizeof(response->high_entropy_secret),
1171 results_table[auth_result].secret,
1172 sizeof(response->high_entropy_secret));
1173 if (ret != EC_SUCCESS)
1174 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001175
Leo Laidb207912021-08-11 16:41:18 +08001176 ret = pinweaver_eal_memcpy_s(&response->reset_secret,
1177 sizeof(response->reset_secret),
1178 results_table[auth_result].reset_secret,
1179 sizeof(response->reset_secret));
1180 if (ret != EC_SUCCESS)
1181 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001182
1183 return results_table[auth_result].ret;
1184}
1185
1186static int pw_handle_reset_auth(struct merkle_tree_t *merkle_tree,
1187 const struct pw_request_reset_auth_t *request,
1188 uint16_t req_size,
1189 struct pw_response_reset_auth_t *response,
1190 uint16_t *response_size)
1191{
1192 int ret = EC_SUCCESS;
1193 struct leaf_data_t leaf_data = {};
1194 struct imported_leaf_data_t imported_leaf_data;
1195 struct wrapped_leaf_data_t wrapped_leaf_data;
1196 uint8_t new_root[PW_HASH_SIZE];
1197
1198 if (req_size < sizeof(*request))
1199 return PW_ERR_LENGTH_INVALID;
1200
1201 ret = validate_request_with_wrapped_leaf(
1202 merkle_tree, req_size - sizeof(*request),
1203 &request->unimported_leaf_data, &imported_leaf_data,
1204 &leaf_data);
1205 if (ret != EC_SUCCESS)
1206 return ret;
1207
1208 /* Safe memcmp is used here to prevent an attacker from being able to
1209 * brute force the reset secret and use it to unlock the leaf.
1210 * memcmp provides an attacker a timing side-channel they can use to
1211 * determine how much of a prefix is correct.
1212 */
Andrey Pronincd7bcce2021-04-14 00:54:12 -07001213 if (pinweaver_eal_safe_memcmp(request->reset_secret,
1214 leaf_data.sec.reset_secret,
1215 sizeof(request->reset_secret)) != 0)
Andrey Pronin9b10e512021-04-13 11:18:53 -07001216 return PW_ERR_RESET_AUTH_FAILED;
1217
1218 leaf_data.pub.attempt_count.v = 0;
1219
1220 ret = handle_leaf_update(merkle_tree, &leaf_data,
1221 imported_leaf_data.hashes, &wrapped_leaf_data,
1222 new_root, &imported_leaf_data);
1223 if (ret != EC_SUCCESS)
1224 return ret;
1225
1226 ret = log_auth(leaf_data.pub.label, new_root, ret,
1227 leaf_data.pub.timestamp);
1228 if (ret != EC_SUCCESS)
1229 return ret;
1230
Leo Laidb207912021-08-11 16:41:18 +08001231 ret = pinweaver_eal_memcpy_s(merkle_tree->root,
1232 sizeof(merkle_tree->root), new_root,
1233 sizeof(new_root));
1234 if (ret != EC_SUCCESS)
1235 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001236
Leo Laidb207912021-08-11 16:41:18 +08001237 ret = pinweaver_eal_memcpy_s(&response->unimported_leaf_data,
1238 sizeof(wrapped_leaf_data),
1239 &wrapped_leaf_data,
1240 sizeof(wrapped_leaf_data));
1241 if (ret != EC_SUCCESS)
1242 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001243
Leo Laidb207912021-08-11 16:41:18 +08001244 ret = pinweaver_eal_memcpy_s(response->high_entropy_secret,
1245 sizeof(response->high_entropy_secret),
1246 leaf_data.sec.high_entropy_secret,
1247 sizeof(response->high_entropy_secret));
1248 if (ret != EC_SUCCESS)
1249 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001250
1251 *response_size = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
1252
1253 return ret;
1254}
1255
1256static int pw_handle_get_log(const struct merkle_tree_t *merkle_tree,
1257 const struct pw_request_get_log_t *request,
1258 uint16_t req_size,
1259 struct pw_get_log_entry_t response[],
1260 uint16_t *response_size)
1261{
1262 int ret;
1263 int x;
1264 struct pw_log_storage_t log;
1265
1266 if (req_size != sizeof(*request))
1267 return PW_ERR_LENGTH_INVALID;
1268
1269 ret = validate_tree(merkle_tree);
1270 if (ret != EC_SUCCESS)
1271 return ret;
1272
1273 ret = load_log_data(&log);
1274 if (ret != EC_SUCCESS)
1275 return ret;
1276
1277 /* Find the relevant log entry. The return value isn't used because if
1278 * the entry isn't found the entire log is returned. This makes it
1279 * easier to recover when the log is too short.
1280 *
1281 * Here is an example:
1282 * 50 attempts have been made against a leaf that becomes out of sync
1283 * because of a disk flush failing. The copy of the leaf on disk is
1284 * behind by 50 and the log contains less than 50 entries. The CrOS
1285 * implementation can check the public parameters of the local copy with
1286 * the log entry to determine that leaf is out of sync. It can then send
1287 * any valid copy of that leaf with a log replay request that will only
1288 * succeed if the HMAC of the resulting leaf matches the log entry.
1289 */
1290 find_relevant_entry(&log, request->root, &x);
1291 /* If there are no valid entries, return. */
1292 if (x < 0)
1293 return EC_SUCCESS;
1294
1295 /* Copy the entries in reverse order. */
1296 while (1) {
Leo Laidb207912021-08-11 16:41:18 +08001297 ret = pinweaver_eal_memcpy_s(&response[x], sizeof(response[x]),
1298 &log.entries[x],
1299 sizeof(log.entries[x]));
1300 if (ret != EC_SUCCESS)
1301 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001302 *response_size += sizeof(log.entries[x]);
1303 if (x == 0)
1304 break;
1305 --x;
1306 }
1307
1308 return EC_SUCCESS;
1309}
1310
1311static int pw_handle_log_replay(const struct merkle_tree_t *merkle_tree,
1312 const struct pw_request_log_replay_t *request,
1313 uint16_t req_size,
1314 struct pw_response_log_replay_t *response,
1315 uint16_t *response_size)
1316{
1317 int ret;
1318 int x;
1319 struct pw_log_storage_t log;
1320 struct leaf_data_t leaf_data = {};
1321 struct imported_leaf_data_t imported_leaf_data;
1322 struct wrapped_leaf_data_t wrapped_leaf_data;
1323 uint8_t hmac[PW_HASH_SIZE];
1324 uint8_t root[PW_HASH_SIZE];
1325
1326 if (req_size < sizeof(*request))
1327 return PW_ERR_LENGTH_INVALID;
1328
1329 ret = validate_tree(merkle_tree);
1330 if (ret != EC_SUCCESS)
1331 return ret;
1332
1333 /* validate_request_with_wrapped_leaf() isn't used here because the
1334 * path validation is delayed to allow any valid copy of the same leaf
1335 * to be used in the replay operation as long as the result passes path
1336 * validation.
1337 */
1338 ret = validate_leaf_header(&request->unimported_leaf_data.head,
1339 req_size - sizeof(*request),
1340 get_path_auxiliary_hash_count(merkle_tree));
1341 if (ret != EC_SUCCESS)
1342 return ret;
1343
1344 import_leaf(&request->unimported_leaf_data, &imported_leaf_data);
1345
1346 ret = load_log_data(&log);
1347 if (ret != EC_SUCCESS)
1348 return ret;
1349
1350 /* Find the relevant log entry. */
1351 ret = find_relevant_entry(&log, request->log_root, &x);
1352 if (ret != EC_SUCCESS)
1353 return ret;
1354
1355 /* The other message types don't need to be handled by Cr50. */
1356 if (log.entries[x].type.v != PW_TRY_AUTH)
1357 return PW_ERR_TYPE_INVALID;
1358
Leo Lai788f41e2021-08-11 00:36:24 +08001359 ret = compute_hmac(merkle_tree, &imported_leaf_data, hmac);
1360 if (ret != EC_SUCCESS)
1361 return ret;
Andrey Pronincd7bcce2021-04-14 00:54:12 -07001362 if (pinweaver_eal_safe_memcmp(hmac,
1363 request->unimported_leaf_data.hmac,
1364 sizeof(hmac)))
Andrey Pronin9b10e512021-04-13 11:18:53 -07001365 return PW_ERR_HMAC_AUTH_FAILED;
1366
1367 ret = decrypt_leaf_data(merkle_tree, &imported_leaf_data, &leaf_data);
1368 if (ret != EC_SUCCESS)
1369 return ret;
1370
1371 if (leaf_data.pub.label.v != log.entries[x].label.v)
1372 return PW_ERR_LABEL_INVALID;
1373
1374 /* Update the metadata to match the log. */
1375 if (log.entries[x].return_code == EC_SUCCESS)
1376 leaf_data.pub.attempt_count.v = 0;
1377 else
1378 ++leaf_data.pub.attempt_count.v;
Leo Laidb207912021-08-11 16:41:18 +08001379 ret = pinweaver_eal_memcpy_s(&leaf_data.pub.timestamp,
1380 sizeof(leaf_data.pub.timestamp),
1381 &log.entries[x].timestamp,
1382 sizeof(leaf_data.pub.timestamp));
1383 if (ret != EC_SUCCESS)
1384 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001385
1386 ret = handle_leaf_update(merkle_tree, &leaf_data,
1387 imported_leaf_data.hashes, &wrapped_leaf_data,
1388 root, &imported_leaf_data);
1389 if (ret != EC_SUCCESS)
1390 return ret;
1391
Yi Chouddf3b452021-08-11 13:40:11 +08001392 if (pinweaver_eal_safe_memcmp(root, log.entries[x].root, PW_HASH_SIZE))
Andrey Pronin9b10e512021-04-13 11:18:53 -07001393 return PW_ERR_PATH_AUTH_FAILED;
1394
Leo Laidb207912021-08-11 16:41:18 +08001395 ret = pinweaver_eal_memcpy_s(&response->unimported_leaf_data,
1396 sizeof(wrapped_leaf_data),
1397 &wrapped_leaf_data,
1398 sizeof(wrapped_leaf_data));
1399 if (ret != EC_SUCCESS)
1400 return PW_ERR_INTERNAL_FAILURE;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001401
1402 *response_size = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
1403
1404 return EC_SUCCESS;
1405}
1406
1407struct merkle_tree_t pw_merkle_tree;
1408
Andrey Pronin9b10e512021-04-13 11:18:53 -07001409/******************************************************************************/
1410/* Non-static functions.
1411 */
1412
1413void pinweaver_init(void)
1414{
1415 load_merkle_tree(&pw_merkle_tree);
1416}
1417
1418int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree)
1419{
1420 return ((1 << merkle_tree->bits_per_level.v) - 1) *
1421 merkle_tree->height.v;
1422}
1423
1424/* Computes the SHA256 parent hash of a set of child hashes given num_hashes
1425 * sibling hashes in hashes[] and the index of child_hash.
1426 *
1427 * Assumptions:
1428 * num_hashes == fan_out - 1
1429 * ARRAY_SIZE(hashes) == num_hashes
1430 * 0 <= location <= num_hashes
1431 */
Leo Lai788f41e2021-08-11 00:36:24 +08001432int compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
1433 struct index_t location,
1434 const uint8_t child_hash[PW_HASH_SIZE],
1435 uint8_t result[PW_HASH_SIZE])
Andrey Pronin9b10e512021-04-13 11:18:53 -07001436{
Leo Lai788f41e2021-08-11 00:36:24 +08001437 int ret;
Andrey Pronincd7bcce2021-04-14 00:54:12 -07001438 pinweaver_eal_sha256_ctx_t ctx;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001439
Leo Lai788f41e2021-08-11 00:36:24 +08001440 ret = pinweaver_eal_sha256_init(&ctx);
1441 if (ret)
1442 return ret;
Andrey Pronin9b10e512021-04-13 11:18:53 -07001443 if (location.v > 0)
Andrey Pronincd7bcce2021-04-14 00:54:12 -07001444 pinweaver_eal_sha256_update(&ctx, hashes[0],
1445 PW_HASH_SIZE * location.v);
Leo Lai788f41e2021-08-11 00:36:24 +08001446 if (ret) {
1447 pinweaver_eal_sha256_final(&ctx, result);
1448 return ret;
1449 }
1450 ret = pinweaver_eal_sha256_update(&ctx, child_hash, PW_HASH_SIZE);
1451 if (ret) {
1452 pinweaver_eal_sha256_final(&ctx, result);
1453 return ret;
1454 }
1455 if (location.v < num_hashes) {
1456 ret = pinweaver_eal_sha256_update(
1457 &ctx, hashes[location.v],
1458 PW_HASH_SIZE * (num_hashes - location.v));
1459 if (ret) {
1460 pinweaver_eal_sha256_final(&ctx, result);
1461 return ret;
1462 }
1463 }
1464 return pinweaver_eal_sha256_final(&ctx, result);
Andrey Pronin9b10e512021-04-13 11:18:53 -07001465}
1466
1467/* If a request from older protocol comes, this method should make it
1468 * compatible with the current request structure.
1469 */
1470int make_compatible_request(struct merkle_tree_t *merkle_tree,
1471 struct pw_request_t *request)
1472{
1473 switch (request->header.version) {
1474 case 0:
1475 /* The switch from protocol version 0 to 1 means all the
1476 * requests have the same format, except insert_leaf.
1477 * Update the request in that case.
1478 */
1479 if (request->header.type.v == PW_INSERT_LEAF) {
1480 unsigned char *src = (unsigned char *)
1481 (&request->data.insert_leaf00.path_hashes);
1482 unsigned char *dest = (unsigned char *)
1483 (&request->data.insert_leaf.path_hashes);
1484 const int hash_count =
1485 get_path_auxiliary_hash_count(merkle_tree);
1486 const uint16_t hashes_size = hash_count * PW_HASH_SIZE;
1487
1488 memmove(dest, src, hashes_size);
1489 memset(&request->data.insert_leaf.valid_pcr_criteria,
1490 0, PW_VALID_PCR_CRITERIA_SIZE);
1491 request->header.data_length +=
1492 PW_VALID_PCR_CRITERIA_SIZE;
1493 }
1494 /* Fallthrough to make compatible from next version */
Leo Lai8c9892c2021-06-22 21:32:02 +08001495 __attribute__((fallthrough));
Andrey Pronin9b10e512021-04-13 11:18:53 -07001496 case PW_PROTOCOL_VERSION:
1497 return 1;
1498 }
1499 /* Unsupported version. */
1500 return 0;
1501}
1502
1503/* Converts the response to be understandable by an older protocol.
1504 */
1505void make_compatible_response(int version, int req_type,
1506 struct pw_response_t *response)
1507{
1508 if (version >= PW_PROTOCOL_VERSION)
1509 return;
1510
1511 response->header.version = version;
1512 if (version == 0) {
1513 if (req_type == PW_TRY_AUTH) {
1514 unsigned char *src = (unsigned char *)
1515 (&response->data.try_auth.unimported_leaf_data);
1516 unsigned char *dest = (unsigned char *)
1517 (&response->data.try_auth00.unimported_leaf_data);
1518 memmove(dest, src,
1519 PW_LEAF_PAYLOAD_SIZE +
1520 sizeof(struct unimported_leaf_data_t));
1521 response->header.data_length -= PW_SECRET_SIZE;
1522 }
1523 }
1524}
1525
Andrey Pronincd7bcce2021-04-14 00:54:12 -07001526enum pinweaver_command_res_t pinweaver_command(void *request_buf,
1527 size_t request_size,
1528 void *response_buf,
1529 size_t *response_size) {
1530 struct pw_request_t *request = request_buf;
1531 struct pw_response_t *response = response_buf;
1532
1533 if (request_size < sizeof(request->header)) {
1534 PINWEAVER_EAL_INFO(
1535 "PinWeaver: message smaller than a header (%zd).\n",
1536 request_size);
1537 return PW_CMD_RES_TOO_SMALL;
1538 }
1539
1540 if (request_size != request->header.data_length +
1541 sizeof(request->header)) {
1542 PINWEAVER_EAL_INFO(
1543 "PinWeaver: header size mismatch %zd != %zd.\n",
1544 request_size,
1545 request->header.data_length + sizeof(request->header));
1546 return PW_CMD_RES_SIZE;
1547 }
1548
1549 /* The response_size is validated by compile time checks. */
1550
1551 /* The return value of this function call is intentionally unused. */
1552 pw_handle_request(&pw_merkle_tree, request, response);
1553
1554 *response_size = response->header.data_length +
1555 sizeof(response->header);
1556
1557 /* The response is only sent for EC_SUCCESS so it is used even for
1558 * errors which are reported through header.return_code.
1559 */
1560 return PW_CMD_RES_SUCCESS;
1561}
1562
1563
Andrey Pronin9b10e512021-04-13 11:18:53 -07001564/* Handles the message in request using the context in merkle_tree and writes
1565 * the results to response. The return value captures any error conditions that
1566 * occurred or EC_SUCCESS if there were no errors.
1567 *
1568 * This implementation is written to handle the case where request and response
1569 * exist at the same memory location---are backed by the same buffer. This means
1570 * the implementation requires that no reads are made to request after response
1571 * has been written to.
1572 */
1573int pw_handle_request(struct merkle_tree_t *merkle_tree,
1574 struct pw_request_t *request,
1575 struct pw_response_t *response)
1576{
1577 int32_t ret;
1578 uint16_t resp_length;
1579 /* Store the message type of the request since it may be overwritten
1580 * inside the switch whenever response and request overlap in memory.
1581 */
1582 struct pw_message_type_t type = request->header.type;
1583 int version = request->header.version;
1584
1585 resp_length = 0;
1586
1587 if (!make_compatible_request(merkle_tree, request)) {
1588 ret = PW_ERR_VERSION_MISMATCH;
1589 goto cleanup;
1590 }
1591 switch (type.v) {
1592 case PW_RESET_TREE:
1593 ret = pw_handle_reset_tree(merkle_tree,
1594 &request->data.reset_tree,
1595 request->header.data_length);
1596 break;
1597 case PW_INSERT_LEAF:
1598 ret = pw_handle_insert_leaf(merkle_tree,
1599 &request->data.insert_leaf,
1600 request->header.data_length,
1601 &response->data.insert_leaf,
1602 &resp_length);
1603 break;
1604 case PW_REMOVE_LEAF:
1605 ret = pw_handle_remove_leaf(merkle_tree,
1606 &request->data.remove_leaf,
1607 request->header.data_length);
1608 break;
1609 case PW_TRY_AUTH:
1610 ret = pw_handle_try_auth(merkle_tree, &request->data.try_auth,
1611 request->header.data_length,
1612 &response->data.try_auth,
1613 &resp_length);
1614 break;
1615 case PW_RESET_AUTH:
1616 ret = pw_handle_reset_auth(merkle_tree,
1617 &request->data.reset_auth,
1618 request->header.data_length,
1619 &response->data.reset_auth,
1620 &resp_length);
1621 break;
1622 case PW_GET_LOG:
1623 ret = pw_handle_get_log(merkle_tree, &request->data.get_log,
1624 request->header.data_length,
1625 (void *)&response->data, &resp_length);
1626 break;
1627 case PW_LOG_REPLAY:
1628 ret = pw_handle_log_replay(merkle_tree,
1629 &request->data.log_replay,
1630 request->header.data_length,
1631 &response->data.log_replay,
1632 &resp_length);
1633 break;
1634 default:
1635 ret = PW_ERR_TYPE_INVALID;
1636 break;
1637 }
1638cleanup:
1639 response->header.version = PW_PROTOCOL_VERSION;
1640 response->header.data_length = resp_length;
1641 response->header.result_code = ret;
Leo Laidb207912021-08-11 16:41:18 +08001642 if (pinweaver_eal_memcpy_s(&response->header.root,
1643 sizeof(response->header.root),
1644 merkle_tree->root,
1645 sizeof(merkle_tree->root))) {
1646 ret = PW_ERR_INTERNAL_FAILURE;
1647 }
Andrey Pronin9b10e512021-04-13 11:18:53 -07001648
1649 make_compatible_response(version, type.v, response);
1650
1651 return ret;
1652};