1 /*
2  * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include <common/debug.h>
12 #include <drivers/arm/cryptocell/cc_rotpk.h>
13 #include <drivers/delay_timer.h>
14 #include <lib/cassert.h>
15 #include <lib/fconf/fconf.h>
16 #include <plat/arm/common/plat_arm.h>
17 #include <plat/arm/common/fconf_nv_cntr_getter.h>
18 #include <plat/common/common_def.h>
19 #include <plat/common/platform.h>
20 #include <platform_def.h>
21 
22 #if defined(ARM_COT_tbbr)
23 #include <tools_share/tbbr_oid.h>
24 #elif defined(ARM_COT_dualroot)
25 #include <tools_share/dualroot_oid.h>
26 #endif
27 
28 #if !ARM_CRYPTOCELL_INTEG
29 #if !ARM_ROTPK_LOCATION_ID
30   #error "ARM_ROTPK_LOCATION_ID not defined"
31 #endif
32 #endif
33 
34 #if COT_DESC_IN_DTB && defined(IMAGE_BL2)
35 uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS];
36 #else
37 uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS] = {
38 	TFW_NVCTR_BASE,
39 	NTFW_CTR_BASE
40 };
41 #endif
42 
43 
44 /* Weak definition may be overridden in specific platform */
45 #pragma weak plat_get_nv_ctr
46 #pragma weak plat_set_nv_ctr
47 
48 extern unsigned char arm_rotpk_header[], arm_rotpk_hash_end[];
49 
50 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) || ARM_CRYPTOCELL_INTEG
51 static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
52 #endif
53 
54 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
55 /*
56  * Return the ROTPK hash stored in dedicated registers.
57  */
arm_get_rotpk_info_regs(void ** key_ptr,unsigned int * key_len,unsigned int * flags)58 int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
59 			unsigned int *flags)
60 {
61 	uint8_t *dst;
62 	uint32_t *src, tmp;
63 	unsigned int words, i;
64 
65 	assert(key_ptr != NULL);
66 	assert(key_len != NULL);
67 	assert(flags != NULL);
68 
69 	/* Copy the DER header */
70 
71 	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
72 	dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
73 
74 	words = ARM_ROTPK_HASH_LEN >> 2;
75 
76 	src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
77 	for (i = 0 ; i < words ; i++) {
78 		tmp = src[words - 1 - i];
79 		/* Words are read in little endian */
80 		*dst++ = (uint8_t)(tmp & 0xFF);
81 		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
82 		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
83 		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
84 	}
85 
86 	*key_ptr = (void *)rotpk_hash_der;
87 	*key_len = (unsigned int)sizeof(rotpk_hash_der);
88 	*flags = ROTPK_IS_HASH;
89 	return 0;
90 }
91 #endif
92 
93 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
94     (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
95 /*
96  * Return development ROTPK hash generated from ROT_KEY.
97  */
arm_get_rotpk_info_dev(void ** key_ptr,unsigned int * key_len,unsigned int * flags)98 int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len,
99 			unsigned int *flags)
100 {
101 	*key_ptr = arm_rotpk_header;
102 	*key_len = arm_rotpk_hash_end - arm_rotpk_header;
103 	*flags = ROTPK_IS_HASH;
104 	return 0;
105 }
106 #endif
107 
108 #if ARM_CRYPTOCELL_INTEG
109 /*
110  * Return ROTPK hash from CryptoCell.
111  */
arm_get_rotpk_info_cc(void ** key_ptr,unsigned int * key_len,unsigned int * flags)112 int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len,
113 			unsigned int *flags)
114 {
115 	unsigned char *dst;
116 
117 	assert(key_ptr != NULL);
118 	assert(key_len != NULL);
119 	assert(flags != NULL);
120 
121 	/* Copy the DER header */
122 	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
123 	dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
124 	*key_ptr = rotpk_hash_der;
125 	*key_len = sizeof(rotpk_hash_der);
126 	return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags);
127 }
128 #endif
129 
130 /*
131  * Wrapper function for most Arm platforms to get ROTPK hash.
132  */
get_rotpk_info(void ** key_ptr,unsigned int * key_len,unsigned int * flags)133 static int get_rotpk_info(void **key_ptr, unsigned int *key_len,
134 				unsigned int *flags)
135 {
136 #if ARM_CRYPTOCELL_INTEG
137 	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
138 #else
139 
140 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
141     (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
142 	return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
143 #elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
144 	return arm_get_rotpk_info_regs(key_ptr, key_len, flags);
145 #else
146 	return 1;
147 #endif
148 #endif /* ARM_CRYPTOCELL_INTEG */
149 }
150 
151 #if defined(ARM_COT_tbbr)
152 
arm_get_rotpk_info(void * cookie __unused,void ** key_ptr,unsigned int * key_len,unsigned int * flags)153 int arm_get_rotpk_info(void *cookie __unused, void **key_ptr,
154 		       unsigned int *key_len, unsigned int *flags)
155 {
156 	return get_rotpk_info(key_ptr, key_len, flags);
157 }
158 
159 #elif defined(ARM_COT_dualroot)
160 
arm_get_rotpk_info(void * cookie,void ** key_ptr,unsigned int * key_len,unsigned int * flags)161 int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
162 		       unsigned int *flags)
163 {
164 	/*
165 	 * Return the right root of trust key hash based on the cookie value:
166 	 *  - NULL means the primary ROTPK.
167 	 *  - Otherwise, interpret cookie as the OID of the certificate
168 	 *    extension containing the key.
169 	 */
170 	if (cookie == NULL) {
171 		return get_rotpk_info(key_ptr, key_len, flags);
172 	} else if (strcmp(cookie, PROT_PK_OID) == 0) {
173 		extern unsigned char arm_protpk_hash[];
174 		extern unsigned char arm_protpk_hash_end[];
175 		*key_ptr = arm_protpk_hash;
176 		*key_len = arm_protpk_hash_end - arm_protpk_hash;
177 		*flags = ROTPK_IS_HASH;
178 		return 0;
179 	} else {
180 		/* Invalid key ID. */
181 		return 1;
182 	}
183 }
184 #endif
185 
186 /*
187  * Return the non-volatile counter value stored in the platform. The cookie
188  * will contain the OID of the counter in the certificate.
189  *
190  * Return: 0 = success, Otherwise = error
191  */
plat_get_nv_ctr(void * cookie,unsigned int * nv_ctr)192 int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
193 {
194 	const char *oid;
195 	uint32_t *nv_ctr_addr;
196 
197 	assert(cookie != NULL);
198 	assert(nv_ctr != NULL);
199 
200 	oid = (const char *)cookie;
201 	if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
202 		nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr,
203 							TRUSTED_NV_CTR_ID);
204 	} else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
205 		nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr,
206 							NON_TRUSTED_NV_CTR_ID);
207 	} else {
208 		return 1;
209 	}
210 
211 	*nv_ctr = (unsigned int)(*nv_ctr_addr);
212 
213 	return 0;
214 }
215 
216 /*
217  * Store a new non-volatile counter value. By default on ARM development
218  * platforms, the non-volatile counters are RO and cannot be modified. We expect
219  * the values in the certificates to always match the RO values so that this
220  * function is never called.
221  *
222  * Return: 0 = success, Otherwise = error
223  */
plat_set_nv_ctr(void * cookie,unsigned int nv_ctr)224 int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
225 {
226 	return 1;
227 }
228