blob: 5546f86e1e3f14eb3335f0581eae982a3ccee162 [file] [log] [blame]
Nan Zhou7a337042021-07-26 21:05:21 -07001/*
2 * Copyright 2021 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "libcr51sign.h"
17
18#include <assert.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#ifdef __cplusplus
24extern "C"
25{
26#endif
27
28#ifndef USER_PRINT
29#define CPRINTS(ctx, format, args...) printf(format, ##args)
30#endif
31
32#define MEMBER_SIZE(type, field) sizeof(((type*)0)->field)
33
34// True of x is a power of two
35#define POWER_OF_TWO(x) ((x) && !((x) & ((x)-1)))
36
37// Maximum version supported. Major revisions are not backwards compatible.
38#define MAX_MAJOR_VERSION 1
39
40#define MAX_REGION_COUNT 16
41
42// Descriptor alignment on the external EEPROM.
43#define DESCRIPTOR_ALIGNMENT (64 * 1024)
44
45// SPS EEPROM sector size is 4KiB, since this is the smallest erasable size.
46#define IMAGE_REGION_ALIGNMENT 4096
47
48#define MAX_READ_SIZE 1024
49
50#ifndef ARRAY_SIZE
51#define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0]))
52#endif
53
54// Values of SIGNATURE_OFFSET shuold be same for all sig types (2048,3072,4096)
55#define SIGNATURE_OFFSET offsetof(struct signature_rsa3072_pkcs15, modulus)
56
57#ifndef BUILD_ASSERT
58#define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
59#endif
60
61 typedef enum libcr51sign_validation_failure_reason failure_reason;
62
63 // Returns the bytes size of keys used in the given signature_scheme.
64 // Return error if signature_scheme is invalid.
65 //
66 static failure_reason get_key_size(enum signature_scheme signature_scheme,
67 uint16_t* key_size)
68 {
69 switch (signature_scheme)
70 {
71 case SIGNATURE_RSA2048_PKCS15:
72 *key_size = 256;
73 return LIBCR51SIGN_SUCCESS;
74 case SIGNATURE_RSA3072_PKCS15:
75 *key_size = 384;
76 return LIBCR51SIGN_SUCCESS;
77 case SIGNATURE_RSA4096_PKCS15:
78 case SIGNATURE_RSA4096_PKCS15_SHA512:
79 *key_size = 512;
80 return LIBCR51SIGN_SUCCESS;
81 default:
82 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
83 }
84 }
85
86 // Returns the hash_type for a given signature scheme
87 // Returns error if scheme is invalid.
88 failure_reason get_hash_type_from_signature(enum signature_scheme scheme,
89 enum hash_type* type)
90 {
91 switch (scheme)
92 {
93 case SIGNATURE_RSA2048_PKCS15:
94 case SIGNATURE_RSA3072_PKCS15:
95 case SIGNATURE_RSA4096_PKCS15:
96 *type = HASH_SHA2_256;
97 return LIBCR51SIGN_SUCCESS;
98 case SIGNATURE_RSA4096_PKCS15_SHA512:
99 *type = HASH_SHA2_512;
100 return LIBCR51SIGN_SUCCESS;
101 default:
102 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
103 }
104 }
105
106 // Check if the given hash_type is supported.
107 // Returns error if hash_type is not supported.
108 static failure_reason is_hash_type_supported(enum hash_type type)
109 {
110 switch (type)
111 {
112 case HASH_SHA2_256:
113 case HASH_SHA2_512:
114 return LIBCR51SIGN_SUCCESS;
115 default:
116 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
117 }
118 }
119
120 // Determines digest size for a given hash_type.
121 // Returns error if hash_type is not supported.
122 static failure_reason get_hash_digest_size(enum hash_type type,
123 uint32_t* size)
124 {
125 switch (type)
126 {
127 case HASH_SHA2_256:
128 *size = SHA256_DIGEST_SIZE;
129 return LIBCR51SIGN_SUCCESS;
130 case HASH_SHA2_512:
131 *size = SHA512_DIGEST_SIZE;
132 return LIBCR51SIGN_SUCCESS;
133 default:
134 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
135 }
136 }
137
138 // Determines hash struct size for a given hash_type.
139 // Returns error if hash_type is not supported.
140 static failure_reason get_hash_struct_size(enum hash_type type,
141 uint32_t* size)
142 {
143 switch (type)
144 {
145 case HASH_SHA2_256:
146 *size = sizeof(struct hash_sha256);
147 return LIBCR51SIGN_SUCCESS;
148 case HASH_SHA2_512:
149 *size = sizeof(struct hash_sha256);
150 return LIBCR51SIGN_SUCCESS;
151 default:
152 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
153 }
154 }
155
156 // Checks that:
157 // - The signing key is trusted
158 // - The target version is not denylisted
159 // If validating a staged update, also checks that:
160 // - The target image family matches the current image family
161 // - The image type transition is legal (i.e. dev -> *|| prod -> prod) or
162 // alternatively that the hardware ID is allowlisted
163 // Assuming the caller has performed following:
164 // board_get_base_key_index();
165 // board_get_key_array
166 // Possible return codes:
167 // LIBCR51SIGN_SUCCESS = 0,
168 // LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
169 // LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
170 // LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
171 // LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
172
173 static failure_reason
174 validate_transition(const struct libcr51sign_ctx* ctx,
175 const struct libcr51sign_intf* intf,
176 uint32_t signature_struct_offset)
177 {
178 BUILD_ASSERT((offsetof(struct signature_rsa2048_pkcs15, modulus) ==
179 SIGNATURE_OFFSET &&
180 offsetof(struct signature_rsa3072_pkcs15, modulus) ==
181 SIGNATURE_OFFSET &&
182 offsetof(struct signature_rsa4096_pkcs15, modulus) ==
183 SIGNATURE_OFFSET));
184
185 // Read up to the modulus.
186 const uint32_t read_len = SIGNATURE_OFFSET;
187 uint8_t buffer[read_len];
188 // "modulus" & "signature" will not be indexed.
189 struct signature_rsa4096_pkcs15* sig_data = (void*)&buffer;
190 int rv;
191 rv = intf->read(ctx, signature_struct_offset, read_len, buffer);
192 if (rv != LIBCR51SIGN_SUCCESS)
193 {
194 CPRINTS(ctx,
195 "validate_transition: failed to read signature struct");
196 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
197 }
198 if (sig_data->signature_magic != SIGNATURE_MAGIC)
199 {
200 CPRINTS(ctx, "validate_transition: bad signature magic");
201 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
202 }
203
204 if (ctx->descriptor.image_family != ctx->current_image_family &&
205 ctx->descriptor.image_family != IMAGE_FAMILY_ALL &&
206 ctx->current_image_family != IMAGE_FAMILY_ALL)
207 {
208 CPRINTS(ctx, "validate_transition: invalid image family");
209 return LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY;
210 }
211
212 if (!intf->is_production_mode)
213 {
214 CPRINTS(ctx, "validate_transition: missing is_production_mode");
215 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
216 }
217 if (intf->is_production_mode() &&
218 (ctx->descriptor.image_type == IMAGE_DEV))
219 {
220 CPRINTS(ctx, "validate_transition: checking exemption allowlist");
221
222 if (!intf->prod_to_dev_downgrade_allowed)
223 {
224 return LIBCR51SIGN_SUCCESS;
225 }
226 else if (!intf->prod_to_dev_downgrade_allowed())
227 {
228 CPRINTS(ctx, "validate_transition: illegal image type");
229 return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED;
230 }
231 }
232 return LIBCR51SIGN_SUCCESS;
233 }
234
235 // If caller had provided read_and_hash_update call that, otherwise call
236 // read and then update.
237
238 static failure_reason
239 read_and_hash_update(const struct libcr51sign_ctx* ctx,
240 const struct libcr51sign_intf* intf,
241 uint32_t offset, uint32_t size)
242 {
243 uint8_t read_buffer[MAX_READ_SIZE];
244 int rv;
245 int read_size;
246
247 if (intf->read_and_hash_update)
248 {
249 rv = intf->read_and_hash_update((void*)ctx, offset, size);
250 }
251 else
252 {
253 if (!intf->hash_update)
254 {
255 CPRINTS(ctx, "read_and_hash_update: missing hash_update");
256 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
257 }
258 do
259 {
260 read_size = size < MAX_READ_SIZE ? size : MAX_READ_SIZE;
261 rv = intf->read((void*)ctx, offset, read_size, read_buffer);
262 if (rv != LIBCR51SIGN_SUCCESS)
263 {
264 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
265 }
266 rv = intf->hash_update((void*)ctx, read_buffer, read_size);
267 if (rv != LIBCR51SIGN_SUCCESS)
268 {
269 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
270 }
271 offset += read_size;
272 size -= read_size;
273 } while (size > 0);
274 }
275 return rv;
276 }
277
278 // Validates the image_region array, namely that:
279 // - The regions are aligned, contiguous & exhaustive
280 // - That the image descriptor resides in a static region
281 //
282 // If the array is consistent, proceeds to hash the static regions and
283 // validates the hash. d_offset is the absolute image descriptor offset
284
285 static failure_reason
286 validate_payload_regions(const struct libcr51sign_ctx* ctx,
287 struct libcr51sign_intf* intf,
288 uint32_t d_offset)
289 {
290 // Allocate buffer to accomodate largest supported hash-type(SHA512)
291 uint8_t magic_and_digest[MEMBER_SIZE(struct hash_sha512, hash_magic) +
292 SHA512_DIGEST_SIZE];
293 uint8_t dcrypto_digest[SHA512_DIGEST_SIZE];
294 struct image_region regions[MAX_REGION_COUNT];
295 uint32_t byte_count, region_count, image_size, hash_offset, digest_size;
296 uint8_t d_region_num = 0;
297 int i, rv;
298
299 BUILD_ASSERT((MEMBER_SIZE(struct hash_sha256, hash_magic) ==
300 MEMBER_SIZE(struct hash_sha512, hash_magic)));
301 image_size = ctx->descriptor.image_size;
302 region_count = ctx->descriptor.region_count;
303 hash_offset = d_offset + sizeof(struct image_descriptor) +
304 region_count * sizeof(struct image_region);
305 // Read the image_region array.
306 rv = intf->read(
307 ctx, d_offset + offsetof(struct image_descriptor, image_regions),
308 region_count * sizeof(struct image_region), (uint8_t*)&regions);
309 if (rv != LIBCR51SIGN_SUCCESS)
310 {
311 CPRINTS(ctx,
312 "validate_payload_regions: failed to read region array");
313 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
314 }
315
316 // Validate that the regions are contiguous & exhaustive.
317 for (i = 0, byte_count = 0; i < region_count; i++)
318 {
319 CPRINTS(ctx,
320 "validate_payload_regions: region #%d \"%s\" (%x - %x)", i,
321 regions[i].region_name, regions[i].region_offset,
322 regions[i].region_offset + regions[i].region_size);
323 if ((regions[i].region_offset % IMAGE_REGION_ALIGNMENT) != 0 ||
324 (regions[i].region_size % IMAGE_REGION_ALIGNMENT) != 0)
325 {
326 CPRINTS(
327 ctx,
328 "validate_payload_regions: regions must be sector aligned");
329 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
330 }
331 if (regions[i].region_offset != byte_count ||
332 regions[i].region_size > image_size - byte_count)
333 {
334 CPRINTS(ctx, "validate_payload_regions: invalid region array");
335 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
336 }
337 byte_count += regions[i].region_size;
338 // The image descriptor must be part of a static region.
339 if (d_offset >= regions[i].region_offset && d_offset < byte_count)
340 {
341 d_region_num = i;
342 CPRINTS(
343 ctx,
344 "validate_payload_regions: image descriptor in region %d",
345 i);
346 // The descriptor can't span regions.
347 if (ctx->descriptor.descriptor_area_size > byte_count ||
348 !(regions[i].region_attributes & IMAGE_REGION_STATIC))
349 {
350 CPRINTS(
351 ctx,
352 "validate_payload_regions: descriptor must reside in "
353 "static region");
354 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
355 }
356 }
357 }
358 if (byte_count != image_size)
359 {
360 CPRINTS(ctx, "validate_payload_regions: invalid image size");
361 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
362 }
363
364 rv = get_hash_digest_size(ctx->descriptor.hash_type, &digest_size);
365 if (rv != LIBCR51SIGN_SUCCESS)
366 {
367 return rv;
368 }
369
370 rv = intf->read(ctx, hash_offset,
371 MEMBER_SIZE(struct hash_sha256, hash_magic) +
372 digest_size,
373 magic_and_digest);
374 if (rv != LIBCR51SIGN_SUCCESS)
375 {
376 CPRINTS(ctx,
377 "validate_payload_regions: failed to read hash from flash");
378 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
379 }
380 if (*(uint32_t*)magic_and_digest != HASH_MAGIC)
381 {
382 CPRINTS(ctx, "validate_payload_regions: bad hash magic");
383 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
384 }
385 rv = intf->hash_init(ctx, ctx->descriptor.hash_type);
386 if (rv != LIBCR51SIGN_SUCCESS)
387 {
388 CPRINTS(ctx, "validate_payload_regions: hash_init failed");
389 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
390 }
391 for (i = 0; i < region_count; i++)
392 {
393 uint32_t hash_start, hash_size;
394 if (!(regions[i].region_attributes & IMAGE_REGION_STATIC))
395 {
396 continue;
397 }
398 hash_start = regions[i].region_offset;
399 hash_size = regions[i].region_size;
400
401 // Skip the descriptor.
402 do
403 {
404 if (i == d_region_num)
405 {
406 hash_size = d_offset - hash_start;
407 }
408
409 if (!hash_size)
410 {
411 hash_start += ctx->descriptor.descriptor_area_size;
412 hash_size = (regions[i].region_offset +
413 regions[i].region_size - hash_start);
414 }
415 CPRINTS("validate_payload_regions: hashing %s (%x - %x)",
416 regions[i].region_name, hash_start,
417 hash_start + hash_size);
418 // Read the image_region array.
419 rv = read_and_hash_update(ctx, intf, hash_start, hash_size);
420 if (rv != LIBCR51SIGN_SUCCESS)
421 {
422 return rv;
423 }
424 hash_start += hash_size;
425 } while (hash_start !=
426 regions[i].region_offset + regions[i].region_size);
427 }
428 rv = intf->hash_final((void*)ctx, (uint8_t*)dcrypto_digest);
429
430 if (rv != LIBCR51SIGN_SUCCESS)
431 {
432 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
433 }
434
435 if (memcmp(magic_and_digest +
436 MEMBER_SIZE(struct hash_sha256, hash_magic),
437 dcrypto_digest, digest_size))
438 {
439 CPRINTS(ctx, "validate_payload_regions: invalid hash");
440 return LIBCR51SIGN_ERROR_INVALID_HASH;
441 }
442 // Image is valid.
443 return LIBCR51SIGN_SUCCESS;
444 }
445
446 // Check if the given signature_scheme is supported.
447 // Returns nonzero on error, zero on success
448
449 static failure_reason
450 is_signature_scheme_supported(enum signature_scheme scheme)
451 {
452 switch (scheme)
453 {
454 case SIGNATURE_RSA2048_PKCS15:
455 case SIGNATURE_RSA3072_PKCS15:
456 case SIGNATURE_RSA4096_PKCS15:
457 case SIGNATURE_RSA4096_PKCS15_SHA512:
458 return LIBCR51SIGN_SUCCESS;
459 default:
460 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
461 }
462 }
463
464 // Returns size of signature struct size in |size|
465 // Returns nonzero on error, zero on success
466
467 static failure_reason
468 get_signature_struct_size(enum signature_scheme scheme, uint32_t* size)
469 {
470 switch (scheme)
471 {
472 case SIGNATURE_RSA2048_PKCS15:
473 *size = sizeof(struct signature_rsa2048_pkcs15);
474 return LIBCR51SIGN_SUCCESS;
475 case SIGNATURE_RSA3072_PKCS15:
476 *size = sizeof(struct signature_rsa3072_pkcs15);
477 return LIBCR51SIGN_SUCCESS;
478 case SIGNATURE_RSA4096_PKCS15:
479 case SIGNATURE_RSA4096_PKCS15_SHA512:
480 *size = sizeof(struct signature_rsa4096_pkcs15);
481 return LIBCR51SIGN_SUCCESS;
482 default:
483 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
484 }
485 }
486
487 static failure_reason
488 get_signature_field_offset(enum signature_scheme scheme,
489 uint32_t* offset)
490 {
491 switch (scheme)
492 {
493 case SIGNATURE_RSA2048_PKCS15:
494 *offset = offsetof(struct signature_rsa2048_pkcs15, signature);
495 return LIBCR51SIGN_SUCCESS;
496 case SIGNATURE_RSA3072_PKCS15:
497 *offset = offsetof(struct signature_rsa3072_pkcs15, signature);
498 return LIBCR51SIGN_SUCCESS;
499 case SIGNATURE_RSA4096_PKCS15:
500 case SIGNATURE_RSA4096_PKCS15_SHA512:
501 *offset = offsetof(struct signature_rsa4096_pkcs15, signature);
502 return LIBCR51SIGN_SUCCESS;
503 default:
504 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
505 }
506 }
507
508 // Validates the signature (of type scheme) read from "device" at
509 //"raw_signature_offset" with "public_key" over a SHA256/SHA512 digest of
510 // EEPROM area "data_offset:data_size".
511
512 static failure_reason validate_signature(
513 const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
514 uint32_t data_offset, uint32_t data_size, enum signature_scheme scheme,
515 uint32_t raw_signature_offset)
516 {
517 uint8_t signature[MAX_SIGNATURE_SIZE];
518 uint16_t key_size;
519 uint32_t digest_size;
520 uint8_t dcrypto_digest[SHA512_DIGEST_SIZE];
521 int rv;
522 enum hash_type hash_type;
523
524 if (!intf->hash_init)
525 {
526 CPRINTS(ctx, "validate_signature: missing hash_init");
527 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
528 }
529 rv = get_hash_type_from_signature(scheme, &hash_type);
530 if (rv != LIBCR51SIGN_SUCCESS)
531 {
532 CPRINTS(
533 ctx,
534 "validate_payload_regions: hash_type from signature failed");
535 return rv;
536 }
537 rv = intf->hash_init(ctx, hash_type);
538 if (rv != LIBCR51SIGN_SUCCESS)
539 {
540 CPRINTS(ctx, "validate_payload_regions: hash_init failed");
541 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
542 }
543 rv = read_and_hash_update(ctx, intf, data_offset, data_size);
544 if (rv != LIBCR51SIGN_SUCCESS)
545 {
546 CPRINTS(ctx, "validate_signature: hash_update failed");
547 return rv;
548 }
549 if (!intf->hash_final)
550 {
551 CPRINTS(ctx, "validate_signature: missing hash_final");
552 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
553 }
554 rv = intf->hash_final((void*)ctx, dcrypto_digest);
555 if (rv != LIBCR51SIGN_SUCCESS)
556 {
557 CPRINTS(ctx, "validate_signature: hash_final failed (status = %d)",
558 rv);
559 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
560 }
561 rv = get_key_size(scheme, &key_size);
562 if (rv != LIBCR51SIGN_SUCCESS)
563 {
564 return rv;
565 }
566
567 rv = intf->read(ctx, raw_signature_offset, key_size, signature);
568 if (rv != LIBCR51SIGN_SUCCESS)
569 {
570 CPRINTS(
571 ctx,
572 "validate_signature: failed to read signature (status = %d)",
573 rv);
574 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
575 }
576 if (!intf->verify_signature)
577 {
578 CPRINTS(ctx, "validate_signature: missing verify_signature");
579 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
580 }
581 rv = get_hash_digest_size(hash_type, &digest_size);
582 if (rv != LIBCR51SIGN_SUCCESS)
583 {
584 return rv;
585 }
586 rv = intf->verify_signature(ctx, scheme, signature, key_size,
587 dcrypto_digest, digest_size);
588 if (rv != LIBCR51SIGN_SUCCESS)
589 {
590 CPRINTS(ctx,
591 "validate_signature: verification failed (status = %d)",
592 rv);
593 return LIBCR51SIGN_ERROR_INVALID_SIGNATURE;
594 }
595 CPRINTS(ctx, "validate_signature: verification succeeded");
596 return LIBCR51SIGN_SUCCESS;
597 }
598
599 // Sanity checks the image descriptor & validates its signature.
600 // This function does not validate the image_region array or image hash.
601 //
602 //@param[in] ctx context which describes the image and holds opaque private
603 // data for the user of the library
604 //@param[in] intf function pointers which interface to the current system
605 // and environment
606 //@param offset Absolute image descriptor flash offset.
607 //@param relative_offset Image descriptor offset relative to image start.
608 //@param image_size Image size in bytes.
609 //@param descriptor Output pointer to an image_descriptor struct
610
611 static failure_reason validate_descriptor(
612 const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
613 uint32_t offset, uint32_t relative_offset, uint32_t image_size)
614 {
615 uint32_t max_descriptor_size, signed_size, signature_scheme,
616 signature_offset;
617 uint32_t signature_struct_offset, signature_struct_size,
618 hash_struct_size;
619 int rv;
620
621 max_descriptor_size = image_size - relative_offset;
622 if (image_size < relative_offset ||
623 max_descriptor_size < sizeof(struct image_descriptor))
624 {
625 CPRINTS(ctx, "validate_descriptor: invalid arguments");
626 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
627 }
628
629 rv = intf->read(ctx, offset, sizeof(ctx->descriptor),
630 (uint8_t*)&ctx->descriptor);
631 if (rv != LIBCR51SIGN_SUCCESS)
632 {
633 CPRINTS(ctx, "validate_descriptor: failed to read descriptor");
634 return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
635 }
636 if (ctx->descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
637 ctx->descriptor.descriptor_offset != relative_offset ||
638 ctx->descriptor.region_count == 0 ||
639 ctx->descriptor.descriptor_area_size > max_descriptor_size ||
640 ctx->descriptor.image_size != image_size)
641 {
642 CPRINTS(ctx, "validate_descriptor: invalid descriptor");
643 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
644 }
645 if (ctx->descriptor.image_type != IMAGE_DEV &&
646 ctx->descriptor.image_type != IMAGE_PROD &&
647 ctx->descriptor.image_type != IMAGE_BREAKOUT &&
648 ctx->descriptor.image_type != IMAGE_TEST &&
649 ctx->descriptor.image_type != IMAGE_SELF)
650 {
651 CPRINTS(ctx, "validate_descriptor: bad image type");
652 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
653 }
654 // Although the image_descriptor struct supports unauthenticated
655 // images, Haven will not allow it.
656 // Haven only supports SHA256 + RSA2048/RSA3072_PKCS15 currently.
657
658 signature_scheme = ctx->descriptor.signature_scheme;
659
660 rv = is_signature_scheme_supported(signature_scheme);
661 if (rv != LIBCR51SIGN_SUCCESS)
662 {
663 return rv;
664 }
665 rv = is_hash_type_supported(ctx->descriptor.hash_type);
666 if (rv != LIBCR51SIGN_SUCCESS)
667 {
668 CPRINTS(ctx, "validate_payload_regions: invalid hash type");
669 return rv;
670 }
671 if (ctx->descriptor.descriptor_major > MAX_MAJOR_VERSION ||
672 ctx->descriptor.region_count > MAX_REGION_COUNT)
673 {
674 CPRINTS(ctx, "validate_descriptor: unsupported descriptor");
675 return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR;
676 }
677 rv =
678 get_signature_struct_size(signature_scheme, &signature_struct_size);
679 if (rv != LIBCR51SIGN_SUCCESS)
680 {
681 return rv;
682 }
683
684 // Compute the size of the signed portion of the image descriptor.
685 signed_size =
686 sizeof(struct image_descriptor) +
687 ctx->descriptor.region_count * sizeof(struct image_region);
688 rv = get_hash_struct_size(ctx->descriptor.hash_type, &hash_struct_size);
689 if (rv != LIBCR51SIGN_SUCCESS)
690 {
691 return rv;
692 }
693 signed_size += hash_struct_size;
694 if (ctx->descriptor.denylist_size)
695 {
696 signed_size += sizeof(struct denylist);
697 signed_size +=
698 ctx->descriptor.denylist_size * sizeof(struct denylist_record);
699 }
700 if (ctx->descriptor.blob_size)
701 {
702 signed_size += sizeof(struct blob);
703 // Previous additions are guaranteed not to overflow.
704 if (ctx->descriptor.blob_size >
705 ctx->descriptor.descriptor_area_size - signed_size)
706 {
707 CPRINTS(ctx, "validate_descriptor: invalid blob size (0x%x)",
708 ctx->descriptor.blob_size);
709 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
710 }
711 signed_size += ctx->descriptor.blob_size;
712 }
713 if (signature_struct_size >
714 ctx->descriptor.descriptor_area_size - signed_size)
715 {
716 CPRINTS(ctx,
717 "validate_descriptor: invalid descriptor area size "
718 "(expected = 0x%x, actual = 0x%x)",
719 ctx->descriptor.descriptor_area_size,
720 signed_size + signature_struct_size);
721 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
722 }
723 signature_struct_offset = signed_size;
724 // Omit the actual signature.
725 rv = get_signature_field_offset(signature_scheme, &signature_offset);
726 if (rv != LIBCR51SIGN_SUCCESS)
727 {
728 return rv;
729 }
730 signed_size += signature_offset;
731
732 // Lookup key & validate transition.
733 rv = validate_transition(ctx, intf, offset + signature_struct_offset);
734
735 if (rv != LIBCR51SIGN_SUCCESS)
736 {
737 return rv;
738 }
739 return validate_signature(ctx, intf, offset, signed_size,
740 signature_scheme, offset + signed_size);
741 }
742
743 // Scans the external EEPROM for a magic value at "alignment" boundaries.
744 //
745 //@param device Handle to the external EEPROM.
746 //@param magic 8-byte pattern to search for.
747 //@param start_offset Offset to begin searching at.
748 //@param limit Exclusive address (e.g. EEPROM size).
749 //@param alignment Alignment boundaries (POW2) to search on.
750 //@param header_offset Location to place the new header offset.
751 //@return LIBCR51SIGN_SUCCESS (or non-zero on error).
752
753 int scan_for_magic_8(const struct libcr51sign_ctx* ctx,
754 const struct libcr51sign_intf* intf, uint64_t magic,
755 uint32_t start_offset, uint32_t limit,
756 uint32_t alignment, uint32_t* header_offset)
757 {
758 uint64_t read_data;
759 uint32_t offset;
760 int rv;
761
762 if (limit <= start_offset || limit > ctx->end_offset ||
763 limit < sizeof(magic) || !POWER_OF_TWO(alignment))
764 {
765 return LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
766 }
767
768 if (!intf->read)
769 {
770 CPRINTS(ctx, "scan_for_magic_8: missing intf->read");
771 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
772 }
773 // Align start_offset to the next valid boundary.
774 start_offset = ((start_offset - 1) & ~(alignment - 1)) + alignment;
775 for (offset = start_offset; offset < limit - sizeof(magic);
776 offset += alignment)
777 {
778 rv = intf->read((void*)ctx, offset, sizeof(read_data),
779 (uint8_t*)&read_data);
780 if (rv != LIBCR51SIGN_SUCCESS)
781 {
782 return rv;
783 }
784 if (read_data == magic)
785 {
786 if (header_offset)
787 {
788 *header_offset = offset;
789 }
790 return LIBCR51SIGN_SUCCESS;
791 }
792 }
793 // Failed to locate magic.
794 return LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC;
795 }
796
797 // Check whether the signature on the image is valid.
798 // Validates the authenticity of an EEPROM image. Scans for & validates the
799 // signature on the image descriptor. If the descriptor validates, hashes
800 // the rest of the image to verify its integrity.
801 //
802 // @param[in] ctx - context which describes the image and holds opaque
803 // private
804 // data for the user of the library
805 // @param[in] intf - function pointers which interface to the current system
806 // and environment
807 //
808 // @return nonzero on error, zero on success
809
810 failure_reason libcr51sign_validate(const struct libcr51sign_ctx* ctx,
811 struct libcr51sign_intf* intf)
812 {
813 uint32_t image_limit = 0;
814 int rv, rv_first_desc = LIBCR51SIGN_SUCCESS;
815 uint32_t descriptor_offset;
816
817 if (!ctx)
818 {
819 CPRINTS(ctx, "MIssing context");
820 return LIBCR51SIGN_ERROR_INVALID_CONTEXT;
821 }
822 else if (!intf)
823 {
824 CPRINTS(ctx, "Missing interface");
825 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
826 }
827
828 rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, ctx->start_offset,
829 ctx->end_offset, DESCRIPTOR_ALIGNMENT,
830 &descriptor_offset);
831 while (rv == LIBCR51SIGN_SUCCESS)
832 {
833 CPRINTS(ctx, "validate: potential image descriptor found @%x ",
834 descriptor_offset);
835 // Validation is split into 2 functions to minimize
836 // stack usage.
837
838 rv = validate_descriptor(ctx, intf, descriptor_offset,
839 descriptor_offset - ctx->start_offset,
840 ctx->end_offset - ctx->start_offset);
841 if (rv != LIBCR51SIGN_SUCCESS)
842 {
843 CPRINTS(ctx, "validate: validate_descriptor() failed ec%d ",
844 rv);
845 }
846
847 if (rv == LIBCR51SIGN_SUCCESS)
848 {
849 rv = validate_payload_regions(ctx, intf, descriptor_offset);
850 if (rv == LIBCR51SIGN_SUCCESS)
851 {
852 CPRINTS(ctx, "validate: success!");
853 return rv;
854 }
855 CPRINTS(ctx,
856 "validate: validate_payload_regions() failed ec%d ",
857 rv);
858 }
859 // Store the first desc fail reason if any
860 if (rv != LIBCR51SIGN_SUCCESS &&
861 rv_first_desc == LIBCR51SIGN_SUCCESS)
862 rv_first_desc = rv;
863
864 // scan_for_magic_8() will round up to the next aligned boundary.
865 descriptor_offset++;
866 image_limit = ctx->end_offset - ctx->start_offset;
867 rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC,
868 descriptor_offset, image_limit,
869 DESCRIPTOR_ALIGNMENT, &descriptor_offset);
870 }
871 CPRINTS(ctx, "validate: failed to validate image ec%d ", rv);
872 // If desc validation failed for some reason then return that reason
873 if (rv_first_desc != LIBCR51SIGN_SUCCESS)
874 return rv_first_desc;
875 else
876 return rv;
877 }
878
879 // @func to returns the libcr51sign error code as a string
880 // @param[in] ec - Error code
881 // @return error code in string format
882
883 const char* libcr51sign_errorcode_to_string(failure_reason ec)
884 {
885 switch (ec)
886 {
887 case LIBCR51SIGN_SUCCESS:
888 return "Success";
889 case LIBCR51SIGN_ERROR_RUNTIME_FAILURE:
890 return "Runtime Error Failure";
891 case LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR:
892 return "Unsupported descriptor";
893 case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR:
894 return "Invalid descriptor";
895 case LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY:
896 return "Invalid image family";
897 case LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED:
898 return "Image type disallowed";
899 case LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED:
900 return "Dev downgrade disallowed";
901 case LIBCR51SIGN_ERROR_UNTRUSTED_KEY:
902 return "Untrusted key";
903 case LIBCR51SIGN_ERROR_INVALID_SIGNATURE:
904 return "Invalid signature";
905 case LIBCR51SIGN_ERROR_INVALID_HASH:
906 return "Invalid hash";
907 case LIBCR51SIGN_ERROR_INVALID_HASH_TYPE:
908 return "Invalid hash type";
909 case LIBCR51SIGN_ERROR_INVALID_ARGUMENT:
910 return "Invalid Argument";
911 case LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC:
912 return "Failed to locate descriptor";
913 case LIBCR51SIGN_ERROR_INVALID_CONTEXT:
914 return "Invalid context";
915 case LIBCR51SIGN_ERROR_INVALID_INTERFACE:
916 return "Invalid interface";
917 case LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME:
918 return "Invalid signature scheme";
919 default:
920 return "Unknown error";
921 }
922 }
923
924#ifdef __cplusplus
925} // extern "C"
926#endif