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  */
clear_temp_vars(void)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 
init(void)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  */
check_integrity(void * img,unsigned int img_len)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  */
get_auth_param(const auth_param_type_desc_t * type_desc,void * img,unsigned int img_len,void ** param,unsigned int * param_len)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