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