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