1 /*
2 * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "config_tfm.h"
9 #include "tfm_plat_provisioning.h"
10
11 #include "cmsis_compiler.h"
12 #include "tfm_plat_otp.h"
13 #include "tfm_attest_hal.h"
14 #include "psa/crypto.h"
15 #include "tfm_spm_log.h"
16
17 #include <string.h>
18
19 #define ASSEMBLY_AND_TEST_PROV_DATA_MAGIC 0xC0DEFEED
20 #define PSA_ROT_PROV_DATA_MAGIC 0xBEEFFEED
21
22 __PACKED_STRUCT tfm_assembly_and_test_provisioning_data_t {
23 uint32_t magic;
24 uint8_t huk[32];
25 };
26
27 __PACKED_STRUCT tfm_psa_rot_provisioning_data_t {
28 uint32_t magic;
29 uint8_t iak[32];
30 uint32_t iak_len;
31 uint32_t iak_type;
32 #if ATTEST_INCLUDE_COSE_KEY_ID
33 uint8_t iak_id[32];
34 #endif /* ATTEST_INCLUDE_COSE_KEY_ID */
35
36 uint8_t boot_seed[32];
37 uint8_t implementation_id[32];
38 uint8_t cert_ref[32];
39 uint8_t verification_service_url[32];
40 uint8_t profile_definition[32];
41
42 uint8_t entropy_seed[64];
43 };
44
45 #ifdef TFM_DUMMY_PROVISIONING
46 static const struct tfm_assembly_and_test_provisioning_data_t assembly_and_test_prov_data = {
47 ASSEMBLY_AND_TEST_PROV_DATA_MAGIC,
48 /* HUK */
49 {
50 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
51 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
52 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
53 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
54 },
55 };
56
57 static const struct tfm_psa_rot_provisioning_data_t psa_rot_prov_data = {
58 PSA_ROT_PROV_DATA_MAGIC,
59 /* IAK */
60 {
61 0xA9, 0xB4, 0x54, 0xB2, 0x6D, 0x6F, 0x90, 0xA4,
62 0xEA, 0x31, 0x19, 0x35, 0x64, 0xCB, 0xA9, 0x1F,
63 0xEC, 0x6F, 0x9A, 0x00, 0x2A, 0x7D, 0xC0, 0x50,
64 0x4B, 0x92, 0xA1, 0x93, 0x71, 0x34, 0x58, 0x5F
65 },
66 /* IAK len */
67 32,
68 #ifdef SYMMETRIC_INITIAL_ATTESTATION
69 /* IAK type */
70 PSA_ALG_HMAC(PSA_ALG_SHA_256),
71 #else
72 /* IAK type */
73 PSA_ECC_FAMILY_SECP_R1,
74 #endif /* SYMMETRIC_INITIAL_ATTESTATION */
75 #if ATTEST_INCLUDE_COSE_KEY_ID
76 /* IAK id */
77 "kid@trustedfirmware.example",
78 #endif /* ATTEST_INCLUDE_COSE_KEY_ID */
79 /* boot seed */
80 {
81 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
82 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
83 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
84 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
85 },
86 /* implementation id */
87 {
88 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
89 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
90 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
91 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
92 },
93 /* certification reference */
94 "0604565272829-10010",
95 /* verification_service_url */
96 "www.trustedfirmware.org",
97 /* attestation_profile_definition */
98 #if ATTEST_TOKEN_PROFILE_PSA_IOT_1
99 "PSA_IOT_PROFILE_1",
100 #elif ATTEST_TOKEN_PROFILE_PSA_2_0_0
101 "http://arm.com/psa/2.0.0",
102 #elif ATTEST_TOKEN_PROFILE_ARM_CCA
103 "http://arm.com/CCA-SSD/1.0.0",
104 #else
105 #ifdef TFM_PARTITION_INITIAL_ATTESTATION
106 #error "Attestation token profile is incorrect"
107 #else
108 "UNDEFINED",
109 #endif /* TFM_PARTITION_INITIAL_ATTESTATION */
110 #endif
111 /* Entropy seed */
112 {
113 0x12, 0x13, 0x23, 0x34, 0x0a, 0x05, 0x89, 0x78,
114 0xa3, 0x66, 0x8c, 0x0d, 0x97, 0x55, 0x53, 0xca,
115 0xb5, 0x76, 0x18, 0x62, 0x29, 0xc6, 0xb6, 0x79,
116 0x75, 0xc8, 0x5a, 0x8d, 0x9e, 0x11, 0x8f, 0x85,
117 0xde, 0xc4, 0x5f, 0x66, 0x21, 0x52, 0xf9, 0x39,
118 0xd9, 0x77, 0x93, 0x28, 0xb0, 0x5e, 0x02, 0xfa,
119 0x58, 0xb4, 0x16, 0xc8, 0x0f, 0x38, 0x91, 0xbb,
120 0x28, 0x17, 0xcd, 0x8a, 0xc9, 0x53, 0x72, 0x66,
121 },
122 };
123 #else
124 static struct tfm_assembly_and_test_provisioning_data_t assembly_and_test_prov_data;
125 static struct tfm_psa_rot_provisioning_data_t psa_rot_prov_data;
126 #endif /* TFM_DUMMY_PROVISIONING */
127
tfm_plat_provisioning_check_for_dummy_keys(void)128 void tfm_plat_provisioning_check_for_dummy_keys(void)
129 {
130 uint64_t iak_start;
131
132 tfm_plat_otp_read(PLAT_OTP_ID_IAK, sizeof(iak_start), (uint8_t*)&iak_start);
133
134 if(iak_start == 0xA4906F6DB254B4A9) {
135 SPMLOG_ERRMSG("[WRN]\033[1;31m ");
136 SPMLOG_ERRMSG("This device was provisioned with dummy keys. ");
137 SPMLOG_ERRMSG("This device is \033[1;1mNOT SECURE");
138 SPMLOG_ERRMSG("\033[0m\r\n");
139 }
140
141 memset(&iak_start, 0, sizeof(iak_start));
142 }
143
tfm_plat_provisioning_is_required(void)144 int tfm_plat_provisioning_is_required(void)
145 {
146 enum tfm_plat_err_t err;
147 enum plat_otp_lcs_t lcs;
148
149 err = tfm_plat_otp_read(PLAT_OTP_ID_LCS, sizeof(lcs), (uint8_t*)&lcs);
150 if (err != TFM_PLAT_ERR_SUCCESS) {
151 return err;
152 }
153
154 return lcs == PLAT_OTP_LCS_ASSEMBLY_AND_TEST
155 || lcs == PLAT_OTP_LCS_PSA_ROT_PROVISIONING;
156 }
157
provision_assembly_and_test(void)158 enum tfm_plat_err_t provision_assembly_and_test(void)
159 {
160 enum tfm_plat_err_t err;
161 uint32_t new_lcs;
162
163 err = tfm_plat_otp_write(PLAT_OTP_ID_HUK, sizeof(assembly_and_test_prov_data.huk),
164 assembly_and_test_prov_data.huk);
165 if (err != TFM_PLAT_ERR_SUCCESS) {
166 return err;
167 }
168
169 new_lcs = PLAT_OTP_LCS_PSA_ROT_PROVISIONING;
170 err = tfm_plat_otp_write(PLAT_OTP_ID_LCS, sizeof(new_lcs),
171 (uint8_t*)&new_lcs);
172 if (err != TFM_PLAT_ERR_SUCCESS) {
173 return err;
174 }
175
176 return err;
177 }
178
provision_psa_rot(void)179 enum tfm_plat_err_t provision_psa_rot(void)
180 {
181 enum tfm_plat_err_t err;
182 uint32_t new_lcs;
183
184 err = tfm_plat_otp_write(PLAT_OTP_ID_IAK,
185 sizeof(psa_rot_prov_data.iak),
186 psa_rot_prov_data.iak);
187 if (err != TFM_PLAT_ERR_SUCCESS) {
188 return err;
189 }
190 err = tfm_plat_otp_write(PLAT_OTP_ID_IAK_LEN,
191 sizeof(psa_rot_prov_data.iak_len),
192 (uint8_t*)&psa_rot_prov_data.iak_len);
193 if (err != TFM_PLAT_ERR_SUCCESS) {
194 return err;
195 }
196 err = tfm_plat_otp_write(PLAT_OTP_ID_IAK_TYPE,
197 sizeof(psa_rot_prov_data.iak_type),
198 (uint8_t*)&psa_rot_prov_data.iak_type);
199 if (err != TFM_PLAT_ERR_SUCCESS) {
200 return err;
201 }
202
203 #if ATTEST_INCLUDE_COSE_KEY_ID
204 err = tfm_plat_otp_write(PLAT_OTP_ID_IAK_ID,
205 sizeof(psa_rot_prov_data.iak_id),
206 psa_rot_prov_data.iak_id);
207 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
208 return err;
209 }
210 #endif /* ATTEST_INCLUDE_COSE_KEY_ID */
211
212 err = tfm_plat_otp_write(PLAT_OTP_ID_BOOT_SEED,
213 sizeof(psa_rot_prov_data.boot_seed),
214 psa_rot_prov_data.boot_seed);
215 if (err != TFM_PLAT_ERR_SUCCESS) {
216 return err;
217 }
218 err = tfm_plat_otp_write(PLAT_OTP_ID_IMPLEMENTATION_ID,
219 sizeof(psa_rot_prov_data.implementation_id),
220 psa_rot_prov_data.implementation_id);
221 if (err != TFM_PLAT_ERR_SUCCESS) {
222 return err;
223 }
224 err = tfm_plat_otp_write(PLAT_OTP_ID_CERT_REF,
225 sizeof(psa_rot_prov_data.cert_ref),
226 psa_rot_prov_data.cert_ref);
227 if (err != TFM_PLAT_ERR_SUCCESS) {
228 return err;
229 }
230 err = tfm_plat_otp_write(PLAT_OTP_ID_VERIFICATION_SERVICE_URL,
231 sizeof(psa_rot_prov_data.verification_service_url),
232 psa_rot_prov_data.verification_service_url);
233 if (err != TFM_PLAT_ERR_SUCCESS) {
234 return err;
235 }
236 err = tfm_plat_otp_write(PLAT_OTP_ID_PROFILE_DEFINITION,
237 sizeof(psa_rot_prov_data.profile_definition),
238 psa_rot_prov_data.profile_definition);
239 if (err != TFM_PLAT_ERR_SUCCESS) {
240 return err;
241 }
242
243 err = tfm_plat_otp_write(PLAT_OTP_ID_ENTROPY_SEED,
244 sizeof(psa_rot_prov_data.entropy_seed),
245 psa_rot_prov_data.entropy_seed);
246 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
247 return err;
248 }
249
250 new_lcs = PLAT_OTP_LCS_SECURED;
251 err = tfm_plat_otp_write(PLAT_OTP_ID_LCS,
252 sizeof(new_lcs),
253 (uint8_t*)&new_lcs);
254 if (err != TFM_PLAT_ERR_SUCCESS) {
255 return err;
256 }
257
258 return err;
259 }
260
tfm_plat_provisioning_perform(void)261 enum tfm_plat_err_t tfm_plat_provisioning_perform(void)
262 {
263 enum tfm_plat_err_t err;
264 enum plat_otp_lcs_t lcs;
265
266 err = tfm_plat_otp_read(PLAT_OTP_ID_LCS, sizeof(lcs), (uint8_t*)&lcs);
267 if (err != TFM_PLAT_ERR_SUCCESS) {
268 return err;
269 }
270
271 SPMLOG_INFMSG("[INF] Beginning TF-M provisioning\r\n");
272
273 #ifdef TFM_DUMMY_PROVISIONING
274 SPMLOG_ERRMSG("[WRN]\033[1;31m ");
275 SPMLOG_ERRMSG("TFM_DUMMY_PROVISIONING is not suitable for production! ");
276 SPMLOG_ERRMSG("This device is \033[1;1mNOT SECURE");
277 SPMLOG_ERRMSG("\033[0m\r\n");
278 #endif /* TFM_DUMMY_PROVISIONING */
279
280 if (lcs == PLAT_OTP_LCS_ASSEMBLY_AND_TEST) {
281 if (assembly_and_test_prov_data.magic != ASSEMBLY_AND_TEST_PROV_DATA_MAGIC) {
282 SPMLOG_ERRMSG("No valid ASSEMBLY_AND_TEST provisioning data found\r\n");
283 return TFM_PLAT_ERR_INVALID_INPUT;
284 }
285
286 err = provision_assembly_and_test();
287 if (err != TFM_PLAT_ERR_SUCCESS) {
288 return err;
289 }
290 }
291
292 err = tfm_plat_otp_read(PLAT_OTP_ID_LCS, sizeof(lcs), (uint8_t*)&lcs);
293 if (err != TFM_PLAT_ERR_SUCCESS) {
294 return err;
295 }
296 if (lcs == PLAT_OTP_LCS_PSA_ROT_PROVISIONING) {
297 if (psa_rot_prov_data.magic != PSA_ROT_PROV_DATA_MAGIC) {
298 SPMLOG_ERRMSG("No valid PSA_ROT provisioning data found\r\n");
299 return TFM_PLAT_ERR_INVALID_INPUT;
300 }
301
302 err = provision_psa_rot();
303 if (err != TFM_PLAT_ERR_SUCCESS) {
304 return err;
305 }
306 }
307
308 return TFM_PLAT_ERR_SUCCESS;
309 }
310