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