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