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 #include <assert.h> 17dca92e47SWilly Tu #include <libcr51sign/cr51_image_descriptor.h> 185acaca2fSWilliam A. Kennington III #include <libcr51sign/libcr51sign.h> 19dca92e47SWilly Tu #include <libcr51sign/libcr51sign_internal.h> 20dca92e47SWilly Tu #include <libcr51sign/libcr51sign_mauv.h> 21027c042eSDan Zhang #include <stddef.h> 22dca92e47SWilly Tu #include <stdint.h> 235acaca2fSWilliam A. Kennington III #include <stdio.h> 24dca92e47SWilly Tu #include <stdlib.h> 255acaca2fSWilliam A. Kennington III #include <string.h> 265acaca2fSWilliam A. Kennington III 275acaca2fSWilliam A. Kennington III #ifdef __cplusplus 285acaca2fSWilliam A. Kennington III extern "C" 295acaca2fSWilliam A. Kennington III { 305acaca2fSWilliam A. Kennington III #endif 315acaca2fSWilliam A. Kennington III 325acaca2fSWilliam A. Kennington III // True of x is a power of two 335acaca2fSWilliam A. Kennington III #define POWER_OF_TWO(x) ((x) && !((x) & ((x) - 1))) 345acaca2fSWilliam A. Kennington III 355acaca2fSWilliam A. Kennington III // Maximum version supported. Major revisions are not backwards compatible. 365acaca2fSWilliam A. Kennington III #define MAX_MAJOR_VERSION 1 375acaca2fSWilliam A. Kennington III 385acaca2fSWilliam A. Kennington III // Descriptor alignment on the external EEPROM. 395acaca2fSWilliam A. Kennington III #define DESCRIPTOR_ALIGNMENT (64 * 1024) 405acaca2fSWilliam A. Kennington III 415acaca2fSWilliam A. Kennington III // SPS EEPROM sector size is 4KiB, since this is the smallest erasable size. 425acaca2fSWilliam A. Kennington III #define IMAGE_REGION_ALIGNMENT 4096 435acaca2fSWilliam A. Kennington III 445acaca2fSWilliam A. Kennington III #define MAX_READ_SIZE 1024 455acaca2fSWilliam A. Kennington III 465acaca2fSWilliam A. Kennington III #ifndef ARRAY_SIZE 475acaca2fSWilliam A. Kennington III #define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0])) 485acaca2fSWilliam A. Kennington III #endif 495acaca2fSWilliam A. Kennington III 50027c042eSDan Zhang // Values of SIGNATURE_OFFSET should be same for all sig types (2048,3072,4096) 515acaca2fSWilliam A. Kennington III #define SIGNATURE_OFFSET offsetof(struct signature_rsa3072_pkcs15, modulus) 525acaca2fSWilliam A. Kennington III 535acaca2fSWilliam A. Kennington III #ifndef BUILD_ASSERT 545acaca2fSWilliam A. Kennington III #define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) 555acaca2fSWilliam A. Kennington III #endif 565acaca2fSWilliam A. Kennington III 575acaca2fSWilliam A. Kennington III // Returns the bytes size of keys used in the given signature_scheme. 585acaca2fSWilliam A. Kennington III // Return error if signature_scheme is invalid. 595acaca2fSWilliam A. Kennington III // 605acaca2fSWilliam A. Kennington III static failure_reason get_key_size(enum signature_scheme signature_scheme, 615acaca2fSWilliam A. Kennington III uint16_t* key_size) 625acaca2fSWilliam A. Kennington III { 635acaca2fSWilliam A. Kennington III switch (signature_scheme) 645acaca2fSWilliam A. Kennington III { 655acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15: 665acaca2fSWilliam A. Kennington III *key_size = 256; 675acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 685acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15: 695acaca2fSWilliam A. Kennington III *key_size = 384; 705acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 715acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15: 725acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512: 735acaca2fSWilliam A. Kennington III *key_size = 512; 745acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 755acaca2fSWilliam A. Kennington III default: 765acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME; 775acaca2fSWilliam A. Kennington III } 785acaca2fSWilliam A. Kennington III } 795acaca2fSWilliam A. Kennington III 805acaca2fSWilliam A. Kennington III // Returns the hash_type for a given signature scheme 815acaca2fSWilliam A. Kennington III // Returns error if scheme is invalid. 825acaca2fSWilliam A. Kennington III failure_reason get_hash_type_from_signature(enum signature_scheme scheme, 835acaca2fSWilliam A. Kennington III enum hash_type* type) 845acaca2fSWilliam A. Kennington III { 855acaca2fSWilliam A. Kennington III switch (scheme) 865acaca2fSWilliam A. Kennington III { 875acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15: 885acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15: 895acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15: 905acaca2fSWilliam A. Kennington III *type = HASH_SHA2_256; 915acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 925acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512: 935acaca2fSWilliam A. Kennington III *type = HASH_SHA2_512; 945acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 955acaca2fSWilliam A. Kennington III default: 965acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME; 975acaca2fSWilliam A. Kennington III } 985acaca2fSWilliam A. Kennington III } 995acaca2fSWilliam A. Kennington III 1005acaca2fSWilliam A. Kennington III // Check if the given hash_type is supported. 1015acaca2fSWilliam A. Kennington III // Returns error if hash_type is not supported. 1025acaca2fSWilliam A. Kennington III static failure_reason is_hash_type_supported(enum hash_type type) 1035acaca2fSWilliam A. Kennington III { 1045acaca2fSWilliam A. Kennington III switch (type) 1055acaca2fSWilliam A. Kennington III { 1065acaca2fSWilliam A. Kennington III case HASH_SHA2_256: 1075acaca2fSWilliam A. Kennington III case HASH_SHA2_512: 1085acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 1095acaca2fSWilliam A. Kennington III default: 1105acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 1115acaca2fSWilliam A. Kennington III } 1125acaca2fSWilliam A. Kennington III } 1135acaca2fSWilliam A. Kennington III 1145acaca2fSWilliam A. Kennington III // Determines digest size for a given hash_type. 1155acaca2fSWilliam A. Kennington III // Returns error if hash_type is not supported. 1166084957fSPatrick Williams static failure_reason get_hash_digest_size(enum hash_type type, uint32_t* size) 1175acaca2fSWilliam A. Kennington III { 1185acaca2fSWilliam A. Kennington III switch (type) 1195acaca2fSWilliam A. Kennington III { 1205acaca2fSWilliam A. Kennington III case HASH_SHA2_256: 1215acaca2fSWilliam A. Kennington III *size = LIBCR51SIGN_SHA256_DIGEST_SIZE; 1225acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 1235acaca2fSWilliam A. Kennington III case HASH_SHA2_512: 1245acaca2fSWilliam A. Kennington III *size = LIBCR51SIGN_SHA512_DIGEST_SIZE; 1255acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 1265acaca2fSWilliam A. Kennington III default: 1275acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 1285acaca2fSWilliam A. Kennington III } 1295acaca2fSWilliam A. Kennington III } 1305acaca2fSWilliam A. Kennington III 1315acaca2fSWilliam A. Kennington III // Determines hash struct size for a given hash_type. 1325acaca2fSWilliam A. Kennington III // Returns error if hash_type is not supported. 1336084957fSPatrick Williams static failure_reason get_hash_struct_size(enum hash_type type, uint32_t* size) 1345acaca2fSWilliam A. Kennington III { 1355acaca2fSWilliam A. Kennington III switch (type) 1365acaca2fSWilliam A. Kennington III { 1375acaca2fSWilliam A. Kennington III case HASH_SHA2_256: 1385acaca2fSWilliam A. Kennington III *size = sizeof(struct hash_sha256); 1395acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 1405acaca2fSWilliam A. Kennington III case HASH_SHA2_512: 141dca92e47SWilly Tu *size = sizeof(struct hash_sha512); 1425acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 1435acaca2fSWilliam A. Kennington III default: 1445acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE; 1455acaca2fSWilliam A. Kennington III } 1465acaca2fSWilliam A. Kennington III } 1475acaca2fSWilliam A. Kennington III 1485acaca2fSWilliam A. Kennington III // Checks that: 1495acaca2fSWilliam A. Kennington III // - The signing key is trusted 1505acaca2fSWilliam A. Kennington III // - The target version is not denylisted 1515acaca2fSWilliam A. Kennington III // If validating a staged update, also checks that: 1525acaca2fSWilliam A. Kennington III // - The target image family matches the current image family 1535acaca2fSWilliam A. Kennington III // - The image type transition is legal (i.e. dev -> *|| prod -> prod) or 1545acaca2fSWilliam A. Kennington III // alternatively that the hardware ID is allowlisted 1555acaca2fSWilliam A. Kennington III // Assuming the caller has performed following: 1565acaca2fSWilliam A. Kennington III // board_get_base_key_index(); 1575acaca2fSWilliam A. Kennington III // board_get_key_array 1585acaca2fSWilliam A. Kennington III // Possible return codes: 1595acaca2fSWilliam A. Kennington III // LIBCR51SIGN_SUCCESS = 0, 1605acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1, 1615acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3, 1625acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4, 1635acaca2fSWilliam A. Kennington III // LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5, 1645acaca2fSWilliam A. Kennington III 1656084957fSPatrick Williams static failure_reason validate_transition(const struct libcr51sign_ctx* ctx, 1665acaca2fSWilliam A. Kennington III const struct libcr51sign_intf* intf, 1675acaca2fSWilliam A. Kennington III uint32_t signature_struct_offset) 1685acaca2fSWilliam A. Kennington III { 1695acaca2fSWilliam A. Kennington III BUILD_ASSERT((offsetof(struct signature_rsa2048_pkcs15, modulus) == 1705acaca2fSWilliam A. Kennington III SIGNATURE_OFFSET && 1715acaca2fSWilliam A. Kennington III offsetof(struct signature_rsa3072_pkcs15, modulus) == 1725acaca2fSWilliam A. Kennington III SIGNATURE_OFFSET && 1735acaca2fSWilliam A. Kennington III offsetof(struct signature_rsa4096_pkcs15, modulus) == 1745acaca2fSWilliam A. Kennington III SIGNATURE_OFFSET)); 1755acaca2fSWilliam A. Kennington III 1765acaca2fSWilliam A. Kennington III // Read up to the modulus. 1775acaca2fSWilliam A. Kennington III enum 1785acaca2fSWilliam A. Kennington III { 1795acaca2fSWilliam A. Kennington III read_len = SIGNATURE_OFFSET 1805acaca2fSWilliam A. Kennington III }; 181027c042eSDan Zhang uint32_t buffer[read_len / sizeof(uint32_t)]; 1825acaca2fSWilliam A. Kennington III int rv; 183027c042eSDan Zhang rv = intf->read(ctx, signature_struct_offset, read_len, (uint8_t*)buffer); 1845acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 1855acaca2fSWilliam A. Kennington III { 186dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read signature struct\n", __FUNCTION__); 1875acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 1885acaca2fSWilliam A. Kennington III } 189027c042eSDan Zhang if (*buffer != SIGNATURE_MAGIC) 1905acaca2fSWilliam A. Kennington III { 191dca92e47SWilly Tu CPRINTS(ctx, "%s: bad signature magic\n", __FUNCTION__); 1925acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 1935acaca2fSWilliam A. Kennington III } 1945acaca2fSWilliam A. Kennington III 1955acaca2fSWilliam A. Kennington III if (ctx->descriptor.image_family != ctx->current_image_family && 1965acaca2fSWilliam A. Kennington III ctx->descriptor.image_family != IMAGE_FAMILY_ALL && 1975acaca2fSWilliam A. Kennington III ctx->current_image_family != IMAGE_FAMILY_ALL) 1985acaca2fSWilliam A. Kennington III { 199dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image family\n", __FUNCTION__); 2005acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY; 2015acaca2fSWilliam A. Kennington III } 2025acaca2fSWilliam A. Kennington III 203d2bcdd5cSWilly Tu if (intf->is_production_mode == NULL) 2045acaca2fSWilliam A. Kennington III { 205dca92e47SWilly Tu CPRINTS(ctx, "%s: missing is_production_mode\n", __FUNCTION__); 2065acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE; 2075acaca2fSWilliam A. Kennington III } 2086084957fSPatrick Williams if (intf->is_production_mode() && (ctx->descriptor.image_type == IMAGE_DEV)) 2095acaca2fSWilliam A. Kennington III { 210dca92e47SWilly Tu CPRINTS(ctx, "%s: checking exemption allowlist\n", __FUNCTION__); 2115acaca2fSWilliam A. Kennington III 212d2bcdd5cSWilly Tu // If function is NULL or if the function call return false, return 213d2bcdd5cSWilly Tu // error 214d2bcdd5cSWilly Tu if (intf->prod_to_dev_downgrade_allowed == NULL || 215d2bcdd5cSWilly Tu !intf->prod_to_dev_downgrade_allowed()) 2165acaca2fSWilliam A. Kennington III { 217dca92e47SWilly Tu CPRINTS(ctx, "%s: illegal image type\n", __FUNCTION__); 2185acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED; 2195acaca2fSWilliam A. Kennington III } 2205acaca2fSWilliam A. Kennington III } 2215acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 2225acaca2fSWilliam A. Kennington III } 2235acaca2fSWilliam A. Kennington III 224dca92e47SWilly Tu // If caller had provided read_and_hash_update call that, otherwise call read 225dca92e47SWilly Tu // and then update. 2265acaca2fSWilliam A. Kennington III 227*0155b431SDan Zhang static failure_reason read_and_hash_update(struct libcr51sign_ctx* ctx, 2285acaca2fSWilliam A. Kennington III const struct libcr51sign_intf* intf, 2295acaca2fSWilliam A. Kennington III uint32_t offset, uint32_t size) 2305acaca2fSWilliam A. Kennington III { 2315acaca2fSWilliam A. Kennington III uint8_t read_buffer[MAX_READ_SIZE]; 2325acaca2fSWilliam A. Kennington III int rv; 233027c042eSDan Zhang uint32_t read_size; 2345acaca2fSWilliam A. Kennington III 2355acaca2fSWilliam A. Kennington III if (intf->read_and_hash_update) 2365acaca2fSWilliam A. Kennington III { 237*0155b431SDan Zhang rv = intf->read_and_hash_update(ctx, offset, size); 2385acaca2fSWilliam A. Kennington III } 2395acaca2fSWilliam A. Kennington III else 2405acaca2fSWilliam A. Kennington III { 2415acaca2fSWilliam A. Kennington III if (!intf->hash_update) 2425acaca2fSWilliam A. Kennington III { 243dca92e47SWilly Tu CPRINTS(ctx, "%s: missing hash_update\n", __FUNCTION__); 2445acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE; 2455acaca2fSWilliam A. Kennington III } 2465acaca2fSWilliam A. Kennington III do 2475acaca2fSWilliam A. Kennington III { 2485acaca2fSWilliam A. Kennington III read_size = size < MAX_READ_SIZE ? size : MAX_READ_SIZE; 249*0155b431SDan Zhang rv = intf->read(ctx, offset, read_size, read_buffer); 2505acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 2515acaca2fSWilliam A. Kennington III { 2525acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 2535acaca2fSWilliam A. Kennington III } 254*0155b431SDan Zhang rv = intf->hash_update(ctx, read_buffer, read_size); 2555acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 2565acaca2fSWilliam A. Kennington III { 2575acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 2585acaca2fSWilliam A. Kennington III } 2595acaca2fSWilliam A. Kennington III offset += read_size; 2605acaca2fSWilliam A. Kennington III size -= read_size; 2615acaca2fSWilliam A. Kennington III } while (size > 0); 2625acaca2fSWilliam A. Kennington III } 2635acaca2fSWilliam A. Kennington III return rv; 2645acaca2fSWilliam A. Kennington III } 2655acaca2fSWilliam A. Kennington III 2665acaca2fSWilliam A. Kennington III // Validates the image_region array, namely that: 2675acaca2fSWilliam A. Kennington III // - The regions are aligned, contiguous & exhaustive 2685acaca2fSWilliam A. Kennington III // - That the image descriptor resides in a static region 2695acaca2fSWilliam A. Kennington III // 2705acaca2fSWilliam A. Kennington III // If the array is consistent, proceeds to hash the static regions and 2715acaca2fSWilliam A. Kennington III // validates the hash. d_offset is the absolute image descriptor offset 2725acaca2fSWilliam A. Kennington III 2735acaca2fSWilliam A. Kennington III static failure_reason validate_payload_regions( 274*0155b431SDan Zhang struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf, 2755acaca2fSWilliam A. Kennington III uint32_t d_offset, struct libcr51sign_validated_regions* image_regions) 2765acaca2fSWilliam A. Kennington III { 277027c042eSDan Zhang // Allocate buffer to accommodate largest supported hash-type(SHA512) 2785acaca2fSWilliam A. Kennington III uint8_t magic_and_digest[MEMBER_SIZE(struct hash_sha512, hash_magic) + 2795acaca2fSWilliam A. Kennington III LIBCR51SIGN_SHA512_DIGEST_SIZE]; 2805acaca2fSWilliam A. Kennington III uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE]; 2815acaca2fSWilliam A. Kennington III uint32_t byte_count, region_count, image_size, hash_offset, digest_size; 282deb5501aSWilliam A. Kennington III uint32_t i; 283027c042eSDan Zhang uint32_t d_region_num = 0; 284deb5501aSWilliam A. Kennington III int rv; 285dca92e47SWilly Tu struct image_region const* region; 2865acaca2fSWilliam A. Kennington III 2875acaca2fSWilliam A. Kennington III if (image_regions == NULL) 2885acaca2fSWilliam A. Kennington III { 289dca92e47SWilly Tu CPRINTS(ctx, "%s: Missing image region input\n", __FUNCTION__); 2905acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_REGION_INPUT; 2915acaca2fSWilliam A. Kennington III } 2925acaca2fSWilliam A. Kennington III 2935acaca2fSWilliam A. Kennington III BUILD_ASSERT((MEMBER_SIZE(struct hash_sha256, hash_magic) == 2945acaca2fSWilliam A. Kennington III MEMBER_SIZE(struct hash_sha512, hash_magic))); 2955acaca2fSWilliam A. Kennington III image_size = ctx->descriptor.image_size; 2965acaca2fSWilliam A. Kennington III region_count = ctx->descriptor.region_count; 2975acaca2fSWilliam A. Kennington III hash_offset = d_offset + sizeof(struct image_descriptor) + 2985acaca2fSWilliam A. Kennington III region_count * sizeof(struct image_region); 2995acaca2fSWilliam A. Kennington III // Read the image_region array. 3005acaca2fSWilliam A. Kennington III 3015acaca2fSWilliam A. Kennington III if (region_count > ARRAY_SIZE(image_regions->image_regions)) 3025acaca2fSWilliam A. Kennington III { 303dca92e47SWilly Tu CPRINTS(ctx, 304dca92e47SWilly Tu "%s: ctx->descriptor.region_count is greater " 305dca92e47SWilly Tu "than LIBCR51SIGN_MAX_REGION_COUNT\n", 306dca92e47SWilly Tu __FUNCTION__); 3075acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_REGION_SIZE; 3085acaca2fSWilliam A. Kennington III } 3095acaca2fSWilliam A. Kennington III 310deb5501aSWilliam A. Kennington III rv = intf->read(ctx, d_offset + sizeof(struct image_descriptor), 3115acaca2fSWilliam A. Kennington III region_count * sizeof(struct image_region), 3125acaca2fSWilliam A. Kennington III (uint8_t*)&image_regions->image_regions); 3135acaca2fSWilliam A. Kennington III 3145acaca2fSWilliam A. Kennington III image_regions->region_count = region_count; 3155acaca2fSWilliam A. Kennington III 3165acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 3175acaca2fSWilliam A. Kennington III { 318dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read region array\n", __FUNCTION__); 3195acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 3205acaca2fSWilliam A. Kennington III } 3215acaca2fSWilliam A. Kennington III 3225acaca2fSWilliam A. Kennington III // Validate that the regions are contiguous & exhaustive. 3235acaca2fSWilliam A. Kennington III for (i = 0, byte_count = 0; i < region_count; i++) 3245acaca2fSWilliam A. Kennington III { 3255acaca2fSWilliam A. Kennington III region = image_regions->image_regions + i; 3265acaca2fSWilliam A. Kennington III 327dca92e47SWilly Tu CPRINTS(ctx, "%s: region #%d \"%s\" (%x - %x)\n", __FUNCTION__, i, 328dca92e47SWilly Tu (const char*)region->region_name, region->region_offset, 3295acaca2fSWilliam A. Kennington III region->region_offset + region->region_size); 3305acaca2fSWilliam A. Kennington III if ((region->region_offset % IMAGE_REGION_ALIGNMENT) != 0 || 3315acaca2fSWilliam A. Kennington III (region->region_size % IMAGE_REGION_ALIGNMENT) != 0) 3325acaca2fSWilliam A. Kennington III { 333dca92e47SWilly Tu CPRINTS(ctx, "%s: regions must be sector aligned\n", __FUNCTION__); 3345acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 3355acaca2fSWilliam A. Kennington III } 3365acaca2fSWilliam A. Kennington III if (region->region_offset != byte_count || 3375acaca2fSWilliam A. Kennington III region->region_size > image_size - byte_count) 3385acaca2fSWilliam A. Kennington III { 339dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid region array\n", __FUNCTION__); 3405acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 3415acaca2fSWilliam A. Kennington III } 3425acaca2fSWilliam A. Kennington III byte_count += region->region_size; 3435acaca2fSWilliam A. Kennington III // The image descriptor must be part of a static region. 3445acaca2fSWilliam A. Kennington III if (d_offset >= region->region_offset && d_offset < byte_count) 3455acaca2fSWilliam A. Kennington III { 3465acaca2fSWilliam A. Kennington III d_region_num = i; 347dca92e47SWilly Tu CPRINTS(ctx, "%s: image descriptor in region %d\n", __FUNCTION__, 3485acaca2fSWilliam A. Kennington III i); 3495acaca2fSWilliam A. Kennington III // The descriptor can't span regions. 350dca92e47SWilly Tu if ((ctx->descriptor.descriptor_area_size > 351dca92e47SWilly Tu (byte_count - d_offset)) || 3525acaca2fSWilliam A. Kennington III !(region->region_attributes & IMAGE_REGION_STATIC)) 3535acaca2fSWilliam A. Kennington III { 3546084957fSPatrick Williams CPRINTS(ctx, 355dca92e47SWilly Tu "%s: descriptor must reside in " 356dca92e47SWilly Tu "static region\n", 357dca92e47SWilly Tu __FUNCTION__); 3585acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 3595acaca2fSWilliam A. Kennington III } 3605acaca2fSWilliam A. Kennington III } 3615acaca2fSWilliam A. Kennington III } 3625acaca2fSWilliam A. Kennington III if (byte_count != image_size) 3635acaca2fSWilliam A. Kennington III { 364dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image size\n", __FUNCTION__); 3655acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 3665acaca2fSWilliam A. Kennington III } 3675acaca2fSWilliam A. Kennington III 3685acaca2fSWilliam A. Kennington III rv = get_hash_digest_size(ctx->descriptor.hash_type, &digest_size); 3695acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 3705acaca2fSWilliam A. Kennington III { 3715acaca2fSWilliam A. Kennington III return rv; 3725acaca2fSWilliam A. Kennington III } 3735acaca2fSWilliam A. Kennington III 3745acaca2fSWilliam A. Kennington III rv = intf->read(ctx, hash_offset, 3756084957fSPatrick Williams MEMBER_SIZE(struct hash_sha256, hash_magic) + digest_size, 3765acaca2fSWilliam A. Kennington III magic_and_digest); 3775acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 3785acaca2fSWilliam A. Kennington III { 379dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read hash from flash\n", __FUNCTION__); 3805acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 3815acaca2fSWilliam A. Kennington III } 3825acaca2fSWilliam A. Kennington III if (*(uint32_t*)magic_and_digest != HASH_MAGIC) 3835acaca2fSWilliam A. Kennington III { 384dca92e47SWilly Tu CPRINTS(ctx, "%s: bad hash magic\n", __FUNCTION__); 3855acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 3865acaca2fSWilliam A. Kennington III } 3875acaca2fSWilliam A. Kennington III rv = intf->hash_init(ctx, ctx->descriptor.hash_type); 3885acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 3895acaca2fSWilliam A. Kennington III { 390dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_init failed\n", __FUNCTION__); 3915acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 3925acaca2fSWilliam A. Kennington III } 3935acaca2fSWilliam A. Kennington III for (i = 0; i < region_count; i++) 3945acaca2fSWilliam A. Kennington III { 3955acaca2fSWilliam A. Kennington III uint32_t hash_start, hash_size; 3965acaca2fSWilliam A. Kennington III region = image_regions->image_regions + i; 3975acaca2fSWilliam A. Kennington III 3985acaca2fSWilliam A. Kennington III if (!(region->region_attributes & IMAGE_REGION_STATIC)) 3995acaca2fSWilliam A. Kennington III { 4005acaca2fSWilliam A. Kennington III continue; 4015acaca2fSWilliam A. Kennington III } 4025acaca2fSWilliam A. Kennington III hash_start = region->region_offset; 4035acaca2fSWilliam A. Kennington III hash_size = region->region_size; 4045acaca2fSWilliam A. Kennington III 4055acaca2fSWilliam A. Kennington III // Skip the descriptor. 4065acaca2fSWilliam A. Kennington III do 4075acaca2fSWilliam A. Kennington III { 4085acaca2fSWilliam A. Kennington III if (i == d_region_num) 4095acaca2fSWilliam A. Kennington III { 4105acaca2fSWilliam A. Kennington III hash_size = d_offset - hash_start; 4115acaca2fSWilliam A. Kennington III if (!hash_size) 4125acaca2fSWilliam A. Kennington III { 4135acaca2fSWilliam A. Kennington III hash_start += ctx->descriptor.descriptor_area_size; 414dca92e47SWilly Tu hash_size = (region->region_offset + region->region_size - 415dca92e47SWilly Tu hash_start); 4165acaca2fSWilliam A. Kennington III } 417dca92e47SWilly Tu } 418dca92e47SWilly Tu 419dca92e47SWilly Tu CPRINTS(ctx, "%s: hashing %s (%x - %x)\n", __FUNCTION__, 420deb5501aSWilliam A. Kennington III (const char*)region->region_name, hash_start, 4215acaca2fSWilliam A. Kennington III hash_start + hash_size); 4225acaca2fSWilliam A. Kennington III // Read the image_region array. 4235acaca2fSWilliam A. Kennington III rv = read_and_hash_update(ctx, intf, hash_start, hash_size); 4245acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 4255acaca2fSWilliam A. Kennington III { 4265acaca2fSWilliam A. Kennington III return rv; 4275acaca2fSWilliam A. Kennington III } 4285acaca2fSWilliam A. Kennington III hash_start += hash_size; 4295acaca2fSWilliam A. Kennington III } while (hash_start != region->region_offset + region->region_size); 4305acaca2fSWilliam A. Kennington III } 431*0155b431SDan Zhang rv = intf->hash_final(ctx, (uint8_t*)dcrypto_digest); 4325acaca2fSWilliam A. Kennington III 4335acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 4345acaca2fSWilliam A. Kennington III { 4355acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 4365acaca2fSWilliam A. Kennington III } 4375acaca2fSWilliam A. Kennington III 4386084957fSPatrick Williams if (memcmp(magic_and_digest + MEMBER_SIZE(struct hash_sha256, hash_magic), 439027c042eSDan Zhang dcrypto_digest, digest_size) != 0) 4405acaca2fSWilliam A. Kennington III { 441dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid hash\n", __FUNCTION__); 4425acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_HASH; 4435acaca2fSWilliam A. Kennington III } 4445acaca2fSWilliam A. Kennington III // Image is valid. 4455acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 4465acaca2fSWilliam A. Kennington III } 4475acaca2fSWilliam A. Kennington III 4485acaca2fSWilliam A. Kennington III // Create empty image_regions to pass to validate_payload_regions 449dca92e47SWilly Tu // Support validate_payload_regions_helper to remove image_regions as a required 450dca92e47SWilly Tu // input. 4515acaca2fSWilliam A. Kennington III 452c66ebc35SPatrick Williams static failure_reason allocate_and_validate_payload_regions( 453*0155b431SDan Zhang struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf, 4545acaca2fSWilliam A. Kennington III uint32_t d_offset) 4555acaca2fSWilliam A. Kennington III { 4565acaca2fSWilliam A. Kennington III struct libcr51sign_validated_regions image_regions; 4575acaca2fSWilliam A. Kennington III return validate_payload_regions(ctx, intf, d_offset, &image_regions); 4585acaca2fSWilliam A. Kennington III } 4595acaca2fSWilliam A. Kennington III 460dca92e47SWilly Tu // Wrapper around validate_payload_regions to allow nullptr for image_regions. 461dca92e47SWilly Tu // Calls allocate_and_validate_payload_regions when image_regions is nullptr to 462dca92e47SWilly Tu // create placer holder image_regions. 4635acaca2fSWilliam A. Kennington III 4645acaca2fSWilliam A. Kennington III static failure_reason validate_payload_regions_helper( 465*0155b431SDan Zhang struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf, 4665acaca2fSWilliam A. Kennington III uint32_t d_offset, struct libcr51sign_validated_regions* image_regions) 4675acaca2fSWilliam A. Kennington III { 4685acaca2fSWilliam A. Kennington III if (image_regions) 4695acaca2fSWilliam A. Kennington III { 4705acaca2fSWilliam A. Kennington III return validate_payload_regions(ctx, intf, d_offset, image_regions); 4715acaca2fSWilliam A. Kennington III } 4725acaca2fSWilliam A. Kennington III 4735acaca2fSWilliam A. Kennington III return allocate_and_validate_payload_regions(ctx, intf, d_offset); 4745acaca2fSWilliam A. Kennington III } 4755acaca2fSWilliam A. Kennington III 4765acaca2fSWilliam A. Kennington III // Check if the given signature_scheme is supported. 4775acaca2fSWilliam A. Kennington III // Returns nonzero on error, zero on success 4785acaca2fSWilliam A. Kennington III 4796c41aba5SPatrick Williams static failure_reason is_signature_scheme_supported( 4806c41aba5SPatrick Williams enum signature_scheme scheme) 4815acaca2fSWilliam A. Kennington III { 4825acaca2fSWilliam A. Kennington III switch (scheme) 4835acaca2fSWilliam A. Kennington III { 4845acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15: 4855acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15: 4865acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15: 4875acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512: 4885acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 4895acaca2fSWilliam A. Kennington III default: 4905acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME; 4915acaca2fSWilliam A. Kennington III } 4925acaca2fSWilliam A. Kennington III } 4935acaca2fSWilliam A. Kennington III 4945acaca2fSWilliam A. Kennington III // Returns size of signature struct size in |size| 4955acaca2fSWilliam A. Kennington III // Returns nonzero on error, zero on success 4965acaca2fSWilliam A. Kennington III 4976c41aba5SPatrick Williams static failure_reason get_signature_struct_size(enum signature_scheme scheme, 4986c41aba5SPatrick Williams uint32_t* size) 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 *size = sizeof(struct signature_rsa2048_pkcs15); 5045acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 5055acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15: 5065acaca2fSWilliam A. Kennington III *size = sizeof(struct signature_rsa3072_pkcs15); 5075acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 5085acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15: 5095acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512: 5105acaca2fSWilliam A. Kennington III *size = sizeof(struct signature_rsa4096_pkcs15); 5115acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 5125acaca2fSWilliam A. Kennington III default: 5135acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME; 5145acaca2fSWilliam A. Kennington III } 5155acaca2fSWilliam A. Kennington III } 5165acaca2fSWilliam A. Kennington III 5176c41aba5SPatrick Williams static failure_reason get_signature_field_offset(enum signature_scheme scheme, 5186c41aba5SPatrick Williams uint32_t* offset) 5195acaca2fSWilliam A. Kennington III { 5205acaca2fSWilliam A. Kennington III switch (scheme) 5215acaca2fSWilliam A. Kennington III { 5225acaca2fSWilliam A. Kennington III case SIGNATURE_RSA2048_PKCS15: 5235acaca2fSWilliam A. Kennington III *offset = offsetof(struct signature_rsa2048_pkcs15, signature); 5245acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 5255acaca2fSWilliam A. Kennington III case SIGNATURE_RSA3072_PKCS15: 5265acaca2fSWilliam A. Kennington III *offset = offsetof(struct signature_rsa3072_pkcs15, signature); 5275acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 5285acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15: 5295acaca2fSWilliam A. Kennington III case SIGNATURE_RSA4096_PKCS15_SHA512: 5305acaca2fSWilliam A. Kennington III *offset = offsetof(struct signature_rsa4096_pkcs15, signature); 5315acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 5325acaca2fSWilliam A. Kennington III default: 5335acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME; 5345acaca2fSWilliam A. Kennington III } 5355acaca2fSWilliam A. Kennington III } 5365acaca2fSWilliam A. Kennington III 537027c042eSDan Zhang __attribute__((nonnull)) static bool is_key_in_signature_struct_trusted( 538*0155b431SDan Zhang struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf, 539027c042eSDan Zhang enum signature_scheme scheme, uint32_t raw_signature_offset, 540027c042eSDan Zhang void* signature_struct, uint32_t* signature_struct_size) 541027c042eSDan Zhang { 542027c042eSDan Zhang if (!intf->trust_key_in_signature_structure) 543027c042eSDan Zhang { 544027c042eSDan Zhang CPRINTS(ctx, "%s: trust_key_in_signature_structure is not supported\n", 545027c042eSDan Zhang __FUNCTION__); 546027c042eSDan Zhang return false; 547027c042eSDan Zhang } 548027c042eSDan Zhang 549027c042eSDan Zhang uint32_t signature_field_offset; 550027c042eSDan Zhang int rv = get_signature_field_offset(scheme, &signature_field_offset); 551027c042eSDan Zhang if (rv != LIBCR51SIGN_SUCCESS) 552027c042eSDan Zhang { 553027c042eSDan Zhang return false; 554027c042eSDan Zhang } 555027c042eSDan Zhang 556027c042eSDan Zhang if (signature_field_offset > raw_signature_offset) 557027c042eSDan Zhang { 558027c042eSDan Zhang CPRINTS(ctx, 559027c042eSDan Zhang "%s: signature_field_offset (%d) is larger than " 560027c042eSDan Zhang "raw_signature_offset (%d)\n", 561027c042eSDan Zhang __FUNCTION__, signature_field_offset, raw_signature_offset); 562027c042eSDan Zhang return false; 563027c042eSDan Zhang } 564027c042eSDan Zhang uint32_t signature_offset = raw_signature_offset - signature_field_offset; 565027c042eSDan Zhang 566027c042eSDan Zhang rv = get_signature_struct_size(scheme, signature_struct_size); 567027c042eSDan Zhang if (rv != LIBCR51SIGN_SUCCESS) 568027c042eSDan Zhang { 569027c042eSDan Zhang return false; 570027c042eSDan Zhang } 571027c042eSDan Zhang 572027c042eSDan Zhang rv = intf->read(ctx, signature_offset, *signature_struct_size, 573027c042eSDan Zhang signature_struct); 574027c042eSDan Zhang if (rv != LIBCR51SIGN_SUCCESS) 575027c042eSDan Zhang { 576027c042eSDan Zhang CPRINTS(ctx, "%s: failed to read signature (status = %d)\n", 577027c042eSDan Zhang __FUNCTION__, rv); 578027c042eSDan Zhang return false; 579027c042eSDan Zhang } 580027c042eSDan Zhang 581027c042eSDan Zhang return intf->trust_key_in_signature_structure(ctx, scheme, signature_struct, 582027c042eSDan Zhang *signature_struct_size); 583027c042eSDan Zhang } 584027c042eSDan Zhang // Validates the signature with verification key provided along with the 585027c042eSDan Zhang // signature if the key is trusted. 586027c042eSDan Zhang 587027c042eSDan Zhang static bool validate_signature_with_key_in_signature_struct( 588*0155b431SDan Zhang struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf, 589027c042eSDan Zhang enum signature_scheme scheme, uint32_t raw_signature_offset, 590027c042eSDan Zhang const uint8_t* digest, uint32_t digest_size) 591027c042eSDan Zhang { 592027c042eSDan Zhang // pick the biggest signature struct size. 593027c042eSDan Zhang uint8_t signature_struct[sizeof(struct signature_rsa4096_pkcs15)]; 594027c042eSDan Zhang uint32_t signature_struct_size = sizeof(signature_struct); 595027c042eSDan Zhang if (!is_key_in_signature_struct_trusted( 596027c042eSDan Zhang ctx, intf, scheme, raw_signature_offset, &signature_struct, 597027c042eSDan Zhang &signature_struct_size)) 598027c042eSDan Zhang { 599027c042eSDan Zhang CPRINTS(ctx, "%s: key in signature struct is not trusted\n", 600027c042eSDan Zhang __FUNCTION__); 601027c042eSDan Zhang return false; 602027c042eSDan Zhang } 603027c042eSDan Zhang if (!intf->verify_rsa_signature_with_modulus_and_exponent) 604027c042eSDan Zhang { 605027c042eSDan Zhang CPRINTS( 606027c042eSDan Zhang ctx, 607027c042eSDan Zhang "%s: verify_rsa_signature_with_modulus_and_exponent is not supported\n", 608027c042eSDan Zhang __FUNCTION__); 609027c042eSDan Zhang return false; 610027c042eSDan Zhang } 611027c042eSDan Zhang 612027c042eSDan Zhang switch (scheme) 613027c042eSDan Zhang { 614027c042eSDan Zhang case SIGNATURE_RSA2048_PKCS15: 615027c042eSDan Zhang { 616027c042eSDan Zhang struct signature_rsa2048_pkcs15* sig = 617027c042eSDan Zhang (struct signature_rsa2048_pkcs15*)signature_struct; 618027c042eSDan Zhang return intf->verify_rsa_signature_with_modulus_and_exponent( 619027c042eSDan Zhang ctx, scheme, sig->modulus, sizeof(sig->modulus), sig->exponent, 620027c042eSDan Zhang sig->signature, sizeof(sig->signature), digest, digest_size); 621027c042eSDan Zhang } 622027c042eSDan Zhang break; 623027c042eSDan Zhang case SIGNATURE_RSA3072_PKCS15: 624027c042eSDan Zhang { 625027c042eSDan Zhang struct signature_rsa3072_pkcs15* sig = 626027c042eSDan Zhang (struct signature_rsa3072_pkcs15*)signature_struct; 627027c042eSDan Zhang return intf->verify_rsa_signature_with_modulus_and_exponent( 628027c042eSDan Zhang ctx, scheme, sig->modulus, sizeof(sig->modulus), sig->exponent, 629027c042eSDan Zhang sig->signature, sizeof(sig->signature), digest, digest_size); 630027c042eSDan Zhang } 631027c042eSDan Zhang break; 632027c042eSDan Zhang case SIGNATURE_RSA4096_PKCS15: 633027c042eSDan Zhang case SIGNATURE_RSA4096_PKCS15_SHA512: 634027c042eSDan Zhang { 635027c042eSDan Zhang struct signature_rsa4096_pkcs15* sig = 636027c042eSDan Zhang (struct signature_rsa4096_pkcs15*)signature_struct; 637027c042eSDan Zhang return intf->verify_rsa_signature_with_modulus_and_exponent( 638027c042eSDan Zhang ctx, scheme, sig->modulus, sizeof(sig->modulus), sig->exponent, 639027c042eSDan Zhang sig->signature, sizeof(sig->signature), digest, digest_size); 640027c042eSDan Zhang } 641027c042eSDan Zhang break; 642027c042eSDan Zhang default: 643027c042eSDan Zhang CPRINTS(ctx, "%s: unsupported signature scheme %d\n", __FUNCTION__, 644027c042eSDan Zhang scheme); 645027c042eSDan Zhang return false; 646027c042eSDan Zhang } 647027c042eSDan Zhang } 648027c042eSDan Zhang 6495acaca2fSWilliam A. Kennington III // Validates the signature (of type scheme) read from "device" at 6505acaca2fSWilliam A. Kennington III //"raw_signature_offset" with "public_key" over a SHA256/SHA512 digest of 6515acaca2fSWilliam A. Kennington III // EEPROM area "data_offset:data_size". 6525acaca2fSWilliam A. Kennington III 653c66ebc35SPatrick Williams static failure_reason validate_signature( 654*0155b431SDan Zhang struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf, 655c66ebc35SPatrick Williams uint32_t data_offset, uint32_t data_size, enum signature_scheme scheme, 6565acaca2fSWilliam A. Kennington III uint32_t raw_signature_offset) 6575acaca2fSWilliam A. Kennington III { 6585acaca2fSWilliam A. Kennington III uint8_t signature[LIBCR51SIGN_MAX_SIGNATURE_SIZE]; 6595acaca2fSWilliam A. Kennington III uint16_t key_size; 6605acaca2fSWilliam A. Kennington III uint32_t digest_size; 6615acaca2fSWilliam A. Kennington III uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE]; 6625acaca2fSWilliam A. Kennington III int rv; 6635acaca2fSWilliam A. Kennington III enum hash_type hash_type; 6645acaca2fSWilliam A. Kennington III 6655acaca2fSWilliam A. Kennington III if (!intf->hash_init) 6665acaca2fSWilliam A. Kennington III { 667dca92e47SWilly Tu CPRINTS(ctx, "%s: missing hash_init\n", __FUNCTION__); 6685acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE; 6695acaca2fSWilliam A. Kennington III } 6705acaca2fSWilliam A. Kennington III rv = get_hash_type_from_signature(scheme, &hash_type); 6715acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 6725acaca2fSWilliam A. Kennington III { 673dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_type from signature failed\n", __FUNCTION__); 6745acaca2fSWilliam A. Kennington III return rv; 6755acaca2fSWilliam A. Kennington III } 6765acaca2fSWilliam A. Kennington III rv = intf->hash_init(ctx, hash_type); 6775acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 6785acaca2fSWilliam A. Kennington III { 679dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_init failed\n", __FUNCTION__); 6805acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 6815acaca2fSWilliam A. Kennington III } 6825acaca2fSWilliam A. Kennington III rv = read_and_hash_update(ctx, intf, data_offset, data_size); 6835acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 6845acaca2fSWilliam A. Kennington III { 685dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_update failed\n", __FUNCTION__); 6865acaca2fSWilliam A. Kennington III return rv; 6875acaca2fSWilliam A. Kennington III } 6885acaca2fSWilliam A. Kennington III if (!intf->hash_final) 6895acaca2fSWilliam A. Kennington III { 690dca92e47SWilly Tu CPRINTS(ctx, "%s: missing hash_final\n", __FUNCTION__); 6915acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE; 6925acaca2fSWilliam A. Kennington III } 693*0155b431SDan Zhang rv = intf->hash_final(ctx, dcrypto_digest); 6945acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 6955acaca2fSWilliam A. Kennington III { 696dca92e47SWilly Tu CPRINTS(ctx, "%s: hash_final failed (status = %d)\n", __FUNCTION__, rv); 6975acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 6985acaca2fSWilliam A. Kennington III } 699027c042eSDan Zhang 700027c042eSDan Zhang rv = get_hash_digest_size(hash_type, &digest_size); 701027c042eSDan Zhang if (rv != LIBCR51SIGN_SUCCESS) 702027c042eSDan Zhang { 703027c042eSDan Zhang return rv; 704027c042eSDan Zhang } 705027c042eSDan Zhang 706027c042eSDan Zhang if (intf->trust_descriptor_hash) 707027c042eSDan Zhang { 708027c042eSDan Zhang if (intf->trust_descriptor_hash(ctx, dcrypto_digest, digest_size)) 709027c042eSDan Zhang { 710027c042eSDan Zhang CPRINTS(ctx, "%s: descriptor hash trusted\n", __FUNCTION__); 711027c042eSDan Zhang return LIBCR51SIGN_SUCCESS; 712027c042eSDan Zhang } 713027c042eSDan Zhang } 714027c042eSDan Zhang 7155acaca2fSWilliam A. Kennington III rv = get_key_size(scheme, &key_size); 7165acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 7175acaca2fSWilliam A. Kennington III { 7185acaca2fSWilliam A. Kennington III return rv; 7195acaca2fSWilliam A. Kennington III } 7205acaca2fSWilliam A. Kennington III 7215acaca2fSWilliam A. Kennington III rv = intf->read(ctx, raw_signature_offset, key_size, signature); 7225acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 7235acaca2fSWilliam A. Kennington III { 724dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read signature (status = %d)\n", 725dca92e47SWilly Tu __FUNCTION__, rv); 7265acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 7275acaca2fSWilliam A. Kennington III } 728027c042eSDan Zhang 729027c042eSDan Zhang if (validate_signature_with_key_in_signature_struct( 730027c042eSDan Zhang ctx, intf, scheme, raw_signature_offset, dcrypto_digest, 731027c042eSDan Zhang digest_size)) 732027c042eSDan Zhang { 733027c042eSDan Zhang CPRINTS(ctx, "%s: verification with external key succeeded\n", 734027c042eSDan Zhang __FUNCTION__); 735027c042eSDan Zhang return LIBCR51SIGN_SUCCESS; 736027c042eSDan Zhang } 737027c042eSDan Zhang 7385acaca2fSWilliam A. Kennington III if (!intf->verify_signature) 7395acaca2fSWilliam A. Kennington III { 740dca92e47SWilly Tu CPRINTS(ctx, "%s: missing verify_signature\n", __FUNCTION__); 7415acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE; 7425acaca2fSWilliam A. Kennington III } 743027c042eSDan Zhang 7445acaca2fSWilliam A. Kennington III rv = intf->verify_signature(ctx, scheme, signature, key_size, 7455acaca2fSWilliam A. Kennington III dcrypto_digest, digest_size); 7465acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 7475acaca2fSWilliam A. Kennington III { 748dca92e47SWilly Tu CPRINTS(ctx, "%s: verification failed (status = %d)\n", __FUNCTION__, 7495acaca2fSWilliam A. Kennington III rv); 7505acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_SIGNATURE; 7515acaca2fSWilliam A. Kennington III } 752dca92e47SWilly Tu CPRINTS(ctx, "%s: verification succeeded\n", __FUNCTION__); 7535acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 7545acaca2fSWilliam A. Kennington III } 7555acaca2fSWilliam A. Kennington III 7565acaca2fSWilliam A. Kennington III // Sanity checks the image descriptor & validates its signature. 7575acaca2fSWilliam A. Kennington III // This function does not validate the image_region array or image hash. 7585acaca2fSWilliam A. Kennington III // 7595acaca2fSWilliam A. Kennington III //@param[in] ctx context which describes the image and holds opaque private 7605acaca2fSWilliam A. Kennington III // data for the user of the library 7615acaca2fSWilliam A. Kennington III //@param[in] intf function pointers which interface to the current system 7625acaca2fSWilliam A. Kennington III // and environment 7635acaca2fSWilliam A. Kennington III //@param offset Absolute image descriptor flash offset. 7645acaca2fSWilliam A. Kennington III //@param relative_offset Image descriptor offset relative to image start. 765af46bea6SWilliam A. Kennington III //@param max_size Maximum size of the flash space in bytes. 766dca92e47SWilly Tu //@param[out] payload_blob_offset Absolute offset of BLOB data in image 767dca92e47SWilly Tu // descriptor (if BLOB data is present) 768c66ebc35SPatrick Williams static failure_reason validate_descriptor( 769*0155b431SDan Zhang struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf, 770c66ebc35SPatrick Williams uint32_t offset, uint32_t relative_offset, uint32_t max_size, 771dca92e47SWilly Tu uint32_t* const restrict payload_blob_offset) 7725acaca2fSWilliam A. Kennington III { 7735acaca2fSWilliam A. Kennington III uint32_t max_descriptor_size, signed_size, signature_scheme, 7745acaca2fSWilliam A. Kennington III signature_offset; 7756084957fSPatrick Williams uint32_t signature_struct_offset, signature_struct_size, hash_struct_size; 7765acaca2fSWilliam A. Kennington III int rv; 7775acaca2fSWilliam A. Kennington III 778af46bea6SWilliam A. Kennington III max_descriptor_size = max_size - relative_offset; 779af46bea6SWilliam A. Kennington III if (max_size < relative_offset || 7805acaca2fSWilliam A. Kennington III max_descriptor_size < sizeof(struct image_descriptor)) 7815acaca2fSWilliam A. Kennington III { 782dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid arguments\n", __FUNCTION__); 7835acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 7845acaca2fSWilliam A. Kennington III } 7855acaca2fSWilliam A. Kennington III 7865acaca2fSWilliam A. Kennington III rv = intf->read(ctx, offset, sizeof(ctx->descriptor), 7875acaca2fSWilliam A. Kennington III (uint8_t*)&ctx->descriptor); 7885acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 7895acaca2fSWilliam A. Kennington III { 790dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to read descriptor\n", __FUNCTION__); 7915acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_RUNTIME_FAILURE; 7925acaca2fSWilliam A. Kennington III } 7935acaca2fSWilliam A. Kennington III if (ctx->descriptor.descriptor_magic != DESCRIPTOR_MAGIC || 7945acaca2fSWilliam A. Kennington III ctx->descriptor.descriptor_offset != relative_offset || 7955acaca2fSWilliam A. Kennington III ctx->descriptor.region_count == 0 || 7965acaca2fSWilliam A. Kennington III ctx->descriptor.descriptor_area_size > max_descriptor_size || 797af46bea6SWilliam A. Kennington III ctx->descriptor.image_size > max_size) 7985acaca2fSWilliam A. Kennington III { 799dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid descriptor\n", __FUNCTION__); 800af46bea6SWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 801af46bea6SWilliam A. Kennington III } 802af46bea6SWilliam A. Kennington III if (intf->image_size_valid == NULL) 803af46bea6SWilliam A. Kennington III { 804dca92e47SWilly Tu // Preserve original behavior of requiring exact image_size match if no 805dca92e47SWilly Tu // operator is provided. 806af46bea6SWilliam A. Kennington III if (ctx->descriptor.image_size != max_size) 807af46bea6SWilliam A. Kennington III { 808dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image size\n", __FUNCTION__); 809af46bea6SWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 810af46bea6SWilliam A. Kennington III } 811af46bea6SWilliam A. Kennington III } 812af46bea6SWilliam A. Kennington III else if (!intf->image_size_valid(ctx->descriptor.image_size)) 813af46bea6SWilliam A. Kennington III { 814dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid image size\n", __FUNCTION__); 8155acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 8165acaca2fSWilliam A. Kennington III } 8175acaca2fSWilliam A. Kennington III if (ctx->descriptor.image_type != IMAGE_DEV && 8185acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_PROD && 8195acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_BREAKOUT && 8205acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_TEST && 8215acaca2fSWilliam A. Kennington III ctx->descriptor.image_type != IMAGE_UNSIGNED_INTEGRITY) 8225acaca2fSWilliam A. Kennington III { 823dca92e47SWilly Tu CPRINTS(ctx, "%s: bad image type\n", __FUNCTION__); 8245acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 8255acaca2fSWilliam A. Kennington III } 8265acaca2fSWilliam A. Kennington III // Although the image_descriptor struct supports unauthenticated 8275acaca2fSWilliam A. Kennington III // images, Haven will not allow it. 8285acaca2fSWilliam A. Kennington III // Haven only supports SHA256 + RSA2048/RSA3072_PKCS15 currently. 8295acaca2fSWilliam A. Kennington III 8305acaca2fSWilliam A. Kennington III signature_scheme = ctx->descriptor.signature_scheme; 8315acaca2fSWilliam A. Kennington III 8325acaca2fSWilliam A. Kennington III rv = is_signature_scheme_supported(signature_scheme); 8335acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 8345acaca2fSWilliam A. Kennington III { 8355acaca2fSWilliam A. Kennington III return rv; 8365acaca2fSWilliam A. Kennington III } 8375acaca2fSWilliam A. Kennington III rv = is_hash_type_supported(ctx->descriptor.hash_type); 8385acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 8395acaca2fSWilliam A. Kennington III { 840dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid hash type\n", __FUNCTION__); 8415acaca2fSWilliam A. Kennington III return rv; 8425acaca2fSWilliam A. Kennington III } 8435acaca2fSWilliam A. Kennington III if (ctx->descriptor.descriptor_major > MAX_MAJOR_VERSION || 8445acaca2fSWilliam A. Kennington III ctx->descriptor.region_count > LIBCR51SIGN_MAX_REGION_COUNT) 8455acaca2fSWilliam A. Kennington III { 846dca92e47SWilly Tu CPRINTS(ctx, "%s: unsupported descriptor\n", __FUNCTION__); 8475acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR; 8485acaca2fSWilliam A. Kennington III } 8496084957fSPatrick Williams rv = get_signature_struct_size(signature_scheme, &signature_struct_size); 8505acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 8515acaca2fSWilliam A. Kennington III { 8525acaca2fSWilliam A. Kennington III return rv; 8535acaca2fSWilliam A. Kennington III } 8545acaca2fSWilliam A. Kennington III 8555acaca2fSWilliam A. Kennington III // Compute the size of the signed portion of the image descriptor. 8562be45238SPatrick Williams signed_size = sizeof(struct image_descriptor) + 8576084957fSPatrick Williams ctx->descriptor.region_count * sizeof(struct image_region); 8585acaca2fSWilliam A. Kennington III rv = get_hash_struct_size(ctx->descriptor.hash_type, &hash_struct_size); 8595acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 8605acaca2fSWilliam A. Kennington III { 8615acaca2fSWilliam A. Kennington III return rv; 8625acaca2fSWilliam A. Kennington III } 8635acaca2fSWilliam A. Kennington III signed_size += hash_struct_size; 8645acaca2fSWilliam A. Kennington III if (ctx->descriptor.denylist_size) 8655acaca2fSWilliam A. Kennington III { 8665acaca2fSWilliam A. Kennington III signed_size += sizeof(struct denylist); 8672be45238SPatrick Williams signed_size += ctx->descriptor.denylist_size * 8682be45238SPatrick Williams sizeof(struct denylist_record); 8695acaca2fSWilliam A. Kennington III } 8705acaca2fSWilliam A. Kennington III if (ctx->descriptor.blob_size) 8715acaca2fSWilliam A. Kennington III { 872dca92e47SWilly Tu *payload_blob_offset = offset + signed_size; 8735acaca2fSWilliam A. Kennington III signed_size += sizeof(struct blob); 8745acaca2fSWilliam A. Kennington III // Previous additions are guaranteed not to overflow. 875dca92e47SWilly Tu if ((ctx->descriptor.blob_size > 876dca92e47SWilly Tu ctx->descriptor.descriptor_area_size - signed_size) || 877dca92e47SWilly Tu // Sanity check blob size 878dca92e47SWilly Tu (ctx->descriptor.blob_size < sizeof(struct blob_data))) 8795acaca2fSWilliam A. Kennington III { 880dca92e47SWilly Tu CPRINTS(ctx, "%s: invalid blob size (0x%x)\n", __FUNCTION__, 8815acaca2fSWilliam A. Kennington III ctx->descriptor.blob_size); 8825acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 8835acaca2fSWilliam A. Kennington III } 8845acaca2fSWilliam A. Kennington III signed_size += ctx->descriptor.blob_size; 8855acaca2fSWilliam A. Kennington III } 8865acaca2fSWilliam A. Kennington III if (signature_struct_size > 8875acaca2fSWilliam A. Kennington III ctx->descriptor.descriptor_area_size - signed_size) 8885acaca2fSWilliam A. Kennington III { 8895acaca2fSWilliam A. Kennington III CPRINTS(ctx, 890dca92e47SWilly Tu "%s: invalid descriptor area size " 891af46bea6SWilliam A. Kennington III "(expected = 0x%x, actual = 0x%x)\n", 892dca92e47SWilly Tu __FUNCTION__, ctx->descriptor.descriptor_area_size, 8935acaca2fSWilliam A. Kennington III signed_size + signature_struct_size); 8945acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR; 8955acaca2fSWilliam A. Kennington III } 8965acaca2fSWilliam A. Kennington III signature_struct_offset = signed_size; 8975acaca2fSWilliam A. Kennington III // Omit the actual signature. 8985acaca2fSWilliam A. Kennington III rv = get_signature_field_offset(signature_scheme, &signature_offset); 8995acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 9005acaca2fSWilliam A. Kennington III { 9015acaca2fSWilliam A. Kennington III return rv; 9025acaca2fSWilliam A. Kennington III } 9035acaca2fSWilliam A. Kennington III signed_size += signature_offset; 9045acaca2fSWilliam A. Kennington III 9055acaca2fSWilliam A. Kennington III // Lookup key & validate transition. 9065acaca2fSWilliam A. Kennington III rv = validate_transition(ctx, intf, offset + signature_struct_offset); 9075acaca2fSWilliam A. Kennington III 9085acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 9095acaca2fSWilliam A. Kennington III { 9105acaca2fSWilliam A. Kennington III return rv; 9115acaca2fSWilliam A. Kennington III } 9126084957fSPatrick Williams return validate_signature(ctx, intf, offset, signed_size, signature_scheme, 9136084957fSPatrick Williams offset + signed_size); 9145acaca2fSWilliam A. Kennington III } 9155acaca2fSWilliam A. Kennington III 9165acaca2fSWilliam A. Kennington III // Scans the external EEPROM for a magic value at "alignment" boundaries. 9175acaca2fSWilliam A. Kennington III // 9185acaca2fSWilliam A. Kennington III //@param device Handle to the external EEPROM. 9195acaca2fSWilliam A. Kennington III //@param magic 8-byte pattern to search for. 9205acaca2fSWilliam A. Kennington III //@param start_offset Offset to begin searching at. 9215acaca2fSWilliam A. Kennington III //@param limit Exclusive address (e.g. EEPROM size). 9225acaca2fSWilliam A. Kennington III //@param alignment Alignment boundaries (POW2) to search on. 9235acaca2fSWilliam A. Kennington III //@param header_offset Location to place the new header offset. 9245acaca2fSWilliam A. Kennington III //@return LIBCR51SIGN_SUCCESS (or non-zero on error). 9255acaca2fSWilliam A. Kennington III 926*0155b431SDan Zhang static int scan_for_magic_8(struct libcr51sign_ctx* ctx, 9275acaca2fSWilliam A. Kennington III const struct libcr51sign_intf* intf, uint64_t magic, 928027c042eSDan Zhang uint32_t start_offset, uint32_t limit, 929027c042eSDan Zhang uint32_t alignment, uint32_t* header_offset) 9305acaca2fSWilliam A. Kennington III { 9315acaca2fSWilliam A. Kennington III uint64_t read_data; 9325acaca2fSWilliam A. Kennington III uint32_t offset; 9335acaca2fSWilliam A. Kennington III int rv; 9345acaca2fSWilliam A. Kennington III 9355acaca2fSWilliam A. Kennington III if (limit <= start_offset || limit > ctx->end_offset || 9365acaca2fSWilliam A. Kennington III limit < sizeof(magic) || !POWER_OF_TWO(alignment)) 9375acaca2fSWilliam A. Kennington III { 9385acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_ARGUMENT; 9395acaca2fSWilliam A. Kennington III } 9405acaca2fSWilliam A. Kennington III 9415acaca2fSWilliam A. Kennington III if (!intf->read) 9425acaca2fSWilliam A. Kennington III { 943dca92e47SWilly Tu CPRINTS(ctx, "%s: missing intf->read\n", __FUNCTION__); 9445acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE; 9455acaca2fSWilliam A. Kennington III } 9465acaca2fSWilliam A. Kennington III // Align start_offset to the next valid boundary. 9475acaca2fSWilliam A. Kennington III start_offset = ((start_offset - 1) & ~(alignment - 1)) + alignment; 9485acaca2fSWilliam A. Kennington III for (offset = start_offset; offset < limit - sizeof(magic); 9495acaca2fSWilliam A. Kennington III offset += alignment) 9505acaca2fSWilliam A. Kennington III { 951*0155b431SDan Zhang rv = intf->read(ctx, offset, sizeof(read_data), (uint8_t*)&read_data); 9525acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 9535acaca2fSWilliam A. Kennington III { 9545acaca2fSWilliam A. Kennington III return rv; 9555acaca2fSWilliam A. Kennington III } 9565acaca2fSWilliam A. Kennington III if (read_data == magic) 9575acaca2fSWilliam A. Kennington III { 9585acaca2fSWilliam A. Kennington III if (header_offset) 9595acaca2fSWilliam A. Kennington III { 9605acaca2fSWilliam A. Kennington III *header_offset = offset; 9615acaca2fSWilliam A. Kennington III } 9625acaca2fSWilliam A. Kennington III return LIBCR51SIGN_SUCCESS; 9635acaca2fSWilliam A. Kennington III } 9645acaca2fSWilliam A. Kennington III } 9655acaca2fSWilliam A. Kennington III // Failed to locate magic. 9665acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC; 9675acaca2fSWilliam A. Kennington III } 9685acaca2fSWilliam A. Kennington III 9695acaca2fSWilliam A. Kennington III // Check whether the signature on the image is valid. 9705acaca2fSWilliam A. Kennington III // Validates the authenticity of an EEPROM image. Scans for & validates the 971dca92e47SWilly Tu // signature on the image descriptor. If the descriptor validates, hashes the 972dca92e47SWilly Tu // rest of the image to verify its integrity. 9735acaca2fSWilliam A. Kennington III // 974dca92e47SWilly Tu // @param[in] ctx - context which describes the image and holds opaque private 9755acaca2fSWilliam A. Kennington III // data for the user of the library 9765acaca2fSWilliam A. Kennington III // @param[in] intf - function pointers which interface to the current system 9775acaca2fSWilliam A. Kennington III // and environment 978dca92e47SWilly Tu // @param[out] image_regions - image_region pointer to an array for the output 979dca92e47SWilly Tu // 9805acaca2fSWilliam A. Kennington III // @return nonzero on error, zero on success 9815acaca2fSWilliam A. Kennington III 982c66ebc35SPatrick Williams failure_reason libcr51sign_validate( 983027c042eSDan Zhang struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf, 9845acaca2fSWilliam A. Kennington III struct libcr51sign_validated_regions* image_regions) 9855acaca2fSWilliam A. Kennington III { 9865acaca2fSWilliam A. Kennington III int rv, rv_first_desc = LIBCR51SIGN_SUCCESS; 9875acaca2fSWilliam A. Kennington III uint32_t descriptor_offset; 988dca92e47SWilly Tu uint32_t payload_blob_offset = 0; 9895acaca2fSWilliam A. Kennington III 9905acaca2fSWilliam A. Kennington III if (!ctx) 9915acaca2fSWilliam A. Kennington III { 992dca92e47SWilly Tu CPRINTS(ctx, "%s: Missing context\n", __FUNCTION__); 9935acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_CONTEXT; 9945acaca2fSWilliam A. Kennington III } 995027c042eSDan Zhang if (!intf) 9965acaca2fSWilliam A. Kennington III { 997dca92e47SWilly Tu CPRINTS(ctx, "%s: Missing interface\n", __FUNCTION__); 9985acaca2fSWilliam A. Kennington III return LIBCR51SIGN_ERROR_INVALID_INTERFACE; 9995acaca2fSWilliam A. Kennington III } 10005acaca2fSWilliam A. Kennington III 1001027c042eSDan Zhang ctx->validation_state = LIBCR51SIGN_IMAGE_INVALID; 1002027c042eSDan Zhang 10035acaca2fSWilliam A. Kennington III rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, ctx->start_offset, 10045acaca2fSWilliam A. Kennington III ctx->end_offset, DESCRIPTOR_ALIGNMENT, 10055acaca2fSWilliam A. Kennington III &descriptor_offset); 10065acaca2fSWilliam A. Kennington III while (rv == LIBCR51SIGN_SUCCESS) 10075acaca2fSWilliam A. Kennington III { 1008dca92e47SWilly Tu CPRINTS(ctx, "%s: potential image descriptor found @%x\n", __FUNCTION__, 10095acaca2fSWilliam A. Kennington III descriptor_offset); 1010dca92e47SWilly Tu // Validation is split into 3 functions to minimize stack usage. 10115acaca2fSWilliam A. Kennington III 1012dca92e47SWilly Tu rv = validate_descriptor( 1013dca92e47SWilly Tu ctx, intf, descriptor_offset, descriptor_offset - ctx->start_offset, 1014dca92e47SWilly Tu ctx->end_offset - ctx->start_offset, &payload_blob_offset); 10155acaca2fSWilliam A. Kennington III if (rv != LIBCR51SIGN_SUCCESS) 10165acaca2fSWilliam A. Kennington III { 1017dca92e47SWilly Tu CPRINTS(ctx, "%s: validate_descriptor() failed ec%d\n", 1018dca92e47SWilly Tu __FUNCTION__, rv); 10195acaca2fSWilliam A. Kennington III } 1020dca92e47SWilly Tu else 10215acaca2fSWilliam A. Kennington III { 10226084957fSPatrick Williams rv = validate_payload_regions_helper(ctx, intf, descriptor_offset, 10236084957fSPatrick Williams image_regions); 1024dca92e47SWilly Tu if (rv != LIBCR51SIGN_SUCCESS) 1025dca92e47SWilly Tu { 1026dca92e47SWilly Tu CPRINTS(ctx, "%s: validate_payload_regions() failed ec%d\n", 1027dca92e47SWilly Tu __FUNCTION__, rv); 1028dca92e47SWilly Tu } 1029dca92e47SWilly Tu else if (ctx->descriptor.image_type == IMAGE_PROD) 1030dca92e47SWilly Tu { 1031027c042eSDan Zhang ctx->validation_state = LIBCR51SIGN_IMAGE_VALID; 1032dca92e47SWilly Tu // Lookup and validate payload Image MAUV against Image MAUV 1033dca92e47SWilly Tu // stored in the system after checking signature to ensure 1034dca92e47SWilly Tu // offsets and sizes are not tampered with. Also, do this after 1035dca92e47SWilly Tu // hash calculation for payload regions to ensure that stored 1036dca92e47SWilly Tu // Image MAUV is updated (if necessary) as close to the end of 1037dca92e47SWilly Tu // payload validation as possible 1038dca92e47SWilly Tu rv = validate_payload_image_mauv(ctx, intf, payload_blob_offset, 1039dca92e47SWilly Tu ctx->descriptor.blob_size); 10405acaca2fSWilliam A. Kennington III if (rv == LIBCR51SIGN_SUCCESS) 10415acaca2fSWilliam A. Kennington III { 1042dca92e47SWilly Tu CPRINTS(ctx, 1043dca92e47SWilly Tu "%s: Payload Image MAUV validation successful\n", 1044dca92e47SWilly Tu __FUNCTION__); 10455acaca2fSWilliam A. Kennington III return rv; 10465acaca2fSWilliam A. Kennington III } 1047dca92e47SWilly Tu if (rv == LIBCR51SIGN_ERROR_STORING_NEW_IMAGE_MAUV_DATA) 1048dca92e47SWilly Tu { 1049dca92e47SWilly Tu CPRINTS( 1050dca92e47SWilly Tu ctx, 1051dca92e47SWilly Tu "%s: Payload validation succeeded, but Image MAUV validation " 1052dca92e47SWilly Tu "failed\n", 1053dca92e47SWilly Tu __FUNCTION__); 1054dca92e47SWilly Tu return LIBCR51SIGN_ERROR_VALID_IMAGE_BUT_NEW_IMAGE_MAUV_DATA_NOT_STORED; 10555acaca2fSWilliam A. Kennington III } 1056dca92e47SWilly Tu CPRINTS(ctx, "%s: Payload Image MAUV validation failed\n", 1057dca92e47SWilly Tu __FUNCTION__); 1058dca92e47SWilly Tu // In practice, we expect only 1 valid image descriptor in 1059dca92e47SWilly Tu // payload. If Image MAUV check fails for the payload after 1060dca92e47SWilly Tu // validating the image descriptor, do not try validating other 1061dca92e47SWilly Tu // image descriptors 1062dca92e47SWilly Tu return rv; 1063dca92e47SWilly Tu } 1064dca92e47SWilly Tu else 1065dca92e47SWilly Tu { 1066027c042eSDan Zhang ctx->validation_state = LIBCR51SIGN_IMAGE_VALID; 1067dca92e47SWilly Tu return rv; 1068dca92e47SWilly Tu } 1069dca92e47SWilly Tu } 1070dca92e47SWilly Tu 10715acaca2fSWilliam A. Kennington III // Store the first desc fail reason if any 10726084957fSPatrick Williams if (rv != LIBCR51SIGN_SUCCESS && rv_first_desc == LIBCR51SIGN_SUCCESS) 10735acaca2fSWilliam A. Kennington III rv_first_desc = rv; 10745acaca2fSWilliam A. Kennington III 10755acaca2fSWilliam A. Kennington III // scan_for_magic_8() will round up to the next aligned boundary. 10765acaca2fSWilliam A. Kennington III descriptor_offset++; 10776084957fSPatrick Williams rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, descriptor_offset, 1078dca92e47SWilly Tu ctx->end_offset, DESCRIPTOR_ALIGNMENT, 10796084957fSPatrick Williams &descriptor_offset); 10805acaca2fSWilliam A. Kennington III } 1081dca92e47SWilly Tu CPRINTS(ctx, "%s: failed to validate image ec%d\n", __FUNCTION__, rv); 10825acaca2fSWilliam A. Kennington III // If desc validation failed for some reason then return that reason 10835acaca2fSWilliam A. Kennington III if (rv_first_desc != LIBCR51SIGN_SUCCESS) 10845acaca2fSWilliam A. Kennington III return rv_first_desc; 1085027c042eSDan Zhang 10865acaca2fSWilliam A. Kennington III return rv; 10875acaca2fSWilliam A. Kennington III } 10885acaca2fSWilliam A. Kennington III 10895acaca2fSWilliam A. Kennington III // @func to returns the libcr51sign error code as a string 10905acaca2fSWilliam A. Kennington III // @param[in] ec - Error code 10915acaca2fSWilliam A. Kennington III // @return error code in string format 10925acaca2fSWilliam A. Kennington III 10935acaca2fSWilliam A. Kennington III const char* libcr51sign_errorcode_to_string(failure_reason ec) 10945acaca2fSWilliam A. Kennington III { 10955acaca2fSWilliam A. Kennington III switch (ec) 10965acaca2fSWilliam A. Kennington III { 10975acaca2fSWilliam A. Kennington III case LIBCR51SIGN_SUCCESS: 10985acaca2fSWilliam A. Kennington III return "Success"; 10995acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_RUNTIME_FAILURE: 11005acaca2fSWilliam A. Kennington III return "Runtime Error Failure"; 11015acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR: 11025acaca2fSWilliam A. Kennington III return "Unsupported descriptor"; 11035acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR: 11045acaca2fSWilliam A. Kennington III return "Invalid descriptor"; 11055acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY: 11065acaca2fSWilliam A. Kennington III return "Invalid image family"; 11075acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED: 11085acaca2fSWilliam A. Kennington III return "Image type disallowed"; 11095acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED: 11105acaca2fSWilliam A. Kennington III return "Dev downgrade disallowed"; 11115acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_UNTRUSTED_KEY: 11125acaca2fSWilliam A. Kennington III return "Untrusted key"; 11135acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_SIGNATURE: 11145acaca2fSWilliam A. Kennington III return "Invalid signature"; 11155acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_HASH: 11165acaca2fSWilliam A. Kennington III return "Invalid hash"; 11175acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_HASH_TYPE: 11185acaca2fSWilliam A. Kennington III return "Invalid hash type"; 11195acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_ARGUMENT: 11205acaca2fSWilliam A. Kennington III return "Invalid Argument"; 11215acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC: 11225acaca2fSWilliam A. Kennington III return "Failed to locate descriptor"; 11235acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_CONTEXT: 11245acaca2fSWilliam A. Kennington III return "Invalid context"; 11255acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_INTERFACE: 11265acaca2fSWilliam A. Kennington III return "Invalid interface"; 11275acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME: 11285acaca2fSWilliam A. Kennington III return "Invalid signature scheme"; 11295acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_REGION_INPUT: 11305acaca2fSWilliam A. Kennington III return "Invalid image region input"; 11315acaca2fSWilliam A. Kennington III case LIBCR51SIGN_ERROR_INVALID_REGION_SIZE: 11325acaca2fSWilliam A. Kennington III return "Invalid image region size"; 1133dca92e47SWilly Tu case LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA: 1134dca92e47SWilly Tu return "Invalid Image MAUV data"; 1135dca92e47SWilly Tu case LIBCR51SIGN_ERROR_RETRIEVING_STORED_IMAGE_MAUV_DATA: 1136dca92e47SWilly Tu return "Failed to retrieve Image MAUV data stored in system"; 1137dca92e47SWilly Tu case LIBCR51SIGN_ERROR_STORING_NEW_IMAGE_MAUV_DATA: 1138dca92e47SWilly Tu return "Failed to store Image MAUV data from payload image into system"; 1139dca92e47SWilly Tu case LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_DOES_NOT_ALLOW_UPDATE_TO_PAYLOAD: 1140dca92e47SWilly Tu return "Image MAUV stored in system does not allow payload " 1141dca92e47SWilly Tu "update"; 1142dca92e47SWilly Tu case LIBCR51SIGN_ERROR_VALID_IMAGE_BUT_NEW_IMAGE_MAUV_DATA_NOT_STORED: 1143dca92e47SWilly Tu return "Payload image is valid for update but failed to store new Image " 1144dca92e47SWilly Tu "MAUV in system"; 1145dca92e47SWilly Tu case LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_EXPECTS_PAYLOAD_IMAGE_MAUV: 1146dca92e47SWilly Tu return "Image MAUV is expected to be present in payload when stored " 1147dca92e47SWilly Tu "Image MAUV is present in the system"; 1148dca92e47SWilly Tu case LIBCR51SIGN_NO_STORED_MAUV_FOUND: 1149dca92e47SWilly Tu return "Client did not find any MAUV data stored in the system"; 1150027c042eSDan Zhang case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR_BLOBS: 1151027c042eSDan Zhang return "Invalid descriptor blobs"; 11525acaca2fSWilliam A. Kennington III default: 11535acaca2fSWilliam A. Kennington III return "Unknown error"; 11545acaca2fSWilliam A. Kennington III } 11555acaca2fSWilliam A. Kennington III } 11565acaca2fSWilliam A. Kennington III 11575acaca2fSWilliam A. Kennington III #ifdef __cplusplus 11585acaca2fSWilliam A. Kennington III } // extern "C" 11595acaca2fSWilliam A. Kennington III #endif 1160