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 */
16dca92e47SWilly Tu
17dca92e47SWilly Tu #include "stddef.h"
18dca92e47SWilly Tu
19dca92e47SWilly Tu #include <assert.h>
20dca92e47SWilly Tu #include <libcr51sign/cr51_image_descriptor.h>
215acaca2fSWilliam A. Kennington III #include <libcr51sign/libcr51sign.h>
22dca92e47SWilly Tu #include <libcr51sign/libcr51sign_internal.h>
23dca92e47SWilly Tu #include <libcr51sign/libcr51sign_mauv.h>
24dca92e47SWilly Tu #include <stdint.h>
255acaca2fSWilliam A. Kennington III #include <stdio.h>
26dca92e47SWilly Tu #include <stdlib.h>
275acaca2fSWilliam A. Kennington III #include <string.h>
285acaca2fSWilliam A. Kennington III
295acaca2fSWilliam A. Kennington III #ifdef __cplusplus
305acaca2fSWilliam A. Kennington III extern "C"
315acaca2fSWilliam A. Kennington III {
325acaca2fSWilliam A. Kennington III #endif
335acaca2fSWilliam A. Kennington III
345acaca2fSWilliam A. Kennington III // True of x is a power of two
355acaca2fSWilliam A. Kennington III #define POWER_OF_TWO(x) ((x) && !((x) & ((x) - 1)))
365acaca2fSWilliam A. Kennington III
375acaca2fSWilliam A. Kennington III // Maximum version supported. Major revisions are not backwards compatible.
385acaca2fSWilliam A. Kennington III #define MAX_MAJOR_VERSION 1
395acaca2fSWilliam A. Kennington III
405acaca2fSWilliam A. Kennington III // Descriptor alignment on the external EEPROM.
415acaca2fSWilliam A. Kennington III #define DESCRIPTOR_ALIGNMENT (64 * 1024)
425acaca2fSWilliam A. Kennington III
435acaca2fSWilliam A. Kennington III // SPS EEPROM sector size is 4KiB, since this is the smallest erasable size.
445acaca2fSWilliam A. Kennington III #define IMAGE_REGION_ALIGNMENT 4096
455acaca2fSWilliam A. Kennington III
465acaca2fSWilliam A. Kennington III #define MAX_READ_SIZE 1024
475acaca2fSWilliam A. Kennington III
485acaca2fSWilliam A. Kennington III #ifndef ARRAY_SIZE
495acaca2fSWilliam A. Kennington III #define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0]))
505acaca2fSWilliam A. Kennington III #endif
515acaca2fSWilliam A. Kennington III
525acaca2fSWilliam A. Kennington III // Values of SIGNATURE_OFFSET shuold be same for all sig types (2048,3072,4096)
535acaca2fSWilliam A. Kennington III #define SIGNATURE_OFFSET offsetof(struct signature_rsa3072_pkcs15, modulus)
545acaca2fSWilliam A. Kennington III
555acaca2fSWilliam A. Kennington III #ifndef BUILD_ASSERT
565acaca2fSWilliam A. Kennington III #define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
575acaca2fSWilliam A. Kennington III #endif
585acaca2fSWilliam A. Kennington III
595acaca2fSWilliam A. Kennington III // Returns the bytes size of keys used in the given signature_scheme.
605acaca2fSWilliam A. Kennington III // Return error if signature_scheme is invalid.
615acaca2fSWilliam A. Kennington III //
get_key_size(enum signature_scheme signature_scheme,uint16_t * key_size)625acaca2fSWilliam A. Kennington III static failure_reason get_key_size(enum signature_scheme signature_scheme,
635acaca2fSWilliam A. Kennington III uint16_t* key_size)
645acaca2fSWilliam A. Kennington III {
655acaca2fSWilliam A. Kennington III switch (signature_scheme)
665acaca2fSWilliam A. Kennington III {
675acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15:
685acaca2fSWilliam A. Kennington III *key_size = 256;
695acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
705acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15:
715acaca2fSWilliam A. Kennington III *key_size = 384;
725acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
735acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15:
745acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512:
755acaca2fSWilliam A. Kennington III *key_size = 512;
765acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
775acaca2fSWilliam A. Kennington III default:
785acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
795acaca2fSWilliam A. Kennington III }
805acaca2fSWilliam A. Kennington III }
815acaca2fSWilliam A. Kennington III
825acaca2fSWilliam A. Kennington III // Returns the hash_type for a given signature scheme
835acaca2fSWilliam A. Kennington III // Returns error if scheme is invalid.
get_hash_type_from_signature(enum signature_scheme scheme,enum hash_type * type)845acaca2fSWilliam A. Kennington III failure_reason get_hash_type_from_signature(enum signature_scheme scheme,
855acaca2fSWilliam A. Kennington III enum hash_type* type)
865acaca2fSWilliam A. Kennington III {
875acaca2fSWilliam A. Kennington III switch (scheme)
885acaca2fSWilliam A. Kennington III {
895acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15:
905acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15:
915acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15:
925acaca2fSWilliam A. Kennington III *type = HASH_SHA2_256;
935acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
945acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512:
955acaca2fSWilliam A. Kennington III *type = HASH_SHA2_512;
965acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
975acaca2fSWilliam A. Kennington III default:
985acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
995acaca2fSWilliam A. Kennington III }
1005acaca2fSWilliam A. Kennington III }
1015acaca2fSWilliam A. Kennington III
1025acaca2fSWilliam A. Kennington III // Check if the given hash_type is supported.
1035acaca2fSWilliam A. Kennington III // Returns error if hash_type is not supported.
is_hash_type_supported(enum hash_type type)1045acaca2fSWilliam A. Kennington III static failure_reason is_hash_type_supported(enum hash_type type)
1055acaca2fSWilliam A. Kennington III {
1065acaca2fSWilliam A. Kennington III switch (type)
1075acaca2fSWilliam A. Kennington III {
1085acaca2fSWilliam A. Kennington III case HASH_SHA2_256:
1095acaca2fSWilliam A. Kennington III case HASH_SHA2_512:
1105acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
1115acaca2fSWilliam A. Kennington III default:
1125acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
1135acaca2fSWilliam A. Kennington III }
1145acaca2fSWilliam A. Kennington III }
1155acaca2fSWilliam A. Kennington III
1165acaca2fSWilliam A. Kennington III // Determines digest size for a given hash_type.
1175acaca2fSWilliam A. Kennington III // Returns error if hash_type is not supported.
get_hash_digest_size(enum hash_type type,uint32_t * size)1186084957fSPatrick Williams static failure_reason get_hash_digest_size(enum hash_type type, uint32_t* size)
1195acaca2fSWilliam A. Kennington III {
1205acaca2fSWilliam A. Kennington III switch (type)
1215acaca2fSWilliam A. Kennington III {
1225acaca2fSWilliam A. Kennington III case HASH_SHA2_256:
1235acaca2fSWilliam A. Kennington III *size = LIBCR51SIGN_SHA256_DIGEST_SIZE;
1245acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
1255acaca2fSWilliam A. Kennington III case HASH_SHA2_512:
1265acaca2fSWilliam A. Kennington III *size = LIBCR51SIGN_SHA512_DIGEST_SIZE;
1275acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
1285acaca2fSWilliam A. Kennington III default:
1295acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
1305acaca2fSWilliam A. Kennington III }
1315acaca2fSWilliam A. Kennington III }
1325acaca2fSWilliam A. Kennington III
1335acaca2fSWilliam A. Kennington III // Determines hash struct size for a given hash_type.
1345acaca2fSWilliam A. Kennington III // Returns error if hash_type is not supported.
get_hash_struct_size(enum hash_type type,uint32_t * size)1356084957fSPatrick Williams static failure_reason get_hash_struct_size(enum hash_type type, uint32_t* size)
1365acaca2fSWilliam A. Kennington III {
1375acaca2fSWilliam A. Kennington III switch (type)
1385acaca2fSWilliam A. Kennington III {
1395acaca2fSWilliam A. Kennington III case HASH_SHA2_256:
1405acaca2fSWilliam A. Kennington III *size = sizeof(struct hash_sha256);
1415acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
1425acaca2fSWilliam A. Kennington III case HASH_SHA2_512:
143dca92e47SWilly Tu *size = sizeof(struct hash_sha512);
1445acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
1455acaca2fSWilliam A. Kennington III default:
1465acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
1475acaca2fSWilliam A. Kennington III }
1485acaca2fSWilliam A. Kennington III }
1495acaca2fSWilliam A. Kennington III
1505acaca2fSWilliam A. Kennington III // Checks that:
1515acaca2fSWilliam A. Kennington III // - The signing key is trusted
1525acaca2fSWilliam A. Kennington III // - The target version is not denylisted
1535acaca2fSWilliam A. Kennington III // If validating a staged update, also checks that:
1545acaca2fSWilliam A. Kennington III // - The target image family matches the current image family
1555acaca2fSWilliam A. Kennington III // - The image type transition is legal (i.e. dev -> *|| prod -> prod) or
1565acaca2fSWilliam A. Kennington III // alternatively that the hardware ID is allowlisted
1575acaca2fSWilliam A. Kennington III // Assuming the caller has performed following:
1585acaca2fSWilliam A. Kennington III // board_get_base_key_index();
1595acaca2fSWilliam A. Kennington III // board_get_key_array
1605acaca2fSWilliam A. Kennington III // Possible return codes:
1615acaca2fSWilliam A. Kennington III // LIBCR51SIGN_SUCCESS = 0,
1625acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
1635acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
1645acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
1655acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
1665acaca2fSWilliam A. Kennington III
validate_transition(const struct libcr51sign_ctx * ctx,const struct libcr51sign_intf * intf,uint32_t signature_struct_offset)1676084957fSPatrick Williams static failure_reason validate_transition(const struct libcr51sign_ctx* ctx,
1685acaca2fSWilliam A. Kennington III const struct libcr51sign_intf* intf,
1695acaca2fSWilliam A. Kennington III uint32_t signature_struct_offset)
1705acaca2fSWilliam A. Kennington III {
1715acaca2fSWilliam A. Kennington III BUILD_ASSERT((offsetof(struct signature_rsa2048_pkcs15, modulus) ==
1725acaca2fSWilliam A. Kennington III SIGNATURE_OFFSET &&
1735acaca2fSWilliam A. Kennington III offsetof(struct signature_rsa3072_pkcs15, modulus) ==
1745acaca2fSWilliam A. Kennington III SIGNATURE_OFFSET &&
1755acaca2fSWilliam A. Kennington III offsetof(struct signature_rsa4096_pkcs15, modulus) ==
1765acaca2fSWilliam A. Kennington III SIGNATURE_OFFSET));
1775acaca2fSWilliam A. Kennington III
1785acaca2fSWilliam A. Kennington III // Read up to the modulus.
1795acaca2fSWilliam A. Kennington III enum
1805acaca2fSWilliam A. Kennington III {
1815acaca2fSWilliam A. Kennington III read_len = SIGNATURE_OFFSET
1825acaca2fSWilliam A. Kennington III };
1835acaca2fSWilliam A. Kennington III uint8_t buffer[read_len];
1845acaca2fSWilliam A. Kennington III int rv;
1855acaca2fSWilliam A. Kennington III rv = intf->read(ctx, signature_struct_offset, read_len, buffer);
1865acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
1875acaca2fSWilliam A. Kennington III {
188dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read signature struct\n", __FUNCTION__);
1895acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
1905acaca2fSWilliam A. Kennington III }
19112e6ad0dSWilliam A. Kennington III if (*(uint32_t*)buffer != SIGNATURE_MAGIC)
1925acaca2fSWilliam A. Kennington III {
193dca92e47SWilly Tu CPRINTS(ctx, "%s: bad signature magic\n", __FUNCTION__);
1945acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
1955acaca2fSWilliam A. Kennington III }
1965acaca2fSWilliam A. Kennington III
1975acaca2fSWilliam A. Kennington III if (ctx->descriptor.image_family != ctx->current_image_family &&
1985acaca2fSWilliam A. Kennington III ctx->descriptor.image_family != IMAGE_FAMILY_ALL &&
1995acaca2fSWilliam A. Kennington III ctx->current_image_family != IMAGE_FAMILY_ALL)
2005acaca2fSWilliam A. Kennington III {
201dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image family\n", __FUNCTION__);
2025acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY;
2035acaca2fSWilliam A. Kennington III }
2045acaca2fSWilliam A. Kennington III
205d2bcdd5cSWilly Tu if (intf->is_production_mode == NULL)
2065acaca2fSWilliam A. Kennington III {
207dca92e47SWilly Tu CPRINTS(ctx, "%s: missing is_production_mode\n", __FUNCTION__);
2085acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
2095acaca2fSWilliam A. Kennington III }
2106084957fSPatrick Williams if (intf->is_production_mode() && (ctx->descriptor.image_type == IMAGE_DEV))
2115acaca2fSWilliam A. Kennington III {
212dca92e47SWilly Tu CPRINTS(ctx, "%s: checking exemption allowlist\n", __FUNCTION__);
2135acaca2fSWilliam A. Kennington III
214d2bcdd5cSWilly Tu // If function is NULL or if the function call return false, return
215d2bcdd5cSWilly Tu // error
216d2bcdd5cSWilly Tu if (intf->prod_to_dev_downgrade_allowed == NULL ||
217d2bcdd5cSWilly Tu !intf->prod_to_dev_downgrade_allowed())
2185acaca2fSWilliam A. Kennington III {
219dca92e47SWilly Tu CPRINTS(ctx, "%s: illegal image type\n", __FUNCTION__);
2205acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED;
2215acaca2fSWilliam A. Kennington III }
2225acaca2fSWilliam A. Kennington III }
2235acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
2245acaca2fSWilliam A. Kennington III }
2255acaca2fSWilliam A. Kennington III
226dca92e47SWilly Tu // If caller had provided read_and_hash_update call that, otherwise call read
227dca92e47SWilly Tu // and then update.
2285acaca2fSWilliam A. Kennington III
read_and_hash_update(const struct libcr51sign_ctx * ctx,const struct libcr51sign_intf * intf,uint32_t offset,uint32_t size)2296084957fSPatrick Williams static failure_reason read_and_hash_update(const struct libcr51sign_ctx* ctx,
2305acaca2fSWilliam A. Kennington III const struct libcr51sign_intf* intf,
2315acaca2fSWilliam A. Kennington III uint32_t offset, uint32_t size)
2325acaca2fSWilliam A. Kennington III {
2335acaca2fSWilliam A. Kennington III uint8_t read_buffer[MAX_READ_SIZE];
2345acaca2fSWilliam A. Kennington III int rv;
2355acaca2fSWilliam A. Kennington III int read_size;
2365acaca2fSWilliam A. Kennington III
2375acaca2fSWilliam A. Kennington III if (intf->read_and_hash_update)
2385acaca2fSWilliam A. Kennington III {
2395acaca2fSWilliam A. Kennington III rv = intf->read_and_hash_update((void*)ctx, offset, size);
2405acaca2fSWilliam A. Kennington III }
2415acaca2fSWilliam A. Kennington III else
2425acaca2fSWilliam A. Kennington III {
2435acaca2fSWilliam A. Kennington III if (!intf->hash_update)
2445acaca2fSWilliam A. Kennington III {
245dca92e47SWilly Tu CPRINTS(ctx, "%s: missing hash_update\n", __FUNCTION__);
2465acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
2475acaca2fSWilliam A. Kennington III }
2485acaca2fSWilliam A. Kennington III do
2495acaca2fSWilliam A. Kennington III {
2505acaca2fSWilliam A. Kennington III read_size = size < MAX_READ_SIZE ? size : MAX_READ_SIZE;
2515acaca2fSWilliam A. Kennington III rv = intf->read((void*)ctx, offset, read_size, read_buffer);
2525acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
2535acaca2fSWilliam A. Kennington III {
2545acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
2555acaca2fSWilliam A. Kennington III }
2565acaca2fSWilliam A. Kennington III rv = intf->hash_update((void*)ctx, read_buffer, read_size);
2575acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
2585acaca2fSWilliam A. Kennington III {
2595acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
2605acaca2fSWilliam A. Kennington III }
2615acaca2fSWilliam A. Kennington III offset += read_size;
2625acaca2fSWilliam A. Kennington III size -= read_size;
2635acaca2fSWilliam A. Kennington III } while (size > 0);
2645acaca2fSWilliam A. Kennington III }
2655acaca2fSWilliam A. Kennington III return rv;
2665acaca2fSWilliam A. Kennington III }
2675acaca2fSWilliam A. Kennington III
2685acaca2fSWilliam A. Kennington III // Validates the image_region array, namely that:
2695acaca2fSWilliam A. Kennington III // - The regions are aligned, contiguous & exhaustive
2705acaca2fSWilliam A. Kennington III // - That the image descriptor resides in a static region
2715acaca2fSWilliam A. Kennington III //
2725acaca2fSWilliam A. Kennington III // If the array is consistent, proceeds to hash the static regions and
2735acaca2fSWilliam A. Kennington III // validates the hash. d_offset is the absolute image descriptor offset
2745acaca2fSWilliam A. Kennington III
validate_payload_regions(const struct libcr51sign_ctx * ctx,struct libcr51sign_intf * intf,uint32_t d_offset,struct libcr51sign_validated_regions * image_regions)2755acaca2fSWilliam A. Kennington III static failure_reason validate_payload_regions(
2765acaca2fSWilliam A. Kennington III const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
2775acaca2fSWilliam A. Kennington III uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
2785acaca2fSWilliam A. Kennington III {
2795acaca2fSWilliam A. Kennington III // Allocate buffer to accomodate largest supported hash-type(SHA512)
2805acaca2fSWilliam A. Kennington III uint8_t magic_and_digest[MEMBER_SIZE(struct hash_sha512, hash_magic) +
2815acaca2fSWilliam A. Kennington III LIBCR51SIGN_SHA512_DIGEST_SIZE];
2825acaca2fSWilliam A. Kennington III uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
2835acaca2fSWilliam A. Kennington III uint32_t byte_count, region_count, image_size, hash_offset, digest_size;
284deb5501aSWilliam A. Kennington III uint32_t i;
2855acaca2fSWilliam A. Kennington III uint8_t d_region_num = 0;
286deb5501aSWilliam A. Kennington III int rv;
287dca92e47SWilly Tu struct image_region const* region;
2885acaca2fSWilliam A. Kennington III
2895acaca2fSWilliam A. Kennington III if (image_regions == NULL)
2905acaca2fSWilliam A. Kennington III {
291dca92e47SWilly Tu CPRINTS(ctx, "%s: Missing image region input\n", __FUNCTION__);
2925acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_REGION_INPUT;
2935acaca2fSWilliam A. Kennington III }
2945acaca2fSWilliam A. Kennington III
2955acaca2fSWilliam A. Kennington III BUILD_ASSERT((MEMBER_SIZE(struct hash_sha256, hash_magic) ==
2965acaca2fSWilliam A. Kennington III MEMBER_SIZE(struct hash_sha512, hash_magic)));
2975acaca2fSWilliam A. Kennington III image_size = ctx->descriptor.image_size;
2985acaca2fSWilliam A. Kennington III region_count = ctx->descriptor.region_count;
2995acaca2fSWilliam A. Kennington III hash_offset = d_offset + sizeof(struct image_descriptor) +
3005acaca2fSWilliam A. Kennington III region_count * sizeof(struct image_region);
3015acaca2fSWilliam A. Kennington III // Read the image_region array.
3025acaca2fSWilliam A. Kennington III
3035acaca2fSWilliam A. Kennington III if (region_count > ARRAY_SIZE(image_regions->image_regions))
3045acaca2fSWilliam A. Kennington III {
305dca92e47SWilly Tu CPRINTS(ctx,
306dca92e47SWilly Tu "%s: ctx->descriptor.region_count is greater "
307dca92e47SWilly Tu "than LIBCR51SIGN_MAX_REGION_COUNT\n",
308dca92e47SWilly Tu __FUNCTION__);
3095acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_REGION_SIZE;
3105acaca2fSWilliam A. Kennington III }
3115acaca2fSWilliam A. Kennington III
312deb5501aSWilliam A. Kennington III rv = intf->read(ctx, d_offset + sizeof(struct image_descriptor),
3135acaca2fSWilliam A. Kennington III region_count * sizeof(struct image_region),
3145acaca2fSWilliam A. Kennington III (uint8_t*)&image_regions->image_regions);
3155acaca2fSWilliam A. Kennington III
3165acaca2fSWilliam A. Kennington III image_regions->region_count = region_count;
3175acaca2fSWilliam A. Kennington III
3185acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
3195acaca2fSWilliam A. Kennington III {
320dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read region array\n", __FUNCTION__);
3215acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
3225acaca2fSWilliam A. Kennington III }
3235acaca2fSWilliam A. Kennington III
3245acaca2fSWilliam A. Kennington III // Validate that the regions are contiguous & exhaustive.
3255acaca2fSWilliam A. Kennington III for (i = 0, byte_count = 0; i < region_count; i++)
3265acaca2fSWilliam A. Kennington III {
3275acaca2fSWilliam A. Kennington III region = image_regions->image_regions + i;
3285acaca2fSWilliam A. Kennington III
329dca92e47SWilly Tu CPRINTS(ctx, "%s: region #%d \"%s\" (%x - %x)\n", __FUNCTION__, i,
330dca92e47SWilly Tu (const char*)region->region_name, region->region_offset,
3315acaca2fSWilliam A. Kennington III region->region_offset + region->region_size);
3325acaca2fSWilliam A. Kennington III if ((region->region_offset % IMAGE_REGION_ALIGNMENT) != 0 ||
3335acaca2fSWilliam A. Kennington III (region->region_size % IMAGE_REGION_ALIGNMENT) != 0)
3345acaca2fSWilliam A. Kennington III {
335dca92e47SWilly Tu CPRINTS(ctx, "%s: regions must be sector aligned\n", __FUNCTION__);
3365acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3375acaca2fSWilliam A. Kennington III }
3385acaca2fSWilliam A. Kennington III if (region->region_offset != byte_count ||
3395acaca2fSWilliam A. Kennington III region->region_size > image_size - byte_count)
3405acaca2fSWilliam A. Kennington III {
341dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid region array\n", __FUNCTION__);
3425acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3435acaca2fSWilliam A. Kennington III }
3445acaca2fSWilliam A. Kennington III byte_count += region->region_size;
3455acaca2fSWilliam A. Kennington III // The image descriptor must be part of a static region.
3465acaca2fSWilliam A. Kennington III if (d_offset >= region->region_offset && d_offset < byte_count)
3475acaca2fSWilliam A. Kennington III {
3485acaca2fSWilliam A. Kennington III d_region_num = i;
349dca92e47SWilly Tu CPRINTS(ctx, "%s: image descriptor in region %d\n", __FUNCTION__,
3505acaca2fSWilliam A. Kennington III i);
3515acaca2fSWilliam A. Kennington III // The descriptor can't span regions.
352dca92e47SWilly Tu if ((ctx->descriptor.descriptor_area_size >
353dca92e47SWilly Tu (byte_count - d_offset)) ||
3545acaca2fSWilliam A. Kennington III !(region->region_attributes & IMAGE_REGION_STATIC))
3555acaca2fSWilliam A. Kennington III {
3566084957fSPatrick Williams CPRINTS(ctx,
357dca92e47SWilly Tu "%s: descriptor must reside in "
358dca92e47SWilly Tu "static region\n",
359dca92e47SWilly Tu __FUNCTION__);
3605acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3615acaca2fSWilliam A. Kennington III }
3625acaca2fSWilliam A. Kennington III }
3635acaca2fSWilliam A. Kennington III }
3645acaca2fSWilliam A. Kennington III if (byte_count != image_size)
3655acaca2fSWilliam A. Kennington III {
366dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image size\n", __FUNCTION__);
3675acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3685acaca2fSWilliam A. Kennington III }
3695acaca2fSWilliam A. Kennington III
3705acaca2fSWilliam A. Kennington III rv = get_hash_digest_size(ctx->descriptor.hash_type, &digest_size);
3715acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
3725acaca2fSWilliam A. Kennington III {
3735acaca2fSWilliam A. Kennington III return rv;
3745acaca2fSWilliam A. Kennington III }
3755acaca2fSWilliam A. Kennington III
3765acaca2fSWilliam A. Kennington III rv = intf->read(ctx, hash_offset,
3776084957fSPatrick Williams MEMBER_SIZE(struct hash_sha256, hash_magic) + digest_size,
3785acaca2fSWilliam A. Kennington III magic_and_digest);
3795acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
3805acaca2fSWilliam A. Kennington III {
381dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read hash from flash\n", __FUNCTION__);
3825acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
3835acaca2fSWilliam A. Kennington III }
3845acaca2fSWilliam A. Kennington III if (*(uint32_t*)magic_and_digest != HASH_MAGIC)
3855acaca2fSWilliam A. Kennington III {
386dca92e47SWilly Tu CPRINTS(ctx, "%s: bad hash magic\n", __FUNCTION__);
3875acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
3885acaca2fSWilliam A. Kennington III }
3895acaca2fSWilliam A. Kennington III rv = intf->hash_init(ctx, ctx->descriptor.hash_type);
3905acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
3915acaca2fSWilliam A. Kennington III {
392dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_init failed\n", __FUNCTION__);
3935acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
3945acaca2fSWilliam A. Kennington III }
3955acaca2fSWilliam A. Kennington III for (i = 0; i < region_count; i++)
3965acaca2fSWilliam A. Kennington III {
3975acaca2fSWilliam A. Kennington III uint32_t hash_start, hash_size;
3985acaca2fSWilliam A. Kennington III region = image_regions->image_regions + i;
3995acaca2fSWilliam A. Kennington III
4005acaca2fSWilliam A. Kennington III if (!(region->region_attributes & IMAGE_REGION_STATIC))
4015acaca2fSWilliam A. Kennington III {
4025acaca2fSWilliam A. Kennington III continue;
4035acaca2fSWilliam A. Kennington III }
4045acaca2fSWilliam A. Kennington III hash_start = region->region_offset;
4055acaca2fSWilliam A. Kennington III hash_size = region->region_size;
4065acaca2fSWilliam A. Kennington III
4075acaca2fSWilliam A. Kennington III // Skip the descriptor.
4085acaca2fSWilliam A. Kennington III do
4095acaca2fSWilliam A. Kennington III {
4105acaca2fSWilliam A. Kennington III if (i == d_region_num)
4115acaca2fSWilliam A. Kennington III {
4125acaca2fSWilliam A. Kennington III hash_size = d_offset - hash_start;
4135acaca2fSWilliam A. Kennington III if (!hash_size)
4145acaca2fSWilliam A. Kennington III {
4155acaca2fSWilliam A. Kennington III hash_start += ctx->descriptor.descriptor_area_size;
416dca92e47SWilly Tu hash_size = (region->region_offset + region->region_size -
417dca92e47SWilly Tu hash_start);
4185acaca2fSWilliam A. Kennington III }
419dca92e47SWilly Tu }
420dca92e47SWilly Tu
421dca92e47SWilly Tu CPRINTS(ctx, "%s: hashing %s (%x - %x)\n", __FUNCTION__,
422deb5501aSWilliam A. Kennington III (const char*)region->region_name, hash_start,
4235acaca2fSWilliam A. Kennington III hash_start + hash_size);
4245acaca2fSWilliam A. Kennington III // Read the image_region array.
4255acaca2fSWilliam A. Kennington III rv = read_and_hash_update(ctx, intf, hash_start, hash_size);
4265acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
4275acaca2fSWilliam A. Kennington III {
4285acaca2fSWilliam A. Kennington III return rv;
4295acaca2fSWilliam A. Kennington III }
4305acaca2fSWilliam A. Kennington III hash_start += hash_size;
4315acaca2fSWilliam A. Kennington III } while (hash_start != region->region_offset + region->region_size);
4325acaca2fSWilliam A. Kennington III }
4335acaca2fSWilliam A. Kennington III rv = intf->hash_final((void*)ctx, (uint8_t*)dcrypto_digest);
4345acaca2fSWilliam A. Kennington III
4355acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
4365acaca2fSWilliam A. Kennington III {
4375acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
4385acaca2fSWilliam A. Kennington III }
4395acaca2fSWilliam A. Kennington III
4406084957fSPatrick Williams if (memcmp(magic_and_digest + MEMBER_SIZE(struct hash_sha256, hash_magic),
4415acaca2fSWilliam A. Kennington III dcrypto_digest, digest_size))
4425acaca2fSWilliam A. Kennington III {
443dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid hash\n", __FUNCTION__);
4445acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH;
4455acaca2fSWilliam A. Kennington III }
4465acaca2fSWilliam A. Kennington III // Image is valid.
4475acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
4485acaca2fSWilliam A. Kennington III }
4495acaca2fSWilliam A. Kennington III
4505acaca2fSWilliam A. Kennington III // Create empty image_regions to pass to validate_payload_regions
451dca92e47SWilly Tu // Support validate_payload_regions_helper to remove image_regions as a required
452dca92e47SWilly Tu // input.
4535acaca2fSWilliam A. Kennington III
allocate_and_validate_payload_regions(const struct libcr51sign_ctx * ctx,struct libcr51sign_intf * intf,uint32_t d_offset)454*c66ebc35SPatrick Williams static failure_reason allocate_and_validate_payload_regions(
455*c66ebc35SPatrick Williams const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
4565acaca2fSWilliam A. Kennington III uint32_t d_offset)
4575acaca2fSWilliam A. Kennington III {
4585acaca2fSWilliam A. Kennington III struct libcr51sign_validated_regions image_regions;
4595acaca2fSWilliam A. Kennington III return validate_payload_regions(ctx, intf, d_offset, &image_regions);
4605acaca2fSWilliam A. Kennington III }
4615acaca2fSWilliam A. Kennington III
462dca92e47SWilly Tu // Wrapper around validate_payload_regions to allow nullptr for image_regions.
463dca92e47SWilly Tu // Calls allocate_and_validate_payload_regions when image_regions is nullptr to
464dca92e47SWilly Tu // create placer holder image_regions.
4655acaca2fSWilliam A. Kennington III
validate_payload_regions_helper(const struct libcr51sign_ctx * ctx,struct libcr51sign_intf * intf,uint32_t d_offset,struct libcr51sign_validated_regions * image_regions)4665acaca2fSWilliam A. Kennington III static failure_reason validate_payload_regions_helper(
4675acaca2fSWilliam A. Kennington III const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
4685acaca2fSWilliam A. Kennington III uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
4695acaca2fSWilliam A. Kennington III {
4705acaca2fSWilliam A. Kennington III if (image_regions)
4715acaca2fSWilliam A. Kennington III {
4725acaca2fSWilliam A. Kennington III return validate_payload_regions(ctx, intf, d_offset, image_regions);
4735acaca2fSWilliam A. Kennington III }
4745acaca2fSWilliam A. Kennington III
4755acaca2fSWilliam A. Kennington III return allocate_and_validate_payload_regions(ctx, intf, d_offset);
4765acaca2fSWilliam A. Kennington III }
4775acaca2fSWilliam A. Kennington III
4785acaca2fSWilliam A. Kennington III // Check if the given signature_scheme is supported.
4795acaca2fSWilliam A. Kennington III // Returns nonzero on error, zero on success
4805acaca2fSWilliam A. Kennington III
4815acaca2fSWilliam A. Kennington III static failure_reason
is_signature_scheme_supported(enum signature_scheme scheme)4825acaca2fSWilliam A. Kennington III is_signature_scheme_supported(enum signature_scheme scheme)
4835acaca2fSWilliam A. Kennington III {
4845acaca2fSWilliam A. Kennington III switch (scheme)
4855acaca2fSWilliam A. Kennington III {
4865acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15:
4875acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15:
4885acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15:
4895acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512:
4905acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
4915acaca2fSWilliam A. Kennington III default:
4925acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
4935acaca2fSWilliam A. Kennington III }
4945acaca2fSWilliam A. Kennington III }
4955acaca2fSWilliam A. Kennington III
4965acaca2fSWilliam A. Kennington III // Returns size of signature struct size in |size|
4975acaca2fSWilliam A. Kennington III // Returns nonzero on error, zero on success
4985acaca2fSWilliam A. Kennington III
499*c66ebc35SPatrick Williams static failure_reason
get_signature_struct_size(enum signature_scheme scheme,uint32_t * size)500*c66ebc35SPatrick Williams get_signature_struct_size(enum signature_scheme scheme, uint32_t* size)
5015acaca2fSWilliam A. Kennington III {
5025acaca2fSWilliam A. Kennington III switch (scheme)
5035acaca2fSWilliam A. Kennington III {
5045acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15:
5055acaca2fSWilliam A. Kennington III *size = sizeof(struct signature_rsa2048_pkcs15);
5065acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
5075acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15:
5085acaca2fSWilliam A. Kennington III *size = sizeof(struct signature_rsa3072_pkcs15);
5095acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
5105acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15:
5115acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512:
5125acaca2fSWilliam A. Kennington III *size = sizeof(struct signature_rsa4096_pkcs15);
5135acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
5145acaca2fSWilliam A. Kennington III default:
5155acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
5165acaca2fSWilliam A. Kennington III }
5175acaca2fSWilliam A. Kennington III }
5185acaca2fSWilliam A. Kennington III
519*c66ebc35SPatrick Williams static failure_reason
get_signature_field_offset(enum signature_scheme scheme,uint32_t * offset)520*c66ebc35SPatrick Williams get_signature_field_offset(enum signature_scheme scheme, uint32_t* offset)
5215acaca2fSWilliam A. Kennington III {
5225acaca2fSWilliam A. Kennington III switch (scheme)
5235acaca2fSWilliam A. Kennington III {
5245acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15:
5255acaca2fSWilliam A. Kennington III *offset = offsetof(struct signature_rsa2048_pkcs15, signature);
5265acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
5275acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15:
5285acaca2fSWilliam A. Kennington III *offset = offsetof(struct signature_rsa3072_pkcs15, signature);
5295acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
5305acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15:
5315acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512:
5325acaca2fSWilliam A. Kennington III *offset = offsetof(struct signature_rsa4096_pkcs15, signature);
5335acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
5345acaca2fSWilliam A. Kennington III default:
5355acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
5365acaca2fSWilliam A. Kennington III }
5375acaca2fSWilliam A. Kennington III }
5385acaca2fSWilliam A. Kennington III
5395acaca2fSWilliam A. Kennington III // Validates the signature (of type scheme) read from "device" at
5405acaca2fSWilliam A. Kennington III //"raw_signature_offset" with "public_key" over a SHA256/SHA512 digest of
5415acaca2fSWilliam A. Kennington III // EEPROM area "data_offset:data_size".
5425acaca2fSWilliam A. Kennington III
validate_signature(const struct libcr51sign_ctx * ctx,const struct libcr51sign_intf * intf,uint32_t data_offset,uint32_t data_size,enum signature_scheme scheme,uint32_t raw_signature_offset)543*c66ebc35SPatrick Williams static failure_reason validate_signature(
544*c66ebc35SPatrick Williams const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
545*c66ebc35SPatrick Williams uint32_t data_offset, uint32_t data_size, enum signature_scheme scheme,
5465acaca2fSWilliam A. Kennington III uint32_t raw_signature_offset)
5475acaca2fSWilliam A. Kennington III {
5485acaca2fSWilliam A. Kennington III uint8_t signature[LIBCR51SIGN_MAX_SIGNATURE_SIZE];
5495acaca2fSWilliam A. Kennington III uint16_t key_size;
5505acaca2fSWilliam A. Kennington III uint32_t digest_size;
5515acaca2fSWilliam A. Kennington III uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
5525acaca2fSWilliam A. Kennington III int rv;
5535acaca2fSWilliam A. Kennington III enum hash_type hash_type;
5545acaca2fSWilliam A. Kennington III
5555acaca2fSWilliam A. Kennington III if (!intf->hash_init)
5565acaca2fSWilliam A. Kennington III {
557dca92e47SWilly Tu CPRINTS(ctx, "%s: missing hash_init\n", __FUNCTION__);
5585acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
5595acaca2fSWilliam A. Kennington III }
5605acaca2fSWilliam A. Kennington III rv = get_hash_type_from_signature(scheme, &hash_type);
5615acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
5625acaca2fSWilliam A. Kennington III {
563dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_type from signature failed\n", __FUNCTION__);
5645acaca2fSWilliam A. Kennington III return rv;
5655acaca2fSWilliam A. Kennington III }
5665acaca2fSWilliam A. Kennington III rv = intf->hash_init(ctx, hash_type);
5675acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
5685acaca2fSWilliam A. Kennington III {
569dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_init failed\n", __FUNCTION__);
5705acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
5715acaca2fSWilliam A. Kennington III }
5725acaca2fSWilliam A. Kennington III rv = read_and_hash_update(ctx, intf, data_offset, data_size);
5735acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
5745acaca2fSWilliam A. Kennington III {
575dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_update failed\n", __FUNCTION__);
5765acaca2fSWilliam A. Kennington III return rv;
5775acaca2fSWilliam A. Kennington III }
5785acaca2fSWilliam A. Kennington III if (!intf->hash_final)
5795acaca2fSWilliam A. Kennington III {
580dca92e47SWilly Tu CPRINTS(ctx, "%s: missing hash_final\n", __FUNCTION__);
5815acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
5825acaca2fSWilliam A. Kennington III }
5835acaca2fSWilliam A. Kennington III rv = intf->hash_final((void*)ctx, dcrypto_digest);
5845acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
5855acaca2fSWilliam A. Kennington III {
586dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_final failed (status = %d)\n", __FUNCTION__, rv);
5875acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
5885acaca2fSWilliam A. Kennington III }
5895acaca2fSWilliam A. Kennington III rv = get_key_size(scheme, &key_size);
5905acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
5915acaca2fSWilliam A. Kennington III {
5925acaca2fSWilliam A. Kennington III return rv;
5935acaca2fSWilliam A. Kennington III }
5945acaca2fSWilliam A. Kennington III
5955acaca2fSWilliam A. Kennington III rv = intf->read(ctx, raw_signature_offset, key_size, signature);
5965acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
5975acaca2fSWilliam A. Kennington III {
598dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read signature (status = %d)\n",
599dca92e47SWilly Tu __FUNCTION__, rv);
6005acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
6015acaca2fSWilliam A. Kennington III }
6025acaca2fSWilliam A. Kennington III if (!intf->verify_signature)
6035acaca2fSWilliam A. Kennington III {
604dca92e47SWilly Tu CPRINTS(ctx, "%s: missing verify_signature\n", __FUNCTION__);
6055acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
6065acaca2fSWilliam A. Kennington III }
6075acaca2fSWilliam A. Kennington III rv = get_hash_digest_size(hash_type, &digest_size);
6085acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
6095acaca2fSWilliam A. Kennington III {
6105acaca2fSWilliam A. Kennington III return rv;
6115acaca2fSWilliam A. Kennington III }
6125acaca2fSWilliam A. Kennington III rv = intf->verify_signature(ctx, scheme, signature, key_size,
6135acaca2fSWilliam A. Kennington III dcrypto_digest, digest_size);
6145acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
6155acaca2fSWilliam A. Kennington III {
616dca92e47SWilly Tu CPRINTS(ctx, "%s: verification failed (status = %d)\n", __FUNCTION__,
6175acaca2fSWilliam A. Kennington III rv);
6185acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIGNATURE;
6195acaca2fSWilliam A. Kennington III }
620dca92e47SWilly Tu CPRINTS(ctx, "%s: verification succeeded\n", __FUNCTION__);
6215acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
6225acaca2fSWilliam A. Kennington III }
6235acaca2fSWilliam A. Kennington III
6245acaca2fSWilliam A. Kennington III // Sanity checks the image descriptor & validates its signature.
6255acaca2fSWilliam A. Kennington III // This function does not validate the image_region array or image hash.
6265acaca2fSWilliam A. Kennington III //
6275acaca2fSWilliam A. Kennington III //@param[in] ctx context which describes the image and holds opaque private
6285acaca2fSWilliam A. Kennington III // data for the user of the library
6295acaca2fSWilliam A. Kennington III //@param[in] intf function pointers which interface to the current system
6305acaca2fSWilliam A. Kennington III // and environment
6315acaca2fSWilliam A. Kennington III //@param offset Absolute image descriptor flash offset.
6325acaca2fSWilliam A. Kennington III //@param relative_offset Image descriptor offset relative to image start.
633af46bea6SWilliam A. Kennington III //@param max_size Maximum size of the flash space in bytes.
634dca92e47SWilly Tu //@param[out] payload_blob_offset Absolute offset of BLOB data in image
635dca92e47SWilly Tu // descriptor (if BLOB data is present)
validate_descriptor(const struct libcr51sign_ctx * ctx,const struct libcr51sign_intf * intf,uint32_t offset,uint32_t relative_offset,uint32_t max_size,uint32_t * const restrict payload_blob_offset)636*c66ebc35SPatrick Williams static failure_reason validate_descriptor(
637*c66ebc35SPatrick Williams const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
638*c66ebc35SPatrick Williams uint32_t offset, uint32_t relative_offset, uint32_t max_size,
639dca92e47SWilly Tu uint32_t* const restrict payload_blob_offset)
6405acaca2fSWilliam A. Kennington III {
6415acaca2fSWilliam A. Kennington III uint32_t max_descriptor_size, signed_size, signature_scheme,
6425acaca2fSWilliam A. Kennington III signature_offset;
6436084957fSPatrick Williams uint32_t signature_struct_offset, signature_struct_size, hash_struct_size;
6445acaca2fSWilliam A. Kennington III int rv;
6455acaca2fSWilliam A. Kennington III
646af46bea6SWilliam A. Kennington III max_descriptor_size = max_size - relative_offset;
647af46bea6SWilliam A. Kennington III if (max_size < relative_offset ||
6485acaca2fSWilliam A. Kennington III max_descriptor_size < sizeof(struct image_descriptor))
6495acaca2fSWilliam A. Kennington III {
650dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid arguments\n", __FUNCTION__);
6515acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
6525acaca2fSWilliam A. Kennington III }
6535acaca2fSWilliam A. Kennington III
6545acaca2fSWilliam A. Kennington III rv = intf->read(ctx, offset, sizeof(ctx->descriptor),
6555acaca2fSWilliam A. Kennington III (uint8_t*)&ctx->descriptor);
6565acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
6575acaca2fSWilliam A. Kennington III {
658dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read descriptor\n", __FUNCTION__);
6595acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
6605acaca2fSWilliam A. Kennington III }
6615acaca2fSWilliam A. Kennington III if (ctx->descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
6625acaca2fSWilliam A. Kennington III ctx->descriptor.descriptor_offset != relative_offset ||
6635acaca2fSWilliam A. Kennington III ctx->descriptor.region_count == 0 ||
6645acaca2fSWilliam A. Kennington III ctx->descriptor.descriptor_area_size > max_descriptor_size ||
665af46bea6SWilliam A. Kennington III ctx->descriptor.image_size > max_size)
6665acaca2fSWilliam A. Kennington III {
667dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid descriptor\n", __FUNCTION__);
668af46bea6SWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
669af46bea6SWilliam A. Kennington III }
670af46bea6SWilliam A. Kennington III if (intf->image_size_valid == NULL)
671af46bea6SWilliam A. Kennington III {
672dca92e47SWilly Tu // Preserve original behavior of requiring exact image_size match if no
673dca92e47SWilly Tu // operator is provided.
674af46bea6SWilliam A. Kennington III if (ctx->descriptor.image_size != max_size)
675af46bea6SWilliam A. Kennington III {
676dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image size\n", __FUNCTION__);
677af46bea6SWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
678af46bea6SWilliam A. Kennington III }
679af46bea6SWilliam A. Kennington III }
680af46bea6SWilliam A. Kennington III else if (!intf->image_size_valid(ctx->descriptor.image_size))
681af46bea6SWilliam A. Kennington III {
682dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image size\n", __FUNCTION__);
6835acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
6845acaca2fSWilliam A. Kennington III }
6855acaca2fSWilliam A. Kennington III if (ctx->descriptor.image_type != IMAGE_DEV &&
6865acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_PROD &&
6875acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_BREAKOUT &&
6885acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_TEST &&
6895acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_UNSIGNED_INTEGRITY)
6905acaca2fSWilliam A. Kennington III {
691dca92e47SWilly Tu CPRINTS(ctx, "%s: bad image type\n", __FUNCTION__);
6925acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
6935acaca2fSWilliam A. Kennington III }
6945acaca2fSWilliam A. Kennington III // Although the image_descriptor struct supports unauthenticated
6955acaca2fSWilliam A. Kennington III // images, Haven will not allow it.
6965acaca2fSWilliam A. Kennington III // Haven only supports SHA256 + RSA2048/RSA3072_PKCS15 currently.
6975acaca2fSWilliam A. Kennington III
6985acaca2fSWilliam A. Kennington III signature_scheme = ctx->descriptor.signature_scheme;
6995acaca2fSWilliam A. Kennington III
7005acaca2fSWilliam A. Kennington III rv = is_signature_scheme_supported(signature_scheme);
7015acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
7025acaca2fSWilliam A. Kennington III {
7035acaca2fSWilliam A. Kennington III return rv;
7045acaca2fSWilliam A. Kennington III }
7055acaca2fSWilliam A. Kennington III rv = is_hash_type_supported(ctx->descriptor.hash_type);
7065acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
7075acaca2fSWilliam A. Kennington III {
708dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid hash type\n", __FUNCTION__);
7095acaca2fSWilliam A. Kennington III return rv;
7105acaca2fSWilliam A. Kennington III }
7115acaca2fSWilliam A. Kennington III if (ctx->descriptor.descriptor_major > MAX_MAJOR_VERSION ||
7125acaca2fSWilliam A. Kennington III ctx->descriptor.region_count > LIBCR51SIGN_MAX_REGION_COUNT)
7135acaca2fSWilliam A. Kennington III {
714dca92e47SWilly Tu CPRINTS(ctx, "%s: unsupported descriptor\n", __FUNCTION__);
7155acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR;
7165acaca2fSWilliam A. Kennington III }
7176084957fSPatrick Williams rv = get_signature_struct_size(signature_scheme, &signature_struct_size);
7185acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
7195acaca2fSWilliam A. Kennington III {
7205acaca2fSWilliam A. Kennington III return rv;
7215acaca2fSWilliam A. Kennington III }
7225acaca2fSWilliam A. Kennington III
7235acaca2fSWilliam A. Kennington III // Compute the size of the signed portion of the image descriptor.
7242be45238SPatrick Williams signed_size = sizeof(struct image_descriptor) +
7256084957fSPatrick Williams ctx->descriptor.region_count * sizeof(struct image_region);
7265acaca2fSWilliam A. Kennington III rv = get_hash_struct_size(ctx->descriptor.hash_type, &hash_struct_size);
7275acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
7285acaca2fSWilliam A. Kennington III {
7295acaca2fSWilliam A. Kennington III return rv;
7305acaca2fSWilliam A. Kennington III }
7315acaca2fSWilliam A. Kennington III signed_size += hash_struct_size;
7325acaca2fSWilliam A. Kennington III if (ctx->descriptor.denylist_size)
7335acaca2fSWilliam A. Kennington III {
7345acaca2fSWilliam A. Kennington III signed_size += sizeof(struct denylist);
7352be45238SPatrick Williams signed_size += ctx->descriptor.denylist_size *
7362be45238SPatrick Williams sizeof(struct denylist_record);
7375acaca2fSWilliam A. Kennington III }
7385acaca2fSWilliam A. Kennington III if (ctx->descriptor.blob_size)
7395acaca2fSWilliam A. Kennington III {
740dca92e47SWilly Tu *payload_blob_offset = offset + signed_size;
7415acaca2fSWilliam A. Kennington III signed_size += sizeof(struct blob);
7425acaca2fSWilliam A. Kennington III // Previous additions are guaranteed not to overflow.
743dca92e47SWilly Tu if ((ctx->descriptor.blob_size >
744dca92e47SWilly Tu ctx->descriptor.descriptor_area_size - signed_size) ||
745dca92e47SWilly Tu // Sanity check blob size
746dca92e47SWilly Tu (ctx->descriptor.blob_size < sizeof(struct blob_data)))
7475acaca2fSWilliam A. Kennington III {
748dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid blob size (0x%x)\n", __FUNCTION__,
7495acaca2fSWilliam A. Kennington III ctx->descriptor.blob_size);
7505acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
7515acaca2fSWilliam A. Kennington III }
7525acaca2fSWilliam A. Kennington III signed_size += ctx->descriptor.blob_size;
7535acaca2fSWilliam A. Kennington III }
7545acaca2fSWilliam A. Kennington III if (signature_struct_size >
7555acaca2fSWilliam A. Kennington III ctx->descriptor.descriptor_area_size - signed_size)
7565acaca2fSWilliam A. Kennington III {
7575acaca2fSWilliam A. Kennington III CPRINTS(ctx,
758dca92e47SWilly Tu "%s: invalid descriptor area size "
759af46bea6SWilliam A. Kennington III "(expected = 0x%x, actual = 0x%x)\n",
760dca92e47SWilly Tu __FUNCTION__, ctx->descriptor.descriptor_area_size,
7615acaca2fSWilliam A. Kennington III signed_size + signature_struct_size);
7625acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
7635acaca2fSWilliam A. Kennington III }
7645acaca2fSWilliam A. Kennington III signature_struct_offset = signed_size;
7655acaca2fSWilliam A. Kennington III // Omit the actual signature.
7665acaca2fSWilliam A. Kennington III rv = get_signature_field_offset(signature_scheme, &signature_offset);
7675acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
7685acaca2fSWilliam A. Kennington III {
7695acaca2fSWilliam A. Kennington III return rv;
7705acaca2fSWilliam A. Kennington III }
7715acaca2fSWilliam A. Kennington III signed_size += signature_offset;
7725acaca2fSWilliam A. Kennington III
7735acaca2fSWilliam A. Kennington III // Lookup key & validate transition.
7745acaca2fSWilliam A. Kennington III rv = validate_transition(ctx, intf, offset + signature_struct_offset);
7755acaca2fSWilliam A. Kennington III
7765acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
7775acaca2fSWilliam A. Kennington III {
7785acaca2fSWilliam A. Kennington III return rv;
7795acaca2fSWilliam A. Kennington III }
7806084957fSPatrick Williams return validate_signature(ctx, intf, offset, signed_size, signature_scheme,
7816084957fSPatrick Williams offset + signed_size);
7825acaca2fSWilliam A. Kennington III }
7835acaca2fSWilliam A. Kennington III
7845acaca2fSWilliam A. Kennington III // Scans the external EEPROM for a magic value at "alignment" boundaries.
7855acaca2fSWilliam A. Kennington III //
7865acaca2fSWilliam A. Kennington III //@param device Handle to the external EEPROM.
7875acaca2fSWilliam A. Kennington III //@param magic 8-byte pattern to search for.
7885acaca2fSWilliam A. Kennington III //@param start_offset Offset to begin searching at.
7895acaca2fSWilliam A. Kennington III //@param limit Exclusive address (e.g. EEPROM size).
7905acaca2fSWilliam A. Kennington III //@param alignment Alignment boundaries (POW2) to search on.
7915acaca2fSWilliam A. Kennington III //@param header_offset Location to place the new header offset.
7925acaca2fSWilliam A. Kennington III //@return LIBCR51SIGN_SUCCESS (or non-zero on error).
7935acaca2fSWilliam A. Kennington III
scan_for_magic_8(const struct libcr51sign_ctx * ctx,const struct libcr51sign_intf * intf,uint64_t magic,uint32_t start_offset,uint32_t limit,uint32_t alignment,uint32_t * header_offset)7945acaca2fSWilliam A. Kennington III int scan_for_magic_8(const struct libcr51sign_ctx* ctx,
7955acaca2fSWilliam A. Kennington III const struct libcr51sign_intf* intf, uint64_t magic,
7966084957fSPatrick Williams uint32_t start_offset, uint32_t limit, uint32_t alignment,
7976084957fSPatrick Williams uint32_t* header_offset)
7985acaca2fSWilliam A. Kennington III {
7995acaca2fSWilliam A. Kennington III uint64_t read_data;
8005acaca2fSWilliam A. Kennington III uint32_t offset;
8015acaca2fSWilliam A. Kennington III int rv;
8025acaca2fSWilliam A. Kennington III
8035acaca2fSWilliam A. Kennington III if (limit <= start_offset || limit > ctx->end_offset ||
8045acaca2fSWilliam A. Kennington III limit < sizeof(magic) || !POWER_OF_TWO(alignment))
8055acaca2fSWilliam A. Kennington III {
8065acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
8075acaca2fSWilliam A. Kennington III }
8085acaca2fSWilliam A. Kennington III
8095acaca2fSWilliam A. Kennington III if (!intf->read)
8105acaca2fSWilliam A. Kennington III {
811dca92e47SWilly Tu CPRINTS(ctx, "%s: missing intf->read\n", __FUNCTION__);
8125acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
8135acaca2fSWilliam A. Kennington III }
8145acaca2fSWilliam A. Kennington III // Align start_offset to the next valid boundary.
8155acaca2fSWilliam A. Kennington III start_offset = ((start_offset - 1) & ~(alignment - 1)) + alignment;
8165acaca2fSWilliam A. Kennington III for (offset = start_offset; offset < limit - sizeof(magic);
8175acaca2fSWilliam A. Kennington III offset += alignment)
8185acaca2fSWilliam A. Kennington III {
8195acaca2fSWilliam A. Kennington III rv = intf->read((void*)ctx, offset, sizeof(read_data),
8205acaca2fSWilliam A. Kennington III (uint8_t*)&read_data);
8215acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
8225acaca2fSWilliam A. Kennington III {
8235acaca2fSWilliam A. Kennington III return rv;
8245acaca2fSWilliam A. Kennington III }
8255acaca2fSWilliam A. Kennington III if (read_data == magic)
8265acaca2fSWilliam A. Kennington III {
8275acaca2fSWilliam A. Kennington III if (header_offset)
8285acaca2fSWilliam A. Kennington III {
8295acaca2fSWilliam A. Kennington III *header_offset = offset;
8305acaca2fSWilliam A. Kennington III }
8315acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS;
8325acaca2fSWilliam A. Kennington III }
8335acaca2fSWilliam A. Kennington III }
8345acaca2fSWilliam A. Kennington III // Failed to locate magic.
8355acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC;
8365acaca2fSWilliam A. Kennington III }
8375acaca2fSWilliam A. Kennington III
8385acaca2fSWilliam A. Kennington III // Check whether the signature on the image is valid.
8395acaca2fSWilliam A. Kennington III // Validates the authenticity of an EEPROM image. Scans for & validates the
840dca92e47SWilly Tu // signature on the image descriptor. If the descriptor validates, hashes the
841dca92e47SWilly Tu // rest of the image to verify its integrity.
8425acaca2fSWilliam A. Kennington III //
843dca92e47SWilly Tu // @param[in] ctx - context which describes the image and holds opaque private
8445acaca2fSWilliam A. Kennington III // data for the user of the library
8455acaca2fSWilliam A. Kennington III // @param[in] intf - function pointers which interface to the current system
8465acaca2fSWilliam A. Kennington III // and environment
847dca92e47SWilly Tu // @param[out] image_regions - image_region pointer to an array for the output
848dca92e47SWilly Tu //
849dca92e47SWilly Tu // TODO(aranika) return valid key
8505acaca2fSWilliam A. Kennington III //
8515acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success
8525acaca2fSWilliam A. Kennington III
libcr51sign_validate(const struct libcr51sign_ctx * ctx,struct libcr51sign_intf * intf,struct libcr51sign_validated_regions * image_regions)853*c66ebc35SPatrick Williams failure_reason libcr51sign_validate(
854*c66ebc35SPatrick Williams const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
8555acaca2fSWilliam A. Kennington III struct libcr51sign_validated_regions* image_regions)
8565acaca2fSWilliam A. Kennington III {
8575acaca2fSWilliam A. Kennington III int rv, rv_first_desc = LIBCR51SIGN_SUCCESS;
8585acaca2fSWilliam A. Kennington III uint32_t descriptor_offset;
859dca92e47SWilly Tu uint32_t payload_blob_offset = 0;
8605acaca2fSWilliam A. Kennington III
8615acaca2fSWilliam A. Kennington III if (!ctx)
8625acaca2fSWilliam A. Kennington III {
863dca92e47SWilly Tu CPRINTS(ctx, "%s: Missing context\n", __FUNCTION__);
8645acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_CONTEXT;
8655acaca2fSWilliam A. Kennington III }
8665acaca2fSWilliam A. Kennington III else if (!intf)
8675acaca2fSWilliam A. Kennington III {
868dca92e47SWilly Tu CPRINTS(ctx, "%s: Missing interface\n", __FUNCTION__);
8695acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
8705acaca2fSWilliam A. Kennington III }
8715acaca2fSWilliam A. Kennington III
8725acaca2fSWilliam A. Kennington III rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, ctx->start_offset,
8735acaca2fSWilliam A. Kennington III ctx->end_offset, DESCRIPTOR_ALIGNMENT,
8745acaca2fSWilliam A. Kennington III &descriptor_offset);
8755acaca2fSWilliam A. Kennington III while (rv == LIBCR51SIGN_SUCCESS)
8765acaca2fSWilliam A. Kennington III {
877dca92e47SWilly Tu CPRINTS(ctx, "%s: potential image descriptor found @%x\n", __FUNCTION__,
8785acaca2fSWilliam A. Kennington III descriptor_offset);
879dca92e47SWilly Tu // Validation is split into 3 functions to minimize stack usage.
8805acaca2fSWilliam A. Kennington III
881dca92e47SWilly Tu rv = validate_descriptor(
882dca92e47SWilly Tu ctx, intf, descriptor_offset, descriptor_offset - ctx->start_offset,
883dca92e47SWilly Tu ctx->end_offset - ctx->start_offset, &payload_blob_offset);
8845acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS)
8855acaca2fSWilliam A. Kennington III {
886dca92e47SWilly Tu CPRINTS(ctx, "%s: validate_descriptor() failed ec%d\n",
887dca92e47SWilly Tu __FUNCTION__, rv);
8885acaca2fSWilliam A. Kennington III }
889dca92e47SWilly Tu else
8905acaca2fSWilliam A. Kennington III {
8916084957fSPatrick Williams rv = validate_payload_regions_helper(ctx, intf, descriptor_offset,
8926084957fSPatrick Williams image_regions);
893dca92e47SWilly Tu if (rv != LIBCR51SIGN_SUCCESS)
894dca92e47SWilly Tu {
895dca92e47SWilly Tu CPRINTS(ctx, "%s: validate_payload_regions() failed ec%d\n",
896dca92e47SWilly Tu __FUNCTION__, rv);
897dca92e47SWilly Tu }
898dca92e47SWilly Tu else if (ctx->descriptor.image_type == IMAGE_PROD)
899dca92e47SWilly Tu {
900dca92e47SWilly Tu // Lookup and validate payload Image MAUV against Image MAUV
901dca92e47SWilly Tu // stored in the system after checking signature to ensure
902dca92e47SWilly Tu // offsets and sizes are not tampered with. Also, do this after
903dca92e47SWilly Tu // hash calculation for payload regions to ensure that stored
904dca92e47SWilly Tu // Image MAUV is updated (if necessary) as close to the end of
905dca92e47SWilly Tu // payload validation as possible
906dca92e47SWilly Tu rv = validate_payload_image_mauv(ctx, intf, payload_blob_offset,
907dca92e47SWilly Tu ctx->descriptor.blob_size);
9085acaca2fSWilliam A. Kennington III if (rv == LIBCR51SIGN_SUCCESS)
9095acaca2fSWilliam A. Kennington III {
910dca92e47SWilly Tu CPRINTS(ctx,
911dca92e47SWilly Tu "%s: Payload Image MAUV validation successful\n",
912dca92e47SWilly Tu __FUNCTION__);
9135acaca2fSWilliam A. Kennington III return rv;
9145acaca2fSWilliam A. Kennington III }
915dca92e47SWilly Tu if (rv == LIBCR51SIGN_ERROR_STORING_NEW_IMAGE_MAUV_DATA)
916dca92e47SWilly Tu {
917dca92e47SWilly Tu CPRINTS(
918dca92e47SWilly Tu ctx,
919dca92e47SWilly Tu "%s: Payload validation succeeded, but Image MAUV validation "
920dca92e47SWilly Tu "failed\n",
921dca92e47SWilly Tu __FUNCTION__);
922dca92e47SWilly Tu return LIBCR51SIGN_ERROR_VALID_IMAGE_BUT_NEW_IMAGE_MAUV_DATA_NOT_STORED;
9235acaca2fSWilliam A. Kennington III }
924dca92e47SWilly Tu CPRINTS(ctx, "%s: Payload Image MAUV validation failed\n",
925dca92e47SWilly Tu __FUNCTION__);
926dca92e47SWilly Tu // In practice, we expect only 1 valid image descriptor in
927dca92e47SWilly Tu // payload. If Image MAUV check fails for the payload after
928dca92e47SWilly Tu // validating the image descriptor, do not try validating other
929dca92e47SWilly Tu // image descriptors
930dca92e47SWilly Tu return rv;
931dca92e47SWilly Tu }
932dca92e47SWilly Tu else
933dca92e47SWilly Tu {
934dca92e47SWilly Tu return rv;
935dca92e47SWilly Tu }
936dca92e47SWilly Tu }
937dca92e47SWilly Tu
9385acaca2fSWilliam A. Kennington III // Store the first desc fail reason if any
9396084957fSPatrick Williams if (rv != LIBCR51SIGN_SUCCESS && rv_first_desc == LIBCR51SIGN_SUCCESS)
9405acaca2fSWilliam A. Kennington III rv_first_desc = rv;
9415acaca2fSWilliam A. Kennington III
9425acaca2fSWilliam A. Kennington III // scan_for_magic_8() will round up to the next aligned boundary.
9435acaca2fSWilliam A. Kennington III descriptor_offset++;
9446084957fSPatrick Williams rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, descriptor_offset,
945dca92e47SWilly Tu ctx->end_offset, DESCRIPTOR_ALIGNMENT,
9466084957fSPatrick Williams &descriptor_offset);
9475acaca2fSWilliam A. Kennington III }
948dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to validate image ec%d\n", __FUNCTION__, rv);
9495acaca2fSWilliam A. Kennington III // If desc validation failed for some reason then return that reason
9505acaca2fSWilliam A. Kennington III if (rv_first_desc != LIBCR51SIGN_SUCCESS)
9515acaca2fSWilliam A. Kennington III return rv_first_desc;
9525acaca2fSWilliam A. Kennington III else
9535acaca2fSWilliam A. Kennington III return rv;
9545acaca2fSWilliam A. Kennington III }
9555acaca2fSWilliam A. Kennington III
9565acaca2fSWilliam A. Kennington III // @func to returns the libcr51sign error code as a string
9575acaca2fSWilliam A. Kennington III // @param[in] ec - Error code
9585acaca2fSWilliam A. Kennington III // @return error code in string format
9595acaca2fSWilliam A. Kennington III
libcr51sign_errorcode_to_string(failure_reason ec)9605acaca2fSWilliam A. Kennington III const char* libcr51sign_errorcode_to_string(failure_reason ec)
9615acaca2fSWilliam A. Kennington III {
9625acaca2fSWilliam A. Kennington III switch (ec)
9635acaca2fSWilliam A. Kennington III {
9645acaca2fSWilliam A. Kennington III case LIBCR51SIGN_SUCCESS:
9655acaca2fSWilliam A. Kennington III return "Success";
9665acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_RUNTIME_FAILURE:
9675acaca2fSWilliam A. Kennington III return "Runtime Error Failure";
9685acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR:
9695acaca2fSWilliam A. Kennington III return "Unsupported descriptor";
9705acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR:
9715acaca2fSWilliam A. Kennington III return "Invalid descriptor";
9725acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY:
9735acaca2fSWilliam A. Kennington III return "Invalid image family";
9745acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED:
9755acaca2fSWilliam A. Kennington III return "Image type disallowed";
9765acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED:
9775acaca2fSWilliam A. Kennington III return "Dev downgrade disallowed";
9785acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_UNTRUSTED_KEY:
9795acaca2fSWilliam A. Kennington III return "Untrusted key";
9805acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_SIGNATURE:
9815acaca2fSWilliam A. Kennington III return "Invalid signature";
9825acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_HASH:
9835acaca2fSWilliam A. Kennington III return "Invalid hash";
9845acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_HASH_TYPE:
9855acaca2fSWilliam A. Kennington III return "Invalid hash type";
9865acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_ARGUMENT:
9875acaca2fSWilliam A. Kennington III return "Invalid Argument";
9885acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC:
9895acaca2fSWilliam A. Kennington III return "Failed to locate descriptor";
9905acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_CONTEXT:
9915acaca2fSWilliam A. Kennington III return "Invalid context";
9925acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_INTERFACE:
9935acaca2fSWilliam A. Kennington III return "Invalid interface";
9945acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME:
9955acaca2fSWilliam A. Kennington III return "Invalid signature scheme";
9965acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_REGION_INPUT:
9975acaca2fSWilliam A. Kennington III return "Invalid image region input";
9985acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_REGION_SIZE:
9995acaca2fSWilliam A. Kennington III return "Invalid image region size";
1000dca92e47SWilly Tu case LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA:
1001dca92e47SWilly Tu return "Invalid Image MAUV data";
1002dca92e47SWilly Tu case LIBCR51SIGN_ERROR_RETRIEVING_STORED_IMAGE_MAUV_DATA:
1003dca92e47SWilly Tu return "Failed to retrieve Image MAUV data stored in system";
1004dca92e47SWilly Tu case LIBCR51SIGN_ERROR_STORING_NEW_IMAGE_MAUV_DATA:
1005dca92e47SWilly Tu return "Failed to store Image MAUV data from payload image into system";
1006dca92e47SWilly Tu case LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_DOES_NOT_ALLOW_UPDATE_TO_PAYLOAD:
1007dca92e47SWilly Tu return "Image MAUV stored in system does not allow payload "
1008dca92e47SWilly Tu "update";
1009dca92e47SWilly Tu case LIBCR51SIGN_ERROR_VALID_IMAGE_BUT_NEW_IMAGE_MAUV_DATA_NOT_STORED:
1010dca92e47SWilly Tu return "Payload image is valid for update but failed to store new Image "
1011dca92e47SWilly Tu "MAUV in system";
1012dca92e47SWilly Tu case LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_EXPECTS_PAYLOAD_IMAGE_MAUV:
1013dca92e47SWilly Tu return "Image MAUV is expected to be present in payload when stored "
1014dca92e47SWilly Tu "Image MAUV is present in the system";
1015dca92e47SWilly Tu case LIBCR51SIGN_NO_STORED_MAUV_FOUND:
1016dca92e47SWilly Tu return "Client did not find any MAUV data stored in the system";
10175acaca2fSWilliam A. Kennington III default:
10185acaca2fSWilliam A. Kennington III return "Unknown error";
10195acaca2fSWilliam A. Kennington III }
10205acaca2fSWilliam A. Kennington III }
10215acaca2fSWilliam A. Kennington III
10225acaca2fSWilliam A. Kennington III #ifdef __cplusplus
10235acaca2fSWilliam A. Kennington III } // extern "C"
10245acaca2fSWilliam A. Kennington III #endif
1025