blob: 64ca3c36d8c705e969ed3e939252ca8709624f75 [file] [log] [blame]
Dan Handley9df48042015-03-19 18:58:55 +00001/*
Masahiro Yamadad1f97752017-05-23 19:41:36 +09002 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
Dan Handley9df48042015-03-19 18:58:55 +00003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Dan Handley9df48042015-03-19 18:58:55 +00005 */
6
Juan Castillo31a68f02015-04-14 12:49:03 +01007#include <assert.h>
Juan Castillo31a68f02015-04-14 12:49:03 +01008#include <stdint.h>
9#include <string.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
11#include <lib/cassert.h>
12#include <plat/common/platform.h>
13#include <tools_share/tbbr_oid.h>
14
15#include <arm_def.h>
Juan Castillo31a68f02015-04-14 12:49:03 +010016
Juan Castillo31a68f02015-04-14 12:49:03 +010017/* SHA256 algorithm */
18#define SHA256_BYTES 32
19
20/* ROTPK locations */
21#define ARM_ROTPK_REGS_ID 1
22#define ARM_ROTPK_DEVEL_RSA_ID 2
Qixiang Xu1c2aef12017-08-24 15:12:20 +080023#define ARM_ROTPK_DEVEL_ECDSA_ID 3
Juan Castillo31a68f02015-04-14 12:49:03 +010024
Juan Castillo31a68f02015-04-14 12:49:03 +010025static const unsigned char rotpk_hash_hdr[] = \
26 "\x30\x31\x30\x0D\x06\x09\x60\x86\x48" \
27 "\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
28static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1;
29static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES];
30
Soby Mathew3e6bbda2017-06-02 17:44:07 +010031/* Use the cryptocell variants if Cryptocell is present */
32#if !ARM_CRYPTOCELL_INTEG
33#if !ARM_ROTPK_LOCATION_ID
34 #error "ARM_ROTPK_LOCATION_ID not defined"
35#endif
36
37/* Weak definition may be overridden in specific platform */
38#pragma weak plat_get_nv_ctr
39#pragma weak plat_set_nv_ctr
40
Juan Castillo31a68f02015-04-14 12:49:03 +010041#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
42static const unsigned char arm_devel_rotpk_hash[] = \
43 "\xB0\xF3\x82\x09\x12\x97\xD8\x3A" \
44 "\x37\x7A\x72\x47\x1B\xEC\x32\x73" \
45 "\xE9\x92\x32\xE2\x49\x59\xF6\x5E" \
46 "\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA";
Qixiang Xu1c2aef12017-08-24 15:12:20 +080047#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
48static const unsigned char arm_devel_rotpk_hash[] = \
49 "\x2E\x40\xBF\x6E\xF9\x12\xBB\x98" \
50 "\x31\x71\x09\x0E\x1E\x15\x3D\x0B" \
51 "\xFD\xD1\xCC\x69\x4A\x98\xEB\x8B" \
52 "\xA0\xB0\x20\x86\x4E\x6C\x07\x17";
Juan Castillo31a68f02015-04-14 12:49:03 +010053#endif
54
Dan Handley9df48042015-03-19 18:58:55 +000055/*
Juan Castillo31a68f02015-04-14 12:49:03 +010056 * Return the ROTPK hash in the following ASN.1 structure in DER format:
57 *
58 * AlgorithmIdentifier ::= SEQUENCE {
59 * algorithm OBJECT IDENTIFIER,
60 * parameters ANY DEFINED BY algorithm OPTIONAL
61 * }
62 *
63 * DigestInfo ::= SEQUENCE {
64 * digestAlgorithm AlgorithmIdentifier,
65 * digest OCTET STRING
66 * }
67 */
68int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
69 unsigned int *flags)
70{
71 uint8_t *dst;
72
73 assert(key_ptr != NULL);
74 assert(key_len != NULL);
75 assert(flags != NULL);
76
77 /* Copy the DER header */
78 memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
79 dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len];
80
Qixiang Xu1c2aef12017-08-24 15:12:20 +080081#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
82 || (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
Juan Castillo31a68f02015-04-14 12:49:03 +010083 memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES);
84#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
85 uint32_t *src, tmp;
86 unsigned int words, i;
87
88 /*
89 * Append the hash from Trusted Root-Key Storage registers. The hash has
90 * not been written linearly into the registers, so we have to do a bit
91 * of byte swapping:
92 *
93 * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C
94 * +---------------------------------------------------------------+
95 * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 |
96 * +---------------------------------------------------------------+
97 * | ... ... | | ... ... |
98 * | +--------------------+ | +-------+
99 * | | | |
100 * +----------------------------+ +----------------------------+
101 * | | | |
102 * +-------+ | +--------------------+ |
103 * | | | |
104 * v v v v
105 * +---------------------------------------------------------------+
106 * | | |
107 * +---------------------------------------------------------------+
108 * 0 15 16 31
109 *
110 * Additionally, we have to access the registers in 32-bit words
111 */
112 words = SHA256_BYTES >> 3;
113
114 /* Swap bytes 0-15 (first four registers) */
115 src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
116 for (i = 0 ; i < words ; i++) {
117 tmp = src[words - 1 - i];
118 /* Words are read in little endian */
119 *dst++ = (uint8_t)((tmp >> 24) & 0xFF);
120 *dst++ = (uint8_t)((tmp >> 16) & 0xFF);
121 *dst++ = (uint8_t)((tmp >> 8) & 0xFF);
122 *dst++ = (uint8_t)(tmp & 0xFF);
123 }
124
125 /* Swap bytes 16-31 (last four registers) */
126 src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2);
127 for (i = 0 ; i < words ; i++) {
128 tmp = src[words - 1 - i];
129 *dst++ = (uint8_t)((tmp >> 24) & 0xFF);
130 *dst++ = (uint8_t)((tmp >> 16) & 0xFF);
131 *dst++ = (uint8_t)((tmp >> 8) & 0xFF);
132 *dst++ = (uint8_t)(tmp & 0xFF);
133 }
Qixiang Xu1c2aef12017-08-24 15:12:20 +0800134#endif /* (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
135 || (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) */
Juan Castillo31a68f02015-04-14 12:49:03 +0100136
137 *key_ptr = (void *)rotpk_hash_der;
138 *key_len = (unsigned int)sizeof(rotpk_hash_der);
139 *flags = ROTPK_IS_HASH;
140 return 0;
141}
142
Juan Castillobfb7fa62016-01-22 11:05:57 +0000143/*
144 * Return the non-volatile counter value stored in the platform. The cookie
145 * will contain the OID of the counter in the certificate.
146 *
147 * Return: 0 = success, Otherwise = error
148 */
149int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
150{
151 const char *oid;
152 uint32_t *nv_ctr_addr;
153
154 assert(cookie != NULL);
155 assert(nv_ctr != NULL);
156
157 oid = (const char *)cookie;
158 if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
159 nv_ctr_addr = (uint32_t *)TFW_NVCTR_BASE;
160 } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
161 nv_ctr_addr = (uint32_t *)NTFW_CTR_BASE;
162 } else {
163 return 1;
164 }
165
166 *nv_ctr = (unsigned int)(*nv_ctr_addr);
167
168 return 0;
169}
170
171/*
Antonio Nino Diaz9d602fe2016-05-20 14:14:16 +0100172 * Store a new non-volatile counter value. By default on ARM development
173 * platforms, the non-volatile counters are RO and cannot be modified. We expect
174 * the values in the certificates to always match the RO values so that this
175 * function is never called.
Juan Castillobfb7fa62016-01-22 11:05:57 +0000176 *
177 * Return: 0 = success, Otherwise = error
178 */
179int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
180{
181 return 1;
182}
Soby Mathew3e6bbda2017-06-02 17:44:07 +0100183#else /* ARM_CRYPTOCELL_INTEG */
184
Antonio Nino Diaze0f90632018-12-14 00:18:21 +0000185#include <drivers/arm/cryptocell/nvm.h>
186#include <drivers/arm/cryptocell/nvm_otp.h>
187#include <drivers/arm/cryptocell/sbrom_bsv_api.h>
Soby Mathew3e6bbda2017-06-02 17:44:07 +0100188
189CASSERT(HASH_RESULT_SIZE_IN_BYTES == SHA256_BYTES,
190 assert_mismatch_in_hash_result_size);
191
192/*
193 * Return the ROTPK hash in the following ASN.1 structure in DER format:
194 *
195 * AlgorithmIdentifier ::= SEQUENCE {
196 * algorithm OBJECT IDENTIFIER,
197 * parameters ANY DEFINED BY algorithm OPTIONAL
198 * }
199 *
200 * DigestInfo ::= SEQUENCE {
201 * digestAlgorithm AlgorithmIdentifier,
202 * digest OCTET STRING
203 * }
204 */
205int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
206 unsigned int *flags)
207{
208 unsigned char *dst;
209 CCError_t error;
210 uint32_t lcs;
211
212 assert(key_ptr != NULL);
213 assert(key_len != NULL);
214 assert(flags != NULL);
215
216 error = NVM_GetLCS(PLAT_CRYPTOCELL_BASE, &lcs);
217 if (error != CC_OK)
218 return 1;
219
220 /* If the lifecycle state is `SD`, return failure */
221 if (lcs == CC_BSV_SECURITY_DISABLED_LCS)
222 return 1;
223
224 /*
225 * If the lifecycle state is `CM` or `DM`, ROTPK shouldn't be verified.
226 * Return success after setting ROTPK_NOT_DEPLOYED flag
227 */
228 if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) ||
229 (lcs == CC_BSV_DEVICE_MANUFACTURE_LCS)) {
230 *key_len = 0;
231 *flags = ROTPK_NOT_DEPLOYED;
232 return 0;
233 }
234
235 /* Copy the DER header */
236 memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
237 dst = &rotpk_hash_der[rotpk_hash_hdr_len];
238 error = NVM_ReadHASHPubKey(PLAT_CRYPTOCELL_BASE,
239 CC_SB_HASH_BOOT_KEY_256B,
240 (uint32_t *)dst, HASH_RESULT_SIZE_IN_WORDS);
241 if (error != CC_OK)
242 return 1;
243
244 *key_ptr = rotpk_hash_der;
245 *key_len = sizeof(rotpk_hash_der);
246 *flags = ROTPK_IS_HASH;
247 return 0;
248}
249
250/*
251 * Return the non-volatile counter value stored in the platform. The cookie
252 * specifies the OID of the counter in the certificate.
253 *
254 * Return: 0 = success, Otherwise = error
255 */
256int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
257{
258 CCError_t error = CC_FAIL;
259
260 if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) {
261 error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE,
262 CC_SW_VERSION_COUNTER1, nv_ctr);
263 } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
264 error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE,
265 CC_SW_VERSION_COUNTER2, nv_ctr);
266 }
267
268 return (error != CC_OK);
269}
270
271/*
272 * Store a new non-volatile counter value in the counter specified by the OID
273 * in the cookie. This function is not expected to be called if the Lifecycle
274 * state is RMA as the values in the certificate are expected to always match
275 * the nvcounter values. But if called when the LCS is RMA, the underlying
276 * helper functions will return success but without updating the counter.
277 *
278 * Return: 0 = success, Otherwise = error
279 */
280int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
281{
282 CCError_t error = CC_FAIL;
283
284 if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) {
285 error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE,
286 CC_SW_VERSION_COUNTER1, nv_ctr);
287 } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
288 error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE,
289 CC_SW_VERSION_COUNTER2, nv_ctr);
290 }
291
292 return (error != CC_OK);
293}
294
295#endif /* ARM_CRYPTOCELL_INTEG */