1 /* 2 * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. 3 * Copyright 2017-2021 NXP 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 */ 8 9 #include <assert.h> 10 #include <stddef.h> 11 #include <stdint.h> 12 #include <string.h> 13 14 #include <arch_helpers.h> 15 #include <common/debug.h> 16 #include <csf_hdr.h> 17 #include <drivers/auth/crypto_mod.h> 18 #include <drivers/auth/img_parser_mod.h> 19 #include <lib/utils.h> 20 #include <sfp.h> 21 22 /* Temporary variables to speed up the authentication parameters search. These 23 * variables are assigned once during the integrity check and used any time an 24 * authentication parameter is requested, so we do not have to parse the image 25 * again. 26 */ 27 28 /* Hash of Image + CSF Header + SRK table */ 29 uint8_t img_hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE); 30 uint32_t hash_len; 31 32 /* Key being used for authentication 33 * Points to the key in CSF header copied in DDR 34 * ESBC client key 35 */ 36 void *img_key; 37 uint32_t key_len; 38 39 /* ESBC client signature */ 40 void *img_sign; 41 uint32_t sign_len; 42 enum sig_alg alg; 43 44 /* Maximum OID string length ("a.b.c.d.e.f ...") */ 45 #define MAX_OID_STR_LEN 64 46 47 #define LIB_NAME "NXP CSFv2" 48 49 /* 50 * Clear all static temporary variables. 51 */ 52 static void clear_temp_vars(void) 53 { 54 #define ZERO_AND_CLEAN(x) \ 55 do { \ 56 zeromem(&x, sizeof(x)); \ 57 clean_dcache_range((uintptr_t)&x, sizeof(x)); \ 58 } while (0) 59 60 ZERO_AND_CLEAN(img_key); 61 ZERO_AND_CLEAN(img_sign); 62 ZERO_AND_CLEAN(img_hash); 63 ZERO_AND_CLEAN(key_len); 64 ZERO_AND_CLEAN(hash_len); 65 ZERO_AND_CLEAN(sign_len); 66 67 #undef ZERO_AND_CLEAN 68 } 69 70 /* Exported functions */ 71 72 static void init(void) 73 { 74 clear_temp_vars(); 75 } 76 77 /* 78 * This function would check the integrity of the CSF header 79 */ 80 static int check_integrity(void *img, unsigned int img_len) 81 { 82 int ret; 83 84 /* 85 * The image file has been successfully loaded till here. 86 * 87 * Flush the image to main memory so that it can be authenticated 88 * by CAAM, a HW accelerator regardless of cache and MMU state. 89 */ 90 flush_dcache_range((uintptr_t) img, img_len); 91 92 /* 93 * Image is appended at an offset of 16K (IMG_OFFSET) to the header. 94 * So the size in header should be equal to img_len - IMG_OFFSET 95 */ 96 VERBOSE("Barker code is %x\n", *(unsigned int *)img); 97 ret = validate_esbc_header(img, &img_key, &key_len, &img_sign, 98 &sign_len, &alg); 99 if (ret < 0) { 100 ERROR("Header authentication failed\n"); 101 clear_temp_vars(); 102 return IMG_PARSER_ERR; 103 } 104 /* Calculate the hash of various components from the image */ 105 ret = calc_img_hash(img, (uint8_t *)img + CSF_HDR_SZ, 106 img_len - CSF_HDR_SZ, img_hash, &hash_len); 107 if (ret != 0) { 108 ERROR("Issue in hash calculation %d\n", ret); 109 clear_temp_vars(); 110 return IMG_PARSER_ERR; 111 } 112 113 return IMG_PARSER_OK; 114 } 115 116 /* 117 * Extract an authentication parameter from CSF header 118 * 119 * CSF header has already been parsed and the required information like 120 * hash of data, signature, length stored in global variables has been 121 * extracted in chek_integrity function. This data 122 * is returned back to the caller. 123 */ 124 static int get_auth_param(const auth_param_type_desc_t *type_desc, 125 void *img, unsigned int img_len, 126 void **param, unsigned int *param_len) 127 { 128 int rc = IMG_PARSER_OK; 129 130 /* We do not use img because the check_integrity function has already 131 * extracted the relevant data ( pk, sig_alg, etc) 132 */ 133 134 switch (type_desc->type) { 135 136 /* Hash will be returned for comparison with signature */ 137 case AUTH_PARAM_HASH: 138 *param = (void *)img_hash; 139 *param_len = (unsigned int)SHA256_BYTES; 140 break; 141 142 /* Return the public key used for signature extracted from the SRK table 143 * after checks with key revocation 144 */ 145 case AUTH_PARAM_PUB_KEY: 146 /* Get the subject public key */ 147 /* For a 1K key - the length would be 2k/8 = 0x100 bytes 148 * 2K RSA key - 0x200 , 4K RSA - 0x400 149 */ 150 *param = img_key; 151 *param_len = (unsigned int)key_len; 152 break; 153 154 /* Call a function to tell if signature is RSA or ECDSA. ECDSA to be 155 * supported in later platforms like LX2 etc 156 */ 157 case AUTH_PARAM_SIG_ALG: 158 /* Algo will be signature - RSA or ECDSA on hash */ 159 *param = (void *)&alg; 160 *param_len = 4U; 161 break; 162 163 /* Return the signature */ 164 case AUTH_PARAM_SIG: 165 *param = img_sign; 166 *param_len = (unsigned int)sign_len; 167 break; 168 169 case AUTH_PARAM_NV_CTR: 170 171 default: 172 rc = IMG_PARSER_ERR_NOT_FOUND; 173 break; 174 } 175 176 return rc; 177 } 178 179 REGISTER_IMG_PARSER_LIB(IMG_PLAT, LIB_NAME, init, 180 check_integrity, get_auth_param); 181