15acaca2fSWilliam A. Kennington III /*
25acaca2fSWilliam A. Kennington III  * Copyright 2021 Google LLC
35acaca2fSWilliam A. Kennington III  *
45acaca2fSWilliam A. Kennington III  * Licensed under the Apache License, Version 2.0 (the "License");
55acaca2fSWilliam A. Kennington III  * you may not use this file except in compliance with the License.
65acaca2fSWilliam A. Kennington III  * You may obtain a copy of the License at
75acaca2fSWilliam A. Kennington III  *
85acaca2fSWilliam A. Kennington III  *      http://www.apache.org/licenses/LICENSE-2.0
95acaca2fSWilliam A. Kennington III  *
105acaca2fSWilliam A. Kennington III  * Unless required by applicable law or agreed to in writing, software
115acaca2fSWilliam A. Kennington III  * distributed under the License is distributed on an "AS IS" BASIS,
125acaca2fSWilliam A. Kennington III  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135acaca2fSWilliam A. Kennington III  * See the License for the specific language governing permissions and
145acaca2fSWilliam A. Kennington III  * limitations under the License.
155acaca2fSWilliam A. Kennington III  */
165acaca2fSWilliam A. Kennington III #include <assert.h>
175acaca2fSWilliam A. Kennington III #include <libcr51sign/libcr51sign.h>
185acaca2fSWilliam A. Kennington III #include <stdio.h>
195acaca2fSWilliam A. Kennington III #include <stdlib.h>
205acaca2fSWilliam A. Kennington III #include <string.h>
215acaca2fSWilliam A. Kennington III 
225acaca2fSWilliam A. Kennington III #ifdef __cplusplus
235acaca2fSWilliam A. Kennington III extern "C"
245acaca2fSWilliam A. Kennington III {
255acaca2fSWilliam A. Kennington III #endif
265acaca2fSWilliam A. Kennington III 
275acaca2fSWilliam A. Kennington III #ifndef USER_PRINT
28deb5501aSWilliam A. Kennington III #define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__)
295acaca2fSWilliam A. Kennington III #endif
305acaca2fSWilliam A. Kennington III 
315acaca2fSWilliam A. Kennington III #define MEMBER_SIZE(type, field) sizeof(((type*)0)->field)
325acaca2fSWilliam A. Kennington III 
335acaca2fSWilliam A. Kennington III // True of x is a power of two
345acaca2fSWilliam A. Kennington III #define POWER_OF_TWO(x) ((x) && !((x) & ((x)-1)))
355acaca2fSWilliam A. Kennington III 
365acaca2fSWilliam A. Kennington III // Maximum version supported. Major revisions are not backwards compatible.
375acaca2fSWilliam A. Kennington III #define MAX_MAJOR_VERSION 1
385acaca2fSWilliam A. Kennington III 
395acaca2fSWilliam A. Kennington III // Descriptor alignment on the external EEPROM.
405acaca2fSWilliam A. Kennington III #define DESCRIPTOR_ALIGNMENT (64 * 1024)
415acaca2fSWilliam A. Kennington III 
425acaca2fSWilliam A. Kennington III // SPS EEPROM sector size is 4KiB, since this is the smallest erasable size.
435acaca2fSWilliam A. Kennington III #define IMAGE_REGION_ALIGNMENT 4096
445acaca2fSWilliam A. Kennington III 
455acaca2fSWilliam A. Kennington III #define MAX_READ_SIZE 1024
465acaca2fSWilliam A. Kennington III 
475acaca2fSWilliam A. Kennington III #ifndef ARRAY_SIZE
485acaca2fSWilliam A. Kennington III #define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0]))
495acaca2fSWilliam A. Kennington III #endif
505acaca2fSWilliam A. Kennington III 
515acaca2fSWilliam A. Kennington III // Values of SIGNATURE_OFFSET shuold be same for all sig types (2048,3072,4096)
525acaca2fSWilliam A. Kennington III #define SIGNATURE_OFFSET offsetof(struct signature_rsa3072_pkcs15, modulus)
535acaca2fSWilliam A. Kennington III 
545acaca2fSWilliam A. Kennington III #ifndef BUILD_ASSERT
555acaca2fSWilliam A. Kennington III #define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
565acaca2fSWilliam A. Kennington III #endif
575acaca2fSWilliam A. Kennington III 
585acaca2fSWilliam A. Kennington III     typedef enum libcr51sign_validation_failure_reason failure_reason;
595acaca2fSWilliam A. Kennington III 
605acaca2fSWilliam A. Kennington III     // Returns the bytes size of keys used in the given signature_scheme.
615acaca2fSWilliam A. Kennington III     // Return error if signature_scheme is invalid.
625acaca2fSWilliam A. Kennington III     //
635acaca2fSWilliam A. Kennington III     static failure_reason get_key_size(enum signature_scheme signature_scheme,
645acaca2fSWilliam A. Kennington III                                        uint16_t* key_size)
655acaca2fSWilliam A. Kennington III     {
665acaca2fSWilliam A. Kennington III         switch (signature_scheme)
675acaca2fSWilliam A. Kennington III         {
685acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
695acaca2fSWilliam A. Kennington III                 *key_size = 256;
705acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
715acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
725acaca2fSWilliam A. Kennington III                 *key_size = 384;
735acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
745acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
755acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
765acaca2fSWilliam A. Kennington III                 *key_size = 512;
775acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
785acaca2fSWilliam A. Kennington III             default:
795acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
805acaca2fSWilliam A. Kennington III         }
815acaca2fSWilliam A. Kennington III     }
825acaca2fSWilliam A. Kennington III 
835acaca2fSWilliam A. Kennington III     // Returns the hash_type for a given signature scheme
845acaca2fSWilliam A. Kennington III     // Returns error if scheme is invalid.
855acaca2fSWilliam A. Kennington III     failure_reason get_hash_type_from_signature(enum signature_scheme scheme,
865acaca2fSWilliam A. Kennington III                                                 enum hash_type* type)
875acaca2fSWilliam A. Kennington III     {
885acaca2fSWilliam A. Kennington III         switch (scheme)
895acaca2fSWilliam A. Kennington III         {
905acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
915acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
925acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
935acaca2fSWilliam A. Kennington III                 *type = HASH_SHA2_256;
945acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
955acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
965acaca2fSWilliam A. Kennington III                 *type = HASH_SHA2_512;
975acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
985acaca2fSWilliam A. Kennington III             default:
995acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
1005acaca2fSWilliam A. Kennington III         }
1015acaca2fSWilliam A. Kennington III     }
1025acaca2fSWilliam A. Kennington III 
1035acaca2fSWilliam A. Kennington III     // Check if the given hash_type is supported.
1045acaca2fSWilliam A. Kennington III     // Returns error if hash_type is not supported.
1055acaca2fSWilliam A. Kennington III     static failure_reason is_hash_type_supported(enum hash_type type)
1065acaca2fSWilliam A. Kennington III     {
1075acaca2fSWilliam A. Kennington III         switch (type)
1085acaca2fSWilliam A. Kennington III         {
1095acaca2fSWilliam A. Kennington III             case HASH_SHA2_256:
1105acaca2fSWilliam A. Kennington III             case HASH_SHA2_512:
1115acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
1125acaca2fSWilliam A. Kennington III             default:
1135acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
1145acaca2fSWilliam A. Kennington III         }
1155acaca2fSWilliam A. Kennington III     }
1165acaca2fSWilliam A. Kennington III 
1175acaca2fSWilliam A. Kennington III     // Determines digest size for a given hash_type.
1185acaca2fSWilliam A. Kennington III     // Returns error if hash_type is not supported.
1195acaca2fSWilliam A. Kennington III     static failure_reason get_hash_digest_size(enum hash_type type,
1205acaca2fSWilliam A. Kennington III                                                uint32_t* size)
1215acaca2fSWilliam A. Kennington III     {
1225acaca2fSWilliam A. Kennington III         switch (type)
1235acaca2fSWilliam A. Kennington III         {
1245acaca2fSWilliam A. Kennington III             case HASH_SHA2_256:
1255acaca2fSWilliam A. Kennington III                 *size = LIBCR51SIGN_SHA256_DIGEST_SIZE;
1265acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
1275acaca2fSWilliam A. Kennington III             case HASH_SHA2_512:
1285acaca2fSWilliam A. Kennington III                 *size = LIBCR51SIGN_SHA512_DIGEST_SIZE;
1295acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
1305acaca2fSWilliam A. Kennington III             default:
1315acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
1325acaca2fSWilliam A. Kennington III         }
1335acaca2fSWilliam A. Kennington III     }
1345acaca2fSWilliam A. Kennington III 
1355acaca2fSWilliam A. Kennington III     // Determines hash struct size for a given hash_type.
1365acaca2fSWilliam A. Kennington III     // Returns error if hash_type is not supported.
1375acaca2fSWilliam A. Kennington III     static failure_reason get_hash_struct_size(enum hash_type type,
1385acaca2fSWilliam A. Kennington III                                                uint32_t* size)
1395acaca2fSWilliam A. Kennington III     {
1405acaca2fSWilliam A. Kennington III         switch (type)
1415acaca2fSWilliam A. Kennington III         {
1425acaca2fSWilliam A. Kennington III             case HASH_SHA2_256:
1435acaca2fSWilliam A. Kennington III                 *size = sizeof(struct hash_sha256);
1445acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
1455acaca2fSWilliam A. Kennington III             case HASH_SHA2_512:
1465acaca2fSWilliam A. Kennington III                 *size = sizeof(struct hash_sha256);
1475acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
1485acaca2fSWilliam A. Kennington III             default:
1495acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
1505acaca2fSWilliam A. Kennington III         }
1515acaca2fSWilliam A. Kennington III     }
1525acaca2fSWilliam A. Kennington III 
1535acaca2fSWilliam A. Kennington III     // Checks that:
1545acaca2fSWilliam A. Kennington III     //  - The signing key is trusted
1555acaca2fSWilliam A. Kennington III     //  - The target version is not denylisted
1565acaca2fSWilliam A. Kennington III     // If validating a staged update, also checks that:
1575acaca2fSWilliam A. Kennington III     //  - The target image family matches the current image family
1585acaca2fSWilliam A. Kennington III     //  - The image type transition is legal (i.e. dev -> *|| prod -> prod) or
1595acaca2fSWilliam A. Kennington III     //    alternatively that the hardware ID is allowlisted
1605acaca2fSWilliam A. Kennington III     // Assuming the caller has performed following:
1615acaca2fSWilliam A. Kennington III     // board_get_base_key_index();
1625acaca2fSWilliam A. Kennington III     // board_get_key_array
1635acaca2fSWilliam A. Kennington III     // Possible return codes:
1645acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_SUCCESS = 0,
1655acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
1665acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
1675acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
1685acaca2fSWilliam A. Kennington III     // LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
1695acaca2fSWilliam A. Kennington III 
1705acaca2fSWilliam A. Kennington III     static failure_reason
1715acaca2fSWilliam A. Kennington III         validate_transition(const struct libcr51sign_ctx* ctx,
1725acaca2fSWilliam A. Kennington III                             const struct libcr51sign_intf* intf,
1735acaca2fSWilliam A. Kennington III                             uint32_t signature_struct_offset)
1745acaca2fSWilliam A. Kennington III     {
1755acaca2fSWilliam A. Kennington III         BUILD_ASSERT((offsetof(struct signature_rsa2048_pkcs15, modulus) ==
1765acaca2fSWilliam A. Kennington III                           SIGNATURE_OFFSET &&
1775acaca2fSWilliam A. Kennington III                       offsetof(struct signature_rsa3072_pkcs15, modulus) ==
1785acaca2fSWilliam A. Kennington III                           SIGNATURE_OFFSET &&
1795acaca2fSWilliam A. Kennington III                       offsetof(struct signature_rsa4096_pkcs15, modulus) ==
1805acaca2fSWilliam A. Kennington III                           SIGNATURE_OFFSET));
1815acaca2fSWilliam A. Kennington III 
1825acaca2fSWilliam A. Kennington III         // Read up to the modulus.
1835acaca2fSWilliam A. Kennington III         enum
1845acaca2fSWilliam A. Kennington III         {
1855acaca2fSWilliam A. Kennington III             read_len = SIGNATURE_OFFSET
1865acaca2fSWilliam A. Kennington III         };
1875acaca2fSWilliam A. Kennington III         uint8_t buffer[read_len];
1885acaca2fSWilliam A. Kennington III         int rv;
1895acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, signature_struct_offset, read_len, buffer);
1905acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
1915acaca2fSWilliam A. Kennington III         {
1925acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
193af46bea6SWilliam A. Kennington III                     "validate_transition: failed to read signature struct\n");
1945acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
1955acaca2fSWilliam A. Kennington III         }
19612e6ad0dSWilliam A. Kennington III         if (*(uint32_t*)buffer != SIGNATURE_MAGIC)
1975acaca2fSWilliam A. Kennington III         {
198af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: bad signature magic\n");
1995acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
2005acaca2fSWilliam A. Kennington III         }
2015acaca2fSWilliam A. Kennington III 
2025acaca2fSWilliam A. Kennington III         if (ctx->descriptor.image_family != ctx->current_image_family &&
2035acaca2fSWilliam A. Kennington III             ctx->descriptor.image_family != IMAGE_FAMILY_ALL &&
2045acaca2fSWilliam A. Kennington III             ctx->current_image_family != IMAGE_FAMILY_ALL)
2055acaca2fSWilliam A. Kennington III         {
206af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: invalid image family\n");
2075acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY;
2085acaca2fSWilliam A. Kennington III         }
2095acaca2fSWilliam A. Kennington III 
210d2bcdd5cSWilly Tu         if (intf->is_production_mode == NULL)
2115acaca2fSWilliam A. Kennington III         {
212af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: missing is_production_mode\n");
2135acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
2145acaca2fSWilliam A. Kennington III         }
2155acaca2fSWilliam A. Kennington III         if (intf->is_production_mode() &&
2165acaca2fSWilliam A. Kennington III             (ctx->descriptor.image_type == IMAGE_DEV))
2175acaca2fSWilliam A. Kennington III         {
218af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_transition: checking exemption allowlist\n");
2195acaca2fSWilliam A. Kennington III 
220d2bcdd5cSWilly Tu             // If function is NULL or if the function call return false, return
221d2bcdd5cSWilly Tu             // error
222d2bcdd5cSWilly Tu             if (intf->prod_to_dev_downgrade_allowed == NULL ||
223d2bcdd5cSWilly Tu                 !intf->prod_to_dev_downgrade_allowed())
2245acaca2fSWilliam A. Kennington III             {
225af46bea6SWilliam A. Kennington III                 CPRINTS(ctx, "validate_transition: illegal image type\n");
2265acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED;
2275acaca2fSWilliam A. Kennington III             }
2285acaca2fSWilliam A. Kennington III         }
2295acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
2305acaca2fSWilliam A. Kennington III     }
2315acaca2fSWilliam A. Kennington III 
2325acaca2fSWilliam A. Kennington III     // If caller had provided read_and_hash_update call that, otherwise call
2335acaca2fSWilliam A. Kennington III     // read and then update.
2345acaca2fSWilliam A. Kennington III 
2355acaca2fSWilliam A. Kennington III     static failure_reason
2365acaca2fSWilliam A. Kennington III         read_and_hash_update(const struct libcr51sign_ctx* ctx,
2375acaca2fSWilliam A. Kennington III                              const struct libcr51sign_intf* intf,
2385acaca2fSWilliam A. Kennington III                              uint32_t offset, uint32_t size)
2395acaca2fSWilliam A. Kennington III     {
2405acaca2fSWilliam A. Kennington III         uint8_t read_buffer[MAX_READ_SIZE];
2415acaca2fSWilliam A. Kennington III         int rv;
2425acaca2fSWilliam A. Kennington III         int read_size;
2435acaca2fSWilliam A. Kennington III 
2445acaca2fSWilliam A. Kennington III         if (intf->read_and_hash_update)
2455acaca2fSWilliam A. Kennington III         {
2465acaca2fSWilliam A. Kennington III             rv = intf->read_and_hash_update((void*)ctx, offset, size);
2475acaca2fSWilliam A. Kennington III         }
2485acaca2fSWilliam A. Kennington III         else
2495acaca2fSWilliam A. Kennington III         {
2505acaca2fSWilliam A. Kennington III             if (!intf->hash_update)
2515acaca2fSWilliam A. Kennington III             {
252af46bea6SWilliam A. Kennington III                 CPRINTS(ctx, "read_and_hash_update: missing hash_update\n");
2535acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
2545acaca2fSWilliam A. Kennington III             }
2555acaca2fSWilliam A. Kennington III             do
2565acaca2fSWilliam A. Kennington III             {
2575acaca2fSWilliam A. Kennington III                 read_size = size < MAX_READ_SIZE ? size : MAX_READ_SIZE;
2585acaca2fSWilliam A. Kennington III                 rv = intf->read((void*)ctx, offset, read_size, read_buffer);
2595acaca2fSWilliam A. Kennington III                 if (rv != LIBCR51SIGN_SUCCESS)
2605acaca2fSWilliam A. Kennington III                 {
2615acaca2fSWilliam A. Kennington III                     return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
2625acaca2fSWilliam A. Kennington III                 }
2635acaca2fSWilliam A. Kennington III                 rv = intf->hash_update((void*)ctx, read_buffer, read_size);
2645acaca2fSWilliam A. Kennington III                 if (rv != LIBCR51SIGN_SUCCESS)
2655acaca2fSWilliam A. Kennington III                 {
2665acaca2fSWilliam A. Kennington III                     return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
2675acaca2fSWilliam A. Kennington III                 }
2685acaca2fSWilliam A. Kennington III                 offset += read_size;
2695acaca2fSWilliam A. Kennington III                 size -= read_size;
2705acaca2fSWilliam A. Kennington III             } while (size > 0);
2715acaca2fSWilliam A. Kennington III         }
2725acaca2fSWilliam A. Kennington III         return rv;
2735acaca2fSWilliam A. Kennington III     }
2745acaca2fSWilliam A. Kennington III 
2755acaca2fSWilliam A. Kennington III     // Validates the image_region array, namely that:
2765acaca2fSWilliam A. Kennington III     //  - The regions are aligned, contiguous & exhaustive
2775acaca2fSWilliam A. Kennington III     //  - That the image descriptor resides in a static region
2785acaca2fSWilliam A. Kennington III     //
2795acaca2fSWilliam A. Kennington III     // If the array is consistent, proceeds to hash the static regions and
2805acaca2fSWilliam A. Kennington III     // validates the hash. d_offset is the absolute image descriptor offset
2815acaca2fSWilliam A. Kennington III 
2825acaca2fSWilliam A. Kennington III     static failure_reason validate_payload_regions(
2835acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
2845acaca2fSWilliam A. Kennington III         uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
2855acaca2fSWilliam A. Kennington III     {
2865acaca2fSWilliam A. Kennington III         // Allocate buffer to accomodate largest supported hash-type(SHA512)
2875acaca2fSWilliam A. Kennington III         uint8_t magic_and_digest[MEMBER_SIZE(struct hash_sha512, hash_magic) +
2885acaca2fSWilliam A. Kennington III                                  LIBCR51SIGN_SHA512_DIGEST_SIZE];
2895acaca2fSWilliam A. Kennington III         uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
2905acaca2fSWilliam A. Kennington III         uint32_t byte_count, region_count, image_size, hash_offset, digest_size;
291deb5501aSWilliam A. Kennington III         uint32_t i;
2925acaca2fSWilliam A. Kennington III         uint8_t d_region_num = 0;
293deb5501aSWilliam A. Kennington III         int rv;
294*2be45238SPatrick Williams         const struct image_region* region;
2955acaca2fSWilliam A. Kennington III 
2965acaca2fSWilliam A. Kennington III         if (image_regions == NULL)
2975acaca2fSWilliam A. Kennington III         {
298af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "Missing image region input\n");
2995acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_REGION_INPUT;
3005acaca2fSWilliam A. Kennington III         }
3015acaca2fSWilliam A. Kennington III 
3025acaca2fSWilliam A. Kennington III         BUILD_ASSERT((MEMBER_SIZE(struct hash_sha256, hash_magic) ==
3035acaca2fSWilliam A. Kennington III                       MEMBER_SIZE(struct hash_sha512, hash_magic)));
3045acaca2fSWilliam A. Kennington III         image_size = ctx->descriptor.image_size;
3055acaca2fSWilliam A. Kennington III         region_count = ctx->descriptor.region_count;
3065acaca2fSWilliam A. Kennington III         hash_offset = d_offset + sizeof(struct image_descriptor) +
3075acaca2fSWilliam A. Kennington III                       region_count * sizeof(struct image_region);
3085acaca2fSWilliam A. Kennington III         // Read the image_region array.
3095acaca2fSWilliam A. Kennington III 
3105acaca2fSWilliam A. Kennington III         if (region_count > ARRAY_SIZE(image_regions->image_regions))
3115acaca2fSWilliam A. Kennington III         {
3125acaca2fSWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: "
3135acaca2fSWilliam A. Kennington III                          "ctx->descriptor.region_count is greater "
314af46bea6SWilliam A. Kennington III                          "than LIBCR51SIGN_MAX_REGION_COUNT\n");
3155acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_REGION_SIZE;
3165acaca2fSWilliam A. Kennington III         }
3175acaca2fSWilliam A. Kennington III 
318deb5501aSWilliam A. Kennington III         rv = intf->read(ctx, d_offset + sizeof(struct image_descriptor),
3195acaca2fSWilliam A. Kennington III                         region_count * sizeof(struct image_region),
3205acaca2fSWilliam A. Kennington III                         (uint8_t*)&image_regions->image_regions);
3215acaca2fSWilliam A. Kennington III 
3225acaca2fSWilliam A. Kennington III         image_regions->region_count = region_count;
3235acaca2fSWilliam A. Kennington III 
3245acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
3255acaca2fSWilliam A. Kennington III         {
3265acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
327af46bea6SWilliam A. Kennington III                     "validate_payload_regions: failed to read region array\n");
3285acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
3295acaca2fSWilliam A. Kennington III         }
3305acaca2fSWilliam A. Kennington III 
3315acaca2fSWilliam A. Kennington III         // Validate that the regions are contiguous & exhaustive.
3325acaca2fSWilliam A. Kennington III         for (i = 0, byte_count = 0; i < region_count; i++)
3335acaca2fSWilliam A. Kennington III         {
3345acaca2fSWilliam A. Kennington III             region = image_regions->image_regions + i;
3355acaca2fSWilliam A. Kennington III 
3365acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
337af46bea6SWilliam A. Kennington III                     "validate_payload_regions: region #%d \"%s\" (%x - %x)\n",
338af46bea6SWilliam A. Kennington III                     i, (const char*)region->region_name, region->region_offset,
3395acaca2fSWilliam A. Kennington III                     region->region_offset + region->region_size);
3405acaca2fSWilliam A. Kennington III             if ((region->region_offset % IMAGE_REGION_ALIGNMENT) != 0 ||
3415acaca2fSWilliam A. Kennington III                 (region->region_size % IMAGE_REGION_ALIGNMENT) != 0)
3425acaca2fSWilliam A. Kennington III             {
343af46bea6SWilliam A. Kennington III                 CPRINTS(ctx, "validate_payload_regions: regions must be sector "
344af46bea6SWilliam A. Kennington III                              "aligned\n");
3455acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3465acaca2fSWilliam A. Kennington III             }
3475acaca2fSWilliam A. Kennington III             if (region->region_offset != byte_count ||
3485acaca2fSWilliam A. Kennington III                 region->region_size > image_size - byte_count)
3495acaca2fSWilliam A. Kennington III             {
350af46bea6SWilliam A. Kennington III                 CPRINTS(ctx,
351af46bea6SWilliam A. Kennington III                         "validate_payload_regions: invalid region array\n");
3525acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3535acaca2fSWilliam A. Kennington III             }
3545acaca2fSWilliam A. Kennington III             byte_count += region->region_size;
3555acaca2fSWilliam A. Kennington III             // The image descriptor must be part of a static region.
3565acaca2fSWilliam A. Kennington III             if (d_offset >= region->region_offset && d_offset < byte_count)
3575acaca2fSWilliam A. Kennington III             {
3585acaca2fSWilliam A. Kennington III                 d_region_num = i;
3595acaca2fSWilliam A. Kennington III                 CPRINTS(
3605acaca2fSWilliam A. Kennington III                     ctx,
361af46bea6SWilliam A. Kennington III                     "validate_payload_regions: image descriptor in region %d\n",
3625acaca2fSWilliam A. Kennington III                     i);
3635acaca2fSWilliam A. Kennington III                 // The descriptor can't span regions.
3645acaca2fSWilliam A. Kennington III                 if (ctx->descriptor.descriptor_area_size > byte_count ||
3655acaca2fSWilliam A. Kennington III                     !(region->region_attributes & IMAGE_REGION_STATIC))
3665acaca2fSWilliam A. Kennington III                 {
3675acaca2fSWilliam A. Kennington III                     CPRINTS(
3685acaca2fSWilliam A. Kennington III                         ctx,
3695acaca2fSWilliam A. Kennington III                         "validate_payload_regions: descriptor must reside in "
370af46bea6SWilliam A. Kennington III                         "static region\n");
3715acaca2fSWilliam A. Kennington III                     return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3725acaca2fSWilliam A. Kennington III                 }
3735acaca2fSWilliam A. Kennington III             }
3745acaca2fSWilliam A. Kennington III         }
3755acaca2fSWilliam A. Kennington III         if (byte_count != image_size)
3765acaca2fSWilliam A. Kennington III         {
377af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: invalid image size\n");
3785acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3795acaca2fSWilliam A. Kennington III         }
3805acaca2fSWilliam A. Kennington III 
3815acaca2fSWilliam A. Kennington III         rv = get_hash_digest_size(ctx->descriptor.hash_type, &digest_size);
3825acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
3835acaca2fSWilliam A. Kennington III         {
3845acaca2fSWilliam A. Kennington III             return rv;
3855acaca2fSWilliam A. Kennington III         }
3865acaca2fSWilliam A. Kennington III 
3875acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, hash_offset,
3885acaca2fSWilliam A. Kennington III                         MEMBER_SIZE(struct hash_sha256, hash_magic) +
3895acaca2fSWilliam A. Kennington III                             digest_size,
3905acaca2fSWilliam A. Kennington III                         magic_and_digest);
3915acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
3925acaca2fSWilliam A. Kennington III         {
393af46bea6SWilliam A. Kennington III             CPRINTS(
394af46bea6SWilliam A. Kennington III                 ctx,
395af46bea6SWilliam A. Kennington III                 "validate_payload_regions: failed to read hash from flash\n");
3965acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
3975acaca2fSWilliam A. Kennington III         }
3985acaca2fSWilliam A. Kennington III         if (*(uint32_t*)magic_and_digest != HASH_MAGIC)
3995acaca2fSWilliam A. Kennington III         {
400af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: bad hash magic\n");
4015acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
4025acaca2fSWilliam A. Kennington III         }
4035acaca2fSWilliam A. Kennington III         rv = intf->hash_init(ctx, ctx->descriptor.hash_type);
4045acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
4055acaca2fSWilliam A. Kennington III         {
406af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: hash_init failed\n");
4075acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
4085acaca2fSWilliam A. Kennington III         }
4095acaca2fSWilliam A. Kennington III         for (i = 0; i < region_count; i++)
4105acaca2fSWilliam A. Kennington III         {
4115acaca2fSWilliam A. Kennington III             uint32_t hash_start, hash_size;
4125acaca2fSWilliam A. Kennington III             region = image_regions->image_regions + i;
4135acaca2fSWilliam A. Kennington III 
4145acaca2fSWilliam A. Kennington III             if (!(region->region_attributes & IMAGE_REGION_STATIC))
4155acaca2fSWilliam A. Kennington III             {
4165acaca2fSWilliam A. Kennington III                 continue;
4175acaca2fSWilliam A. Kennington III             }
4185acaca2fSWilliam A. Kennington III             hash_start = region->region_offset;
4195acaca2fSWilliam A. Kennington III             hash_size = region->region_size;
4205acaca2fSWilliam A. Kennington III 
4215acaca2fSWilliam A. Kennington III             // Skip the descriptor.
4225acaca2fSWilliam A. Kennington III             do
4235acaca2fSWilliam A. Kennington III             {
4245acaca2fSWilliam A. Kennington III                 if (i == d_region_num)
4255acaca2fSWilliam A. Kennington III                 {
4265acaca2fSWilliam A. Kennington III                     hash_size = d_offset - hash_start;
4275acaca2fSWilliam A. Kennington III                 }
4285acaca2fSWilliam A. Kennington III 
4295acaca2fSWilliam A. Kennington III                 if (!hash_size)
4305acaca2fSWilliam A. Kennington III                 {
4315acaca2fSWilliam A. Kennington III                     hash_start += ctx->descriptor.descriptor_area_size;
4325acaca2fSWilliam A. Kennington III                     hash_size = (region->region_offset + region->region_size -
4335acaca2fSWilliam A. Kennington III                                  hash_start);
4345acaca2fSWilliam A. Kennington III                 }
435af46bea6SWilliam A. Kennington III                 CPRINTS("validate_payload_regions: hashing %s (%x - %x)\n",
436deb5501aSWilliam A. Kennington III                         (const char*)region->region_name, hash_start,
4375acaca2fSWilliam A. Kennington III                         hash_start + hash_size);
4385acaca2fSWilliam A. Kennington III                 // Read the image_region array.
4395acaca2fSWilliam A. Kennington III                 rv = read_and_hash_update(ctx, intf, hash_start, hash_size);
4405acaca2fSWilliam A. Kennington III                 if (rv != LIBCR51SIGN_SUCCESS)
4415acaca2fSWilliam A. Kennington III                 {
4425acaca2fSWilliam A. Kennington III                     return rv;
4435acaca2fSWilliam A. Kennington III                 }
4445acaca2fSWilliam A. Kennington III                 hash_start += hash_size;
4455acaca2fSWilliam A. Kennington III             } while (hash_start != region->region_offset + region->region_size);
4465acaca2fSWilliam A. Kennington III         }
4475acaca2fSWilliam A. Kennington III         rv = intf->hash_final((void*)ctx, (uint8_t*)dcrypto_digest);
4485acaca2fSWilliam A. Kennington III 
4495acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
4505acaca2fSWilliam A. Kennington III         {
4515acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
4525acaca2fSWilliam A. Kennington III         }
4535acaca2fSWilliam A. Kennington III 
4545acaca2fSWilliam A. Kennington III         if (memcmp(magic_and_digest +
4555acaca2fSWilliam A. Kennington III                        MEMBER_SIZE(struct hash_sha256, hash_magic),
4565acaca2fSWilliam A. Kennington III                    dcrypto_digest, digest_size))
4575acaca2fSWilliam A. Kennington III         {
458af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: invalid hash\n");
4595acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_HASH;
4605acaca2fSWilliam A. Kennington III         }
4615acaca2fSWilliam A. Kennington III         // Image is valid.
4625acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
4635acaca2fSWilliam A. Kennington III     }
4645acaca2fSWilliam A. Kennington III 
4655acaca2fSWilliam A. Kennington III     // Create empty image_regions to pass to validate_payload_regions
4665acaca2fSWilliam A. Kennington III     // Support validate_payload_regions_helper to remove image_regions as a
4675acaca2fSWilliam A. Kennington III     // required input.
4685acaca2fSWilliam A. Kennington III 
4695acaca2fSWilliam A. Kennington III     static failure_reason
4705acaca2fSWilliam A. Kennington III         allocate_and_validate_payload_regions(const struct libcr51sign_ctx* ctx,
4715acaca2fSWilliam A. Kennington III                                               struct libcr51sign_intf* intf,
4725acaca2fSWilliam A. Kennington III                                               uint32_t d_offset)
4735acaca2fSWilliam A. Kennington III     {
4745acaca2fSWilliam A. Kennington III         struct libcr51sign_validated_regions image_regions;
4755acaca2fSWilliam A. Kennington III         return validate_payload_regions(ctx, intf, d_offset, &image_regions);
4765acaca2fSWilliam A. Kennington III     }
4775acaca2fSWilliam A. Kennington III 
4785acaca2fSWilliam A. Kennington III     // Wrapper around validate_payload_regions to allow nullptr for
4795acaca2fSWilliam A. Kennington III     // image_regions. Calls allocate_and_validate_payload_regions when
4805acaca2fSWilliam A. Kennington III     // image_regions is nullptr to create placer holder image_regions.
4815acaca2fSWilliam A. Kennington III 
4825acaca2fSWilliam A. Kennington III     static failure_reason validate_payload_regions_helper(
4835acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
4845acaca2fSWilliam A. Kennington III         uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
4855acaca2fSWilliam A. Kennington III     {
4865acaca2fSWilliam A. Kennington III         if (image_regions)
4875acaca2fSWilliam A. Kennington III         {
4885acaca2fSWilliam A. Kennington III             return validate_payload_regions(ctx, intf, d_offset, image_regions);
4895acaca2fSWilliam A. Kennington III         }
4905acaca2fSWilliam A. Kennington III 
4915acaca2fSWilliam A. Kennington III         return allocate_and_validate_payload_regions(ctx, intf, d_offset);
4925acaca2fSWilliam A. Kennington III     }
4935acaca2fSWilliam A. Kennington III 
4945acaca2fSWilliam A. Kennington III     // Check if the given signature_scheme is supported.
4955acaca2fSWilliam A. Kennington III     // Returns nonzero on error, zero on success
4965acaca2fSWilliam A. Kennington III 
4975acaca2fSWilliam A. Kennington III     static failure_reason
4985acaca2fSWilliam A. Kennington III         is_signature_scheme_supported(enum signature_scheme scheme)
4995acaca2fSWilliam A. Kennington III     {
5005acaca2fSWilliam A. Kennington III         switch (scheme)
5015acaca2fSWilliam A. Kennington III         {
5025acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
5035acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
5045acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
5055acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
5065acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
5075acaca2fSWilliam A. Kennington III             default:
5085acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
5095acaca2fSWilliam A. Kennington III         }
5105acaca2fSWilliam A. Kennington III     }
5115acaca2fSWilliam A. Kennington III 
5125acaca2fSWilliam A. Kennington III     // Returns size of signature struct size in |size|
5135acaca2fSWilliam A. Kennington III     // Returns nonzero on error, zero on success
5145acaca2fSWilliam A. Kennington III 
5155acaca2fSWilliam A. Kennington III     static failure_reason
5165acaca2fSWilliam A. Kennington III         get_signature_struct_size(enum signature_scheme scheme, uint32_t* size)
5175acaca2fSWilliam A. Kennington III     {
5185acaca2fSWilliam A. Kennington III         switch (scheme)
5195acaca2fSWilliam A. Kennington III         {
5205acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
5215acaca2fSWilliam A. Kennington III                 *size = sizeof(struct signature_rsa2048_pkcs15);
5225acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
5235acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
5245acaca2fSWilliam A. Kennington III                 *size = sizeof(struct signature_rsa3072_pkcs15);
5255acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
5265acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
5275acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
5285acaca2fSWilliam A. Kennington III                 *size = sizeof(struct signature_rsa4096_pkcs15);
5295acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
5305acaca2fSWilliam A. Kennington III             default:
5315acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
5325acaca2fSWilliam A. Kennington III         }
5335acaca2fSWilliam A. Kennington III     }
5345acaca2fSWilliam A. Kennington III 
5355acaca2fSWilliam A. Kennington III     static failure_reason
5365acaca2fSWilliam A. Kennington III         get_signature_field_offset(enum signature_scheme scheme,
5375acaca2fSWilliam A. Kennington III                                    uint32_t* offset)
5385acaca2fSWilliam A. Kennington III     {
5395acaca2fSWilliam A. Kennington III         switch (scheme)
5405acaca2fSWilliam A. Kennington III         {
5415acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA2048_PKCS15:
5425acaca2fSWilliam A. Kennington III                 *offset = offsetof(struct signature_rsa2048_pkcs15, signature);
5435acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
5445acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA3072_PKCS15:
5455acaca2fSWilliam A. Kennington III                 *offset = offsetof(struct signature_rsa3072_pkcs15, signature);
5465acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
5475acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15:
5485acaca2fSWilliam A. Kennington III             case SIGNATURE_RSA4096_PKCS15_SHA512:
5495acaca2fSWilliam A. Kennington III                 *offset = offsetof(struct signature_rsa4096_pkcs15, signature);
5505acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
5515acaca2fSWilliam A. Kennington III             default:
5525acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
5535acaca2fSWilliam A. Kennington III         }
5545acaca2fSWilliam A. Kennington III     }
5555acaca2fSWilliam A. Kennington III 
5565acaca2fSWilliam A. Kennington III     // Validates the signature (of type scheme) read from "device" at
5575acaca2fSWilliam A. Kennington III     //"raw_signature_offset" with "public_key" over a SHA256/SHA512 digest of
5585acaca2fSWilliam A. Kennington III     // EEPROM area "data_offset:data_size".
5595acaca2fSWilliam A. Kennington III 
5605acaca2fSWilliam A. Kennington III     static failure_reason validate_signature(
5615acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
5625acaca2fSWilliam A. Kennington III         uint32_t data_offset, uint32_t data_size, enum signature_scheme scheme,
5635acaca2fSWilliam A. Kennington III         uint32_t raw_signature_offset)
5645acaca2fSWilliam A. Kennington III     {
5655acaca2fSWilliam A. Kennington III         uint8_t signature[LIBCR51SIGN_MAX_SIGNATURE_SIZE];
5665acaca2fSWilliam A. Kennington III         uint16_t key_size;
5675acaca2fSWilliam A. Kennington III         uint32_t digest_size;
5685acaca2fSWilliam A. Kennington III         uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
5695acaca2fSWilliam A. Kennington III         int rv;
5705acaca2fSWilliam A. Kennington III         enum hash_type hash_type;
5715acaca2fSWilliam A. Kennington III 
5725acaca2fSWilliam A. Kennington III         if (!intf->hash_init)
5735acaca2fSWilliam A. Kennington III         {
574af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: missing hash_init\n");
5755acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
5765acaca2fSWilliam A. Kennington III         }
5775acaca2fSWilliam A. Kennington III         rv = get_hash_type_from_signature(scheme, &hash_type);
5785acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
5795acaca2fSWilliam A. Kennington III         {
5805acaca2fSWilliam A. Kennington III             CPRINTS(
5815acaca2fSWilliam A. Kennington III                 ctx,
582af46bea6SWilliam A. Kennington III                 "validate_payload_regions: hash_type from signature failed\n");
5835acaca2fSWilliam A. Kennington III             return rv;
5845acaca2fSWilliam A. Kennington III         }
5855acaca2fSWilliam A. Kennington III         rv = intf->hash_init(ctx, hash_type);
5865acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
5875acaca2fSWilliam A. Kennington III         {
588af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: hash_init failed\n");
5895acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
5905acaca2fSWilliam A. Kennington III         }
5915acaca2fSWilliam A. Kennington III         rv = read_and_hash_update(ctx, intf, data_offset, data_size);
5925acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
5935acaca2fSWilliam A. Kennington III         {
594af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: hash_update failed\n");
5955acaca2fSWilliam A. Kennington III             return rv;
5965acaca2fSWilliam A. Kennington III         }
5975acaca2fSWilliam A. Kennington III         if (!intf->hash_final)
5985acaca2fSWilliam A. Kennington III         {
599af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: missing hash_final\n");
6005acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
6015acaca2fSWilliam A. Kennington III         }
6025acaca2fSWilliam A. Kennington III         rv = intf->hash_final((void*)ctx, dcrypto_digest);
6035acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
6045acaca2fSWilliam A. Kennington III         {
605af46bea6SWilliam A. Kennington III             CPRINTS(ctx,
606af46bea6SWilliam A. Kennington III                     "validate_signature: hash_final failed (status = %d)\n",
6075acaca2fSWilliam A. Kennington III                     rv);
6085acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
6095acaca2fSWilliam A. Kennington III         }
6105acaca2fSWilliam A. Kennington III         rv = get_key_size(scheme, &key_size);
6115acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
6125acaca2fSWilliam A. Kennington III         {
6135acaca2fSWilliam A. Kennington III             return rv;
6145acaca2fSWilliam A. Kennington III         }
6155acaca2fSWilliam A. Kennington III 
6165acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, raw_signature_offset, key_size, signature);
6175acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
6185acaca2fSWilliam A. Kennington III         {
6195acaca2fSWilliam A. Kennington III             CPRINTS(
6205acaca2fSWilliam A. Kennington III                 ctx,
621af46bea6SWilliam A. Kennington III                 "validate_signature: failed to read signature (status = %d)\n",
6225acaca2fSWilliam A. Kennington III                 rv);
6235acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
6245acaca2fSWilliam A. Kennington III         }
6255acaca2fSWilliam A. Kennington III         if (!intf->verify_signature)
6265acaca2fSWilliam A. Kennington III         {
627af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_signature: missing verify_signature\n");
6285acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
6295acaca2fSWilliam A. Kennington III         }
6305acaca2fSWilliam A. Kennington III         rv = get_hash_digest_size(hash_type, &digest_size);
6315acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
6325acaca2fSWilliam A. Kennington III         {
6335acaca2fSWilliam A. Kennington III             return rv;
6345acaca2fSWilliam A. Kennington III         }
6355acaca2fSWilliam A. Kennington III         rv = intf->verify_signature(ctx, scheme, signature, key_size,
6365acaca2fSWilliam A. Kennington III                                     dcrypto_digest, digest_size);
6375acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
6385acaca2fSWilliam A. Kennington III         {
6395acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
640af46bea6SWilliam A. Kennington III                     "validate_signature: verification failed (status = %d)\n",
6415acaca2fSWilliam A. Kennington III                     rv);
6425acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_SIGNATURE;
6435acaca2fSWilliam A. Kennington III         }
644af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "validate_signature: verification succeeded\n");
6455acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_SUCCESS;
6465acaca2fSWilliam A. Kennington III     }
6475acaca2fSWilliam A. Kennington III 
6485acaca2fSWilliam A. Kennington III     // Sanity checks the image descriptor & validates its signature.
6495acaca2fSWilliam A. Kennington III     // This function does not validate the image_region array or image hash.
6505acaca2fSWilliam A. Kennington III     //
6515acaca2fSWilliam A. Kennington III     //@param[in] ctx  context which describes the image and holds opaque private
6525acaca2fSWilliam A. Kennington III     //                 data for the user of the library
6535acaca2fSWilliam A. Kennington III     //@param[in] intf  function pointers which interface to the current system
6545acaca2fSWilliam A. Kennington III     // and environment
6555acaca2fSWilliam A. Kennington III     //@param offset  Absolute image descriptor flash offset.
6565acaca2fSWilliam A. Kennington III     //@param relative_offset  Image descriptor offset relative to image start.
657af46bea6SWilliam A. Kennington III     //@param max_size Maximum size of the flash space in bytes.
6585acaca2fSWilliam A. Kennington III     //@param descriptor  Output pointer to an image_descriptor struct
6595acaca2fSWilliam A. Kennington III 
6605acaca2fSWilliam A. Kennington III     static failure_reason validate_descriptor(
6615acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
662af46bea6SWilliam A. Kennington III         uint32_t offset, uint32_t relative_offset, uint32_t max_size)
6635acaca2fSWilliam A. Kennington III     {
6645acaca2fSWilliam A. Kennington III         uint32_t max_descriptor_size, signed_size, signature_scheme,
6655acaca2fSWilliam A. Kennington III             signature_offset;
6665acaca2fSWilliam A. Kennington III         uint32_t signature_struct_offset, signature_struct_size,
6675acaca2fSWilliam A. Kennington III             hash_struct_size;
6685acaca2fSWilliam A. Kennington III         int rv;
6695acaca2fSWilliam A. Kennington III 
670af46bea6SWilliam A. Kennington III         max_descriptor_size = max_size - relative_offset;
671af46bea6SWilliam A. Kennington III         if (max_size < relative_offset ||
6725acaca2fSWilliam A. Kennington III             max_descriptor_size < sizeof(struct image_descriptor))
6735acaca2fSWilliam A. Kennington III         {
674af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: invalid arguments\n");
6755acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
6765acaca2fSWilliam A. Kennington III         }
6775acaca2fSWilliam A. Kennington III 
6785acaca2fSWilliam A. Kennington III         rv = intf->read(ctx, offset, sizeof(ctx->descriptor),
6795acaca2fSWilliam A. Kennington III                         (uint8_t*)&ctx->descriptor);
6805acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
6815acaca2fSWilliam A. Kennington III         {
682af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: failed to read descriptor\n");
6835acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
6845acaca2fSWilliam A. Kennington III         }
6855acaca2fSWilliam A. Kennington III         if (ctx->descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
6865acaca2fSWilliam A. Kennington III             ctx->descriptor.descriptor_offset != relative_offset ||
6875acaca2fSWilliam A. Kennington III             ctx->descriptor.region_count == 0 ||
6885acaca2fSWilliam A. Kennington III             ctx->descriptor.descriptor_area_size > max_descriptor_size ||
689af46bea6SWilliam A. Kennington III             ctx->descriptor.image_size > max_size)
6905acaca2fSWilliam A. Kennington III         {
691af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: invalid descriptor\n");
692af46bea6SWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
693af46bea6SWilliam A. Kennington III         }
694af46bea6SWilliam A. Kennington III         if (intf->image_size_valid == NULL)
695af46bea6SWilliam A. Kennington III         {
696af46bea6SWilliam A. Kennington III             // Preserve original behavior of requiring exact image_size match if
697af46bea6SWilliam A. Kennington III             // no operator is provided.
698af46bea6SWilliam A. Kennington III             if (ctx->descriptor.image_size != max_size)
699af46bea6SWilliam A. Kennington III             {
700af46bea6SWilliam A. Kennington III                 CPRINTS(ctx, "validate_descriptor: invalid image size\n");
701af46bea6SWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
702af46bea6SWilliam A. Kennington III             }
703af46bea6SWilliam A. Kennington III         }
704af46bea6SWilliam A. Kennington III         else if (!intf->image_size_valid(ctx->descriptor.image_size))
705af46bea6SWilliam A. Kennington III         {
706af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: invalid image size\n");
7075acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
7085acaca2fSWilliam A. Kennington III         }
7095acaca2fSWilliam A. Kennington III         if (ctx->descriptor.image_type != IMAGE_DEV &&
7105acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_PROD &&
7115acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_BREAKOUT &&
7125acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_TEST &&
7135acaca2fSWilliam A. Kennington III             ctx->descriptor.image_type != IMAGE_UNSIGNED_INTEGRITY)
7145acaca2fSWilliam A. Kennington III         {
715af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: bad image type\n");
7165acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
7175acaca2fSWilliam A. Kennington III         }
7185acaca2fSWilliam A. Kennington III         // Although the image_descriptor struct supports unauthenticated
7195acaca2fSWilliam A. Kennington III         // images, Haven will not allow it.
7205acaca2fSWilliam A. Kennington III         // Haven only supports SHA256 + RSA2048/RSA3072_PKCS15 currently.
7215acaca2fSWilliam A. Kennington III 
7225acaca2fSWilliam A. Kennington III         signature_scheme = ctx->descriptor.signature_scheme;
7235acaca2fSWilliam A. Kennington III 
7245acaca2fSWilliam A. Kennington III         rv = is_signature_scheme_supported(signature_scheme);
7255acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
7265acaca2fSWilliam A. Kennington III         {
7275acaca2fSWilliam A. Kennington III             return rv;
7285acaca2fSWilliam A. Kennington III         }
7295acaca2fSWilliam A. Kennington III         rv = is_hash_type_supported(ctx->descriptor.hash_type);
7305acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
7315acaca2fSWilliam A. Kennington III         {
732af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_payload_regions: invalid hash type\n");
7335acaca2fSWilliam A. Kennington III             return rv;
7345acaca2fSWilliam A. Kennington III         }
7355acaca2fSWilliam A. Kennington III         if (ctx->descriptor.descriptor_major > MAX_MAJOR_VERSION ||
7365acaca2fSWilliam A. Kennington III             ctx->descriptor.region_count > LIBCR51SIGN_MAX_REGION_COUNT)
7375acaca2fSWilliam A. Kennington III         {
738af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate_descriptor: unsupported descriptor\n");
7395acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR;
7405acaca2fSWilliam A. Kennington III         }
741*2be45238SPatrick Williams         rv = get_signature_struct_size(signature_scheme,
742*2be45238SPatrick Williams                                        &signature_struct_size);
7435acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
7445acaca2fSWilliam A. Kennington III         {
7455acaca2fSWilliam A. Kennington III             return rv;
7465acaca2fSWilliam A. Kennington III         }
7475acaca2fSWilliam A. Kennington III 
7485acaca2fSWilliam A. Kennington III         // Compute the size of the signed portion of the image descriptor.
749*2be45238SPatrick Williams         signed_size = sizeof(struct image_descriptor) +
750*2be45238SPatrick Williams                       ctx->descriptor.region_count *
751*2be45238SPatrick Williams                           sizeof(struct image_region);
7525acaca2fSWilliam A. Kennington III         rv = get_hash_struct_size(ctx->descriptor.hash_type, &hash_struct_size);
7535acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
7545acaca2fSWilliam A. Kennington III         {
7555acaca2fSWilliam A. Kennington III             return rv;
7565acaca2fSWilliam A. Kennington III         }
7575acaca2fSWilliam A. Kennington III         signed_size += hash_struct_size;
7585acaca2fSWilliam A. Kennington III         if (ctx->descriptor.denylist_size)
7595acaca2fSWilliam A. Kennington III         {
7605acaca2fSWilliam A. Kennington III             signed_size += sizeof(struct denylist);
761*2be45238SPatrick Williams             signed_size += ctx->descriptor.denylist_size *
762*2be45238SPatrick Williams                            sizeof(struct denylist_record);
7635acaca2fSWilliam A. Kennington III         }
7645acaca2fSWilliam A. Kennington III         if (ctx->descriptor.blob_size)
7655acaca2fSWilliam A. Kennington III         {
7665acaca2fSWilliam A. Kennington III             signed_size += sizeof(struct blob);
7675acaca2fSWilliam A. Kennington III             // Previous additions are guaranteed not to overflow.
7685acaca2fSWilliam A. Kennington III             if (ctx->descriptor.blob_size >
7695acaca2fSWilliam A. Kennington III                 ctx->descriptor.descriptor_area_size - signed_size)
7705acaca2fSWilliam A. Kennington III             {
771af46bea6SWilliam A. Kennington III                 CPRINTS(ctx, "validate_descriptor: invalid blob size (0x%x)\n",
7725acaca2fSWilliam A. Kennington III                         ctx->descriptor.blob_size);
7735acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
7745acaca2fSWilliam A. Kennington III             }
7755acaca2fSWilliam A. Kennington III             signed_size += ctx->descriptor.blob_size;
7765acaca2fSWilliam A. Kennington III         }
7775acaca2fSWilliam A. Kennington III         if (signature_struct_size >
7785acaca2fSWilliam A. Kennington III             ctx->descriptor.descriptor_area_size - signed_size)
7795acaca2fSWilliam A. Kennington III         {
7805acaca2fSWilliam A. Kennington III             CPRINTS(ctx,
7815acaca2fSWilliam A. Kennington III                     "validate_descriptor: invalid descriptor area size "
782af46bea6SWilliam A. Kennington III                     "(expected = 0x%x, actual = 0x%x)\n",
7835acaca2fSWilliam A. Kennington III                     ctx->descriptor.descriptor_area_size,
7845acaca2fSWilliam A. Kennington III                     signed_size + signature_struct_size);
7855acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
7865acaca2fSWilliam A. Kennington III         }
7875acaca2fSWilliam A. Kennington III         signature_struct_offset = signed_size;
7885acaca2fSWilliam A. Kennington III         // Omit the actual signature.
7895acaca2fSWilliam A. Kennington III         rv = get_signature_field_offset(signature_scheme, &signature_offset);
7905acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
7915acaca2fSWilliam A. Kennington III         {
7925acaca2fSWilliam A. Kennington III             return rv;
7935acaca2fSWilliam A. Kennington III         }
7945acaca2fSWilliam A. Kennington III         signed_size += signature_offset;
7955acaca2fSWilliam A. Kennington III 
7965acaca2fSWilliam A. Kennington III         // Lookup key & validate transition.
7975acaca2fSWilliam A. Kennington III         rv = validate_transition(ctx, intf, offset + signature_struct_offset);
7985acaca2fSWilliam A. Kennington III 
7995acaca2fSWilliam A. Kennington III         if (rv != LIBCR51SIGN_SUCCESS)
8005acaca2fSWilliam A. Kennington III         {
8015acaca2fSWilliam A. Kennington III             return rv;
8025acaca2fSWilliam A. Kennington III         }
8035acaca2fSWilliam A. Kennington III         return validate_signature(ctx, intf, offset, signed_size,
8045acaca2fSWilliam A. Kennington III                                   signature_scheme, offset + signed_size);
8055acaca2fSWilliam A. Kennington III     }
8065acaca2fSWilliam A. Kennington III 
8075acaca2fSWilliam A. Kennington III     // Scans the external EEPROM for a magic value at "alignment" boundaries.
8085acaca2fSWilliam A. Kennington III     //
8095acaca2fSWilliam A. Kennington III     //@param device  Handle to the external EEPROM.
8105acaca2fSWilliam A. Kennington III     //@param magic   8-byte pattern to search for.
8115acaca2fSWilliam A. Kennington III     //@param start_offset  Offset to begin searching at.
8125acaca2fSWilliam A. Kennington III     //@param limit   Exclusive address (e.g. EEPROM size).
8135acaca2fSWilliam A. Kennington III     //@param alignment   Alignment boundaries (POW2) to search on.
8145acaca2fSWilliam A. Kennington III     //@param header_offset   Location to place the new header offset.
8155acaca2fSWilliam A. Kennington III     //@return LIBCR51SIGN_SUCCESS (or non-zero on error).
8165acaca2fSWilliam A. Kennington III 
8175acaca2fSWilliam A. Kennington III     int scan_for_magic_8(const struct libcr51sign_ctx* ctx,
8185acaca2fSWilliam A. Kennington III                          const struct libcr51sign_intf* intf, uint64_t magic,
8195acaca2fSWilliam A. Kennington III                          uint32_t start_offset, uint32_t limit,
8205acaca2fSWilliam A. Kennington III                          uint32_t alignment, uint32_t* header_offset)
8215acaca2fSWilliam A. Kennington III     {
8225acaca2fSWilliam A. Kennington III         uint64_t read_data;
8235acaca2fSWilliam A. Kennington III         uint32_t offset;
8245acaca2fSWilliam A. Kennington III         int rv;
8255acaca2fSWilliam A. Kennington III 
8265acaca2fSWilliam A. Kennington III         if (limit <= start_offset || limit > ctx->end_offset ||
8275acaca2fSWilliam A. Kennington III             limit < sizeof(magic) || !POWER_OF_TWO(alignment))
8285acaca2fSWilliam A. Kennington III         {
8295acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
8305acaca2fSWilliam A. Kennington III         }
8315acaca2fSWilliam A. Kennington III 
8325acaca2fSWilliam A. Kennington III         if (!intf->read)
8335acaca2fSWilliam A. Kennington III         {
834af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "scan_for_magic_8: missing intf->read\n");
8355acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
8365acaca2fSWilliam A. Kennington III         }
8375acaca2fSWilliam A. Kennington III         // Align start_offset to the next valid boundary.
8385acaca2fSWilliam A. Kennington III         start_offset = ((start_offset - 1) & ~(alignment - 1)) + alignment;
8395acaca2fSWilliam A. Kennington III         for (offset = start_offset; offset < limit - sizeof(magic);
8405acaca2fSWilliam A. Kennington III              offset += alignment)
8415acaca2fSWilliam A. Kennington III         {
8425acaca2fSWilliam A. Kennington III             rv = intf->read((void*)ctx, offset, sizeof(read_data),
8435acaca2fSWilliam A. Kennington III                             (uint8_t*)&read_data);
8445acaca2fSWilliam A. Kennington III             if (rv != LIBCR51SIGN_SUCCESS)
8455acaca2fSWilliam A. Kennington III             {
8465acaca2fSWilliam A. Kennington III                 return rv;
8475acaca2fSWilliam A. Kennington III             }
8485acaca2fSWilliam A. Kennington III             if (read_data == magic)
8495acaca2fSWilliam A. Kennington III             {
8505acaca2fSWilliam A. Kennington III                 if (header_offset)
8515acaca2fSWilliam A. Kennington III                 {
8525acaca2fSWilliam A. Kennington III                     *header_offset = offset;
8535acaca2fSWilliam A. Kennington III                 }
8545acaca2fSWilliam A. Kennington III                 return LIBCR51SIGN_SUCCESS;
8555acaca2fSWilliam A. Kennington III             }
8565acaca2fSWilliam A. Kennington III         }
8575acaca2fSWilliam A. Kennington III         // Failed to locate magic.
8585acaca2fSWilliam A. Kennington III         return LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC;
8595acaca2fSWilliam A. Kennington III     }
8605acaca2fSWilliam A. Kennington III 
8615acaca2fSWilliam A. Kennington III     // Check whether the signature on the image is valid.
8625acaca2fSWilliam A. Kennington III     // Validates the authenticity of an EEPROM image. Scans for & validates the
8635acaca2fSWilliam A. Kennington III     // signature on the image descriptor. If the descriptor validates, hashes
8645acaca2fSWilliam A. Kennington III     // the rest of the image to verify its integrity.
8655acaca2fSWilliam A. Kennington III     //
8665acaca2fSWilliam A. Kennington III     // @param[in] ctx - context which describes the image and holds opaque
8675acaca2fSWilliam A. Kennington III     // private
8685acaca2fSWilliam A. Kennington III     //                 data for the user of the library
8695acaca2fSWilliam A. Kennington III     // @param[in] intf - function pointers which interface to the current system
8705acaca2fSWilliam A. Kennington III     //                  and environment
8715acaca2fSWilliam A. Kennington III     // @param[out] image_regions - image_region pointer to an array for the
8725acaca2fSWilliam A. Kennington III     // output
8735acaca2fSWilliam A. Kennington III     //
8745acaca2fSWilliam A. Kennington III     // @return nonzero on error, zero on success
8755acaca2fSWilliam A. Kennington III 
8765acaca2fSWilliam A. Kennington III     failure_reason libcr51sign_validate(
8775acaca2fSWilliam A. Kennington III         const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
8785acaca2fSWilliam A. Kennington III         struct libcr51sign_validated_regions* image_regions)
8795acaca2fSWilliam A. Kennington III     {
8805acaca2fSWilliam A. Kennington III         uint32_t image_limit = 0;
8815acaca2fSWilliam A. Kennington III         int rv, rv_first_desc = LIBCR51SIGN_SUCCESS;
8825acaca2fSWilliam A. Kennington III         uint32_t descriptor_offset;
8835acaca2fSWilliam A. Kennington III 
8845acaca2fSWilliam A. Kennington III         if (!ctx)
8855acaca2fSWilliam A. Kennington III         {
886af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "Missing context\n");
8875acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_CONTEXT;
8885acaca2fSWilliam A. Kennington III         }
8895acaca2fSWilliam A. Kennington III         else if (!intf)
8905acaca2fSWilliam A. Kennington III         {
891af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "Missing interface\n");
8925acaca2fSWilliam A. Kennington III             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
8935acaca2fSWilliam A. Kennington III         }
8945acaca2fSWilliam A. Kennington III 
8955acaca2fSWilliam A. Kennington III         rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, ctx->start_offset,
8965acaca2fSWilliam A. Kennington III                               ctx->end_offset, DESCRIPTOR_ALIGNMENT,
8975acaca2fSWilliam A. Kennington III                               &descriptor_offset);
8985acaca2fSWilliam A. Kennington III         while (rv == LIBCR51SIGN_SUCCESS)
8995acaca2fSWilliam A. Kennington III         {
900af46bea6SWilliam A. Kennington III             CPRINTS(ctx, "validate: potential image descriptor found @%x\n",
9015acaca2fSWilliam A. Kennington III                     descriptor_offset);
9025acaca2fSWilliam A. Kennington III             // Validation is split into 2 functions to minimize
9035acaca2fSWilliam A. Kennington III             // stack usage.
9045acaca2fSWilliam A. Kennington III 
9055acaca2fSWilliam A. Kennington III             rv = validate_descriptor(ctx, intf, descriptor_offset,
9065acaca2fSWilliam A. Kennington III                                      descriptor_offset - ctx->start_offset,
9075acaca2fSWilliam A. Kennington III                                      ctx->end_offset - ctx->start_offset);
9085acaca2fSWilliam A. Kennington III             if (rv != LIBCR51SIGN_SUCCESS)
9095acaca2fSWilliam A. Kennington III             {
910af46bea6SWilliam A. Kennington III                 CPRINTS(ctx, "validate: validate_descriptor() failed ec%d\n",
9115acaca2fSWilliam A. Kennington III                         rv);
9125acaca2fSWilliam A. Kennington III             }
9135acaca2fSWilliam A. Kennington III 
9145acaca2fSWilliam A. Kennington III             if (rv == LIBCR51SIGN_SUCCESS)
9155acaca2fSWilliam A. Kennington III             {
9165acaca2fSWilliam A. Kennington III                 rv = validate_payload_regions_helper(
9175acaca2fSWilliam A. Kennington III                     ctx, intf, descriptor_offset, image_regions);
9185acaca2fSWilliam A. Kennington III                 if (rv == LIBCR51SIGN_SUCCESS)
9195acaca2fSWilliam A. Kennington III                 {
920af46bea6SWilliam A. Kennington III                     CPRINTS(ctx, "validate: success!\n");
9215acaca2fSWilliam A. Kennington III                     return rv;
9225acaca2fSWilliam A. Kennington III                 }
9235acaca2fSWilliam A. Kennington III                 CPRINTS(ctx,
924af46bea6SWilliam A. Kennington III                         "validate: validate_payload_regions() failed ec%d\n",
9255acaca2fSWilliam A. Kennington III                         rv);
9265acaca2fSWilliam A. Kennington III             }
9275acaca2fSWilliam A. Kennington III             // Store the first desc fail reason if any
9285acaca2fSWilliam A. Kennington III             if (rv != LIBCR51SIGN_SUCCESS &&
9295acaca2fSWilliam A. Kennington III                 rv_first_desc == LIBCR51SIGN_SUCCESS)
9305acaca2fSWilliam A. Kennington III                 rv_first_desc = rv;
9315acaca2fSWilliam A. Kennington III 
9325acaca2fSWilliam A. Kennington III             // scan_for_magic_8() will round up to the next aligned boundary.
9335acaca2fSWilliam A. Kennington III             descriptor_offset++;
9345acaca2fSWilliam A. Kennington III             image_limit = ctx->end_offset - ctx->start_offset;
9355acaca2fSWilliam A. Kennington III             rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC,
9365acaca2fSWilliam A. Kennington III                                   descriptor_offset, image_limit,
9375acaca2fSWilliam A. Kennington III                                   DESCRIPTOR_ALIGNMENT, &descriptor_offset);
9385acaca2fSWilliam A. Kennington III         }
939af46bea6SWilliam A. Kennington III         CPRINTS(ctx, "validate: failed to validate image ec%d\n", rv);
9405acaca2fSWilliam A. Kennington III         // If desc validation failed for some reason then return that reason
9415acaca2fSWilliam A. Kennington III         if (rv_first_desc != LIBCR51SIGN_SUCCESS)
9425acaca2fSWilliam A. Kennington III             return rv_first_desc;
9435acaca2fSWilliam A. Kennington III         else
9445acaca2fSWilliam A. Kennington III             return rv;
9455acaca2fSWilliam A. Kennington III     }
9465acaca2fSWilliam A. Kennington III 
9475acaca2fSWilliam A. Kennington III     // @func to returns the libcr51sign error code as a string
9485acaca2fSWilliam A. Kennington III     // @param[in] ec - Error code
9495acaca2fSWilliam A. Kennington III     // @return error code in string format
9505acaca2fSWilliam A. Kennington III 
9515acaca2fSWilliam A. Kennington III     const char* libcr51sign_errorcode_to_string(failure_reason ec)
9525acaca2fSWilliam A. Kennington III     {
9535acaca2fSWilliam A. Kennington III         switch (ec)
9545acaca2fSWilliam A. Kennington III         {
9555acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_SUCCESS:
9565acaca2fSWilliam A. Kennington III                 return "Success";
9575acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_RUNTIME_FAILURE:
9585acaca2fSWilliam A. Kennington III                 return "Runtime Error Failure";
9595acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR:
9605acaca2fSWilliam A. Kennington III                 return "Unsupported descriptor";
9615acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR:
9625acaca2fSWilliam A. Kennington III                 return "Invalid descriptor";
9635acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY:
9645acaca2fSWilliam A. Kennington III                 return "Invalid image family";
9655acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED:
9665acaca2fSWilliam A. Kennington III                 return "Image type disallowed";
9675acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED:
9685acaca2fSWilliam A. Kennington III                 return "Dev downgrade disallowed";
9695acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_UNTRUSTED_KEY:
9705acaca2fSWilliam A. Kennington III                 return "Untrusted key";
9715acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_SIGNATURE:
9725acaca2fSWilliam A. Kennington III                 return "Invalid signature";
9735acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_HASH:
9745acaca2fSWilliam A. Kennington III                 return "Invalid hash";
9755acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_HASH_TYPE:
9765acaca2fSWilliam A. Kennington III                 return "Invalid hash type";
9775acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_ARGUMENT:
9785acaca2fSWilliam A. Kennington III                 return "Invalid Argument";
9795acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC:
9805acaca2fSWilliam A. Kennington III                 return "Failed to locate descriptor";
9815acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_CONTEXT:
9825acaca2fSWilliam A. Kennington III                 return "Invalid context";
9835acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_INTERFACE:
9845acaca2fSWilliam A. Kennington III                 return "Invalid interface";
9855acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME:
9865acaca2fSWilliam A. Kennington III                 return "Invalid signature scheme";
9875acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_REGION_INPUT:
9885acaca2fSWilliam A. Kennington III                 return "Invalid image region input";
9895acaca2fSWilliam A. Kennington III             case LIBCR51SIGN_ERROR_INVALID_REGION_SIZE:
9905acaca2fSWilliam A. Kennington III                 return "Invalid image region size";
9915acaca2fSWilliam A. Kennington III             default:
9925acaca2fSWilliam A. Kennington III                 return "Unknown error";
9935acaca2fSWilliam A. Kennington III         }
9945acaca2fSWilliam A. Kennington III     }
9955acaca2fSWilliam A. Kennington III 
9965acaca2fSWilliam A. Kennington III #ifdef __cplusplus
9975acaca2fSWilliam A. Kennington III } //  extern "C"
9985acaca2fSWilliam A. Kennington III #endif
999