/* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. * Copyright 2017-2021 NXP * * SPDX-License-Identifier: BSD-3-Clause * */ #include #include #include #include #include #include #include #include #include #include #include /* Temporary variables to speed up the authentication parameters search. These * variables are assigned once during the integrity check and used any time an * authentication parameter is requested, so we do not have to parse the image * again. */ /* Hash of Image + CSF Header + SRK table */ uint8_t img_hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE); uint32_t hash_len; /* Key being used for authentication * Points to the key in CSF header copied in DDR * ESBC client key */ void *img_key; uint32_t key_len; /* ESBC client signature */ void *img_sign; uint32_t sign_len; enum sig_alg alg; /* Maximum OID string length ("a.b.c.d.e.f ...") */ #define MAX_OID_STR_LEN 64 #define LIB_NAME "NXP CSFv2" /* * Clear all static temporary variables. */ static void clear_temp_vars(void) { #define ZERO_AND_CLEAN(x) \ do { \ zeromem(&x, sizeof(x)); \ clean_dcache_range((uintptr_t)&x, sizeof(x)); \ } while (0) ZERO_AND_CLEAN(img_key); ZERO_AND_CLEAN(img_sign); ZERO_AND_CLEAN(img_hash); ZERO_AND_CLEAN(key_len); ZERO_AND_CLEAN(hash_len); ZERO_AND_CLEAN(sign_len); #undef ZERO_AND_CLEAN } /* Exported functions */ static void init(void) { clear_temp_vars(); } /* * This function would check the integrity of the CSF header */ static int check_integrity(void *img, unsigned int img_len) { int ret; /* * The image file has been successfully loaded till here. * * Flush the image to main memory so that it can be authenticated * by CAAM, a HW accelerator regardless of cache and MMU state. */ flush_dcache_range((uintptr_t) img, img_len); /* * Image is appended at an offset of 16K (IMG_OFFSET) to the header. * So the size in header should be equal to img_len - IMG_OFFSET */ VERBOSE("Barker code is %x\n", *(unsigned int *)img); ret = validate_esbc_header(img, &img_key, &key_len, &img_sign, &sign_len, &alg); if (ret < 0) { ERROR("Header authentication failed\n"); clear_temp_vars(); return IMG_PARSER_ERR; } /* Calculate the hash of various components from the image */ ret = calc_img_hash(img, (uint8_t *)img + CSF_HDR_SZ, img_len - CSF_HDR_SZ, img_hash, &hash_len); if (ret != 0) { ERROR("Issue in hash calculation %d\n", ret); clear_temp_vars(); return IMG_PARSER_ERR; } return IMG_PARSER_OK; } /* * Extract an authentication parameter from CSF header * * CSF header has already been parsed and the required information like * hash of data, signature, length stored in global variables has been * extracted in chek_integrity function. This data * is returned back to the caller. */ static int get_auth_param(const auth_param_type_desc_t *type_desc, void *img, unsigned int img_len, void **param, unsigned int *param_len) { int rc = IMG_PARSER_OK; /* We do not use img because the check_integrity function has already * extracted the relevant data ( pk, sig_alg, etc) */ switch (type_desc->type) { /* Hash will be returned for comparison with signature */ case AUTH_PARAM_HASH: *param = (void *)img_hash; *param_len = (unsigned int)SHA256_BYTES; break; /* Return the public key used for signature extracted from the SRK table * after checks with key revocation */ case AUTH_PARAM_PUB_KEY: /* Get the subject public key */ /* For a 1K key - the length would be 2k/8 = 0x100 bytes * 2K RSA key - 0x200 , 4K RSA - 0x400 */ *param = img_key; *param_len = (unsigned int)key_len; break; /* Call a function to tell if signature is RSA or ECDSA. ECDSA to be * supported in later platforms like LX2 etc */ case AUTH_PARAM_SIG_ALG: /* Algo will be signature - RSA or ECDSA on hash */ *param = (void *)&alg; *param_len = 4U; break; /* Return the signature */ case AUTH_PARAM_SIG: *param = img_sign; *param_len = (unsigned int)sign_len; break; case AUTH_PARAM_NV_CTR: default: rc = IMG_PARSER_ERR_NOT_FOUND; break; } return rc; } REGISTER_IMG_PARSER_LIB(IMG_PLAT, LIB_NAME, init, check_integrity, get_auth_param);