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