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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 224 int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) 225 { 226 return 1; 227 } 228