1 /* 2 * Copyright (c) 2015-2023, 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/common/common_def.h> 17 #include <plat/common/platform.h> 18 #if defined(ARM_COT_cca) 19 #include <tools_share/cca_oid.h> 20 #elif defined(ARM_COT_dualroot) 21 #include <tools_share/dualroot_oid.h> 22 #elif defined(ARM_COT_tbbr) 23 #include <tools_share/tbbr_oid.h> 24 #endif 25 26 #include <plat/arm/common/fconf_nv_cntr_getter.h> 27 #include <plat/arm/common/plat_arm.h> 28 #include <platform_def.h> 29 30 #if !ARM_CRYPTOCELL_INTEG 31 #if !ARM_ROTPK_LOCATION_ID 32 #error "ARM_ROTPK_LOCATION_ID not defined" 33 #endif 34 #endif 35 36 #if COT_DESC_IN_DTB && defined(IMAGE_BL2) 37 uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS]; 38 #else 39 uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS] = { 40 TFW_NVCTR_BASE, 41 NTFW_CTR_BASE 42 }; 43 #endif 44 45 46 /* Weak definition may be overridden in specific platform */ 47 #pragma weak plat_get_nv_ctr 48 #pragma weak plat_set_nv_ctr 49 50 extern unsigned char arm_rotpk_header[], arm_rotpk_key[], arm_rotpk_hash_end[], 51 arm_rotpk_key_end[]; 52 53 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) || ARM_CRYPTOCELL_INTEG 54 static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN]; 55 #endif 56 57 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) 58 /* 59 * Return the ROTPK hash stored in dedicated registers. 60 */ 61 int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, 62 unsigned int *flags) 63 { 64 uint8_t *dst; 65 uint32_t *src, tmp; 66 unsigned int words, i; 67 68 assert(key_ptr != NULL); 69 assert(key_len != NULL); 70 assert(flags != NULL); 71 72 /* Copy the DER header */ 73 74 memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); 75 dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; 76 77 words = ARM_ROTPK_HASH_LEN >> 2; 78 79 src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; 80 for (i = 0 ; i < words ; i++) { 81 tmp = src[words - 1 - i]; 82 /* Words are read in little endian */ 83 *dst++ = (uint8_t)(tmp & 0xFF); 84 *dst++ = (uint8_t)((tmp >> 8) & 0xFF); 85 *dst++ = (uint8_t)((tmp >> 16) & 0xFF); 86 *dst++ = (uint8_t)((tmp >> 24) & 0xFF); 87 } 88 89 *key_ptr = (void *)rotpk_hash_der; 90 *key_len = (unsigned int)sizeof(rotpk_hash_der); 91 *flags = ROTPK_IS_HASH; 92 return 0; 93 } 94 #endif 95 96 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ 97 (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) 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_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_FULL_DEV_RSA_KEY_ID) || \ 109 (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_FULL_DEV_ECDSA_KEY_ID) 110 int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len, 111 unsigned int *flags) 112 { 113 *key_ptr = arm_rotpk_key; 114 *key_len = arm_rotpk_key_end - arm_rotpk_key; 115 *flags = 0; 116 return 0; 117 } 118 #endif 119 120 #if ARM_CRYPTOCELL_INTEG 121 /* 122 * Return ROTPK hash from CryptoCell. 123 */ 124 int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len, 125 unsigned int *flags) 126 { 127 unsigned char *dst; 128 129 assert(key_ptr != NULL); 130 assert(key_len != NULL); 131 assert(flags != NULL); 132 133 /* Copy the DER header */ 134 memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); 135 dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; 136 *key_ptr = rotpk_hash_der; 137 *key_len = sizeof(rotpk_hash_der); 138 return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags); 139 } 140 #endif 141 142 /* 143 * Wrapper function for most Arm platforms to get ROTPK info. 144 */ 145 static int get_rotpk_info(void **key_ptr, unsigned int *key_len, 146 unsigned int *flags) 147 { 148 #if ARM_CRYPTOCELL_INTEG 149 return arm_get_rotpk_info_cc(key_ptr, key_len, flags); 150 #else 151 152 #if ARM_USE_DEVEL_ROTPK 153 return arm_get_rotpk_info_dev(key_ptr, key_len, flags); 154 #elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) 155 return arm_get_rotpk_info_regs(key_ptr, key_len, flags); 156 #else 157 return 1; 158 #endif 159 #endif /* ARM_CRYPTOCELL_INTEG */ 160 } 161 162 #if defined(ARM_COT_tbbr) 163 164 int arm_get_rotpk_info(void *cookie __unused, void **key_ptr, 165 unsigned int *key_len, unsigned int *flags) 166 { 167 return get_rotpk_info(key_ptr, key_len, flags); 168 } 169 170 #elif defined(ARM_COT_dualroot) 171 172 int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, 173 unsigned int *flags) 174 { 175 /* 176 * Return the right root of trust key hash based on the cookie value: 177 * - NULL means the primary ROTPK. 178 * - Otherwise, interpret cookie as the OID of the certificate 179 * extension containing the key. 180 */ 181 if (cookie == NULL) { 182 return get_rotpk_info(key_ptr, key_len, flags); 183 } else if (strcmp(cookie, PROT_PK_OID) == 0) { 184 extern unsigned char arm_protpk_hash[]; 185 extern unsigned char arm_protpk_hash_end[]; 186 *key_ptr = arm_protpk_hash; 187 *key_len = arm_protpk_hash_end - arm_protpk_hash; 188 *flags = ROTPK_IS_HASH; 189 return 0; 190 } else { 191 /* Invalid key ID. */ 192 return 1; 193 } 194 } 195 196 #elif defined(ARM_COT_cca) 197 198 int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, 199 unsigned int *flags) 200 { 201 /* 202 * Return the right root of trust key hash based on the cookie value: 203 * - NULL means the primary ROTPK. 204 * - Otherwise, interpret cookie as the OID of the certificate 205 * extension containing the key. 206 */ 207 if (cookie == NULL) { 208 return get_rotpk_info(key_ptr, key_len, flags); 209 } else if (strcmp(cookie, PROT_PK_OID) == 0) { 210 extern unsigned char arm_protpk_hash[]; 211 extern unsigned char arm_protpk_hash_end[]; 212 *key_ptr = arm_protpk_hash; 213 *key_len = arm_protpk_hash_end - arm_protpk_hash; 214 *flags = ROTPK_IS_HASH; 215 return 0; 216 } else if (strcmp(cookie, SWD_ROT_PK_OID) == 0) { 217 extern unsigned char arm_swd_rotpk_hash[]; 218 extern unsigned char arm_swd_rotpk_hash_end[]; 219 *key_ptr = arm_swd_rotpk_hash; 220 *key_len = arm_swd_rotpk_hash_end - arm_swd_rotpk_hash; 221 *flags = ROTPK_IS_HASH; 222 return 0; 223 } else { 224 /* Invalid key ID. */ 225 return 1; 226 } 227 } 228 229 #endif 230 231 /* 232 * Return the non-volatile counter value stored in the platform. The cookie 233 * will contain the OID of the counter in the certificate. 234 * 235 * Return: 0 = success, Otherwise = error 236 */ 237 int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) 238 { 239 const char *oid; 240 uint32_t *nv_ctr_addr; 241 242 assert(cookie != NULL); 243 assert(nv_ctr != NULL); 244 245 oid = (const char *)cookie; 246 if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) { 247 nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr, 248 TRUSTED_NV_CTR_ID); 249 } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { 250 nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr, 251 NON_TRUSTED_NV_CTR_ID); 252 } else { 253 return 1; 254 } 255 256 *nv_ctr = (unsigned int)(*nv_ctr_addr); 257 258 return 0; 259 } 260 261 /* 262 * Store a new non-volatile counter value. By default on ARM development 263 * platforms, the non-volatile counters are RO and cannot be modified. We expect 264 * the values in the certificates to always match the RO values so that this 265 * function is never called. 266 * 267 * Return: 0 = success, Otherwise = error 268 */ 269 int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) 270 { 271 return 1; 272 } 273