blob: 64c38582d803fc1756edf885eaafef28d1a0ee84 [file] [log] [blame]
Raef Coles148b9472021-06-18 08:48:17 +01001/*
2 * Copyright (c) 2021, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8/* NOTE: For the security of the protected storage system, the bootloader
9 * rollback protection, and the protection of cryptographic material it is
10 * CRITICAL to use a internal (in-die) persistent memory for the implementation
11 * of the OTP_NV_COUNTERS flash area (see flash_otp_nv_layout.c).
12 */
13
14#include "tfm_plat_otp.h"
15
16#include "flash_layout.h"
17#include "flash_otp_nv_counters_backend.h"
18#include <string.h>
19#include <stddef.h>
20
21enum tfm_plat_err_t tfm_plat_otp_init(void)
22{
23 return init_otp_nv_counters_flash();
24}
25
26static enum tfm_plat_err_t write_to_output(enum tfm_otp_element_id_t id,
27 uint32_t offset, size_t out_len,
28 uint8_t *out)
29{
30 enum tfm_plat_err_t err = TFM_PLAT_ERR_SUCCESS;
31 size_t value_size;
32 size_t copy_size;
33
34 err = tfm_plat_otp_get_size(id, &value_size);
35 if (err != TFM_PLAT_ERR_SUCCESS) {
36 return err;
37 }
38
39 copy_size = out_len < value_size ? out_len : value_size;
40
41 err = read_otp_nv_counters_flash(offset, out, copy_size);
42 if (err != TFM_PLAT_ERR_SUCCESS) {
43 return err;
44 }
45
46 return TFM_PLAT_ERR_SUCCESS;
47}
48
49enum tfm_plat_err_t tfm_plat_otp_read(enum tfm_otp_element_id_t id,
50 size_t out_len, uint8_t *out)
51{
52 switch (id) {
53 case PLAT_OTP_ID_HUK:
54 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, huk), out_len, out);
55 case PLAT_OTP_ID_IAK:
56 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, iak), out_len, out);
57 case PLAT_OTP_ID_IAK_LEN:
58 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, iak_len), out_len, out);
59 case PLAT_OTP_ID_IAK_TYPE:
60 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, iak_type), out_len, out);
61 case PLAT_OTP_ID_IAK_ID:
62 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, iak_id), out_len, out);
63
64 case PLAT_OTP_ID_BOOT_SEED:
65 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, boot_seed), out_len, out);
66 case PLAT_OTP_ID_LCS:
67 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, lcs), out_len, out);
68 case PLAT_OTP_ID_IMPLEMENTATION_ID:
69 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, implementation_id), out_len, out);
70 case PLAT_OTP_ID_HW_VERSION:
71 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, hw_version), out_len, out);
72 case PLAT_OTP_ID_VERIFICATION_SERVICE_URL:
73 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, verification_service_url), out_len, out);
74 case PLAT_OTP_ID_PROFILE_DEFINITION:
75 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, profile_definition), out_len, out);
76
77#ifdef BL2
78 case PLAT_OTP_ID_BL2_ROTPK_0:
79 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_rotpk_0), out_len, out);
80 case PLAT_OTP_ID_BL2_ROTPK_1:
81 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_rotpk_1), out_len, out);
82 case PLAT_OTP_ID_BL2_ROTPK_2:
83 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_rotpk_2), out_len, out);
84
85 case PLAT_OTP_ID_NV_COUNTER_BL2_0:
86 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_nv_counter_0), out_len, out);
87 case PLAT_OTP_ID_NV_COUNTER_BL2_1:
88 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_nv_counter_1), out_len, out);
89 case PLAT_OTP_ID_NV_COUNTER_BL2_2:
90 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_nv_counter_2), out_len, out);
91#endif /* BL2 */
92
93#ifdef BL1
94 case PLAT_OTP_ID_BL1_ROTPK_0:
95 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl1_rotpk_0), out_len, out);
96
97 case PLAT_OTP_ID_NV_COUNTER_BL1_0:
98 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, bl1_nv_counter_0), out_len, out);
99#endif /* BL1 */
100
101 case PLAT_OTP_ID_ENTROPY_SEED:
102 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, entropy_seed), out_len, out);
103
Satish Kumara5312fd2021-10-26 07:08:57 +0100104 case PLAT_OTP_ID_SECURE_DEBUG_PK:
105 return write_to_output(id, offsetof(struct flash_otp_nv_counters_region_t, secure_debug_pk), out_len, out);
106
Raef Coles148b9472021-06-18 08:48:17 +0100107 default:
108 return TFM_PLAT_ERR_UNSUPPORTED;
109 }
110}
111
Michel Jaouend0fd8d92021-10-14 09:22:41 +0200112#if defined(OTP_WRITEABLE)
Raef Coles148b9472021-06-18 08:48:17 +0100113static enum tfm_plat_err_t read_from_input(enum tfm_otp_element_id_t id,
114 uint32_t offset, size_t in_len,
115 const uint8_t *in)
116{
117 enum tfm_plat_err_t err = TFM_PLAT_ERR_SUCCESS;
118 size_t value_size;
Raef Coles148b9472021-06-18 08:48:17 +0100119 uint8_t buffer[in_len];
120 size_t idx;
121
122 err = tfm_plat_otp_get_size(id, &value_size);
123 if (err != TFM_PLAT_ERR_SUCCESS) {
124 return err;
125 }
126
Raef Coles8018e6b2021-11-17 10:55:01 +0000127 if (in_len > value_size) {
128 return TFM_PLAT_ERR_INVALID_INPUT;
129 }
Raef Coles148b9472021-06-18 08:48:17 +0100130
Raef Coles8018e6b2021-11-17 10:55:01 +0000131 err = read_otp_nv_counters_flash(offset, buffer, in_len);
Raef Coles148b9472021-06-18 08:48:17 +0100132 if (err != TFM_PLAT_ERR_SUCCESS) {
133 return err;
134 }
135
Raef Coles8018e6b2021-11-17 10:55:01 +0000136 for (idx = 0; idx < in_len; idx++) {
Raef Coles148b9472021-06-18 08:48:17 +0100137 if ((buffer[idx] | in[idx]) != in[idx]) {
138 return TFM_PLAT_ERR_INVALID_INPUT;
139 }
140
141 buffer[idx] |= in[idx];
142 }
143
Raef Coles8018e6b2021-11-17 10:55:01 +0000144 err = write_otp_nv_counters_flash(offset, buffer, in_len);
Raef Coles148b9472021-06-18 08:48:17 +0100145 if (err != TFM_PLAT_ERR_SUCCESS) {
146 return err;
147 }
148
149 return TFM_PLAT_ERR_SUCCESS;
150}
151
152enum tfm_plat_err_t tfm_plat_otp_write(enum tfm_otp_element_id_t id,
153 size_t in_len, const uint8_t *in)
154{
155 switch (id) {
156 case PLAT_OTP_ID_HUK:
157 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, huk), in_len, in);
158 case PLAT_OTP_ID_IAK:
159 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, iak), in_len, in);
160 case PLAT_OTP_ID_IAK_LEN:
161 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, iak_len), in_len, in);
162 case PLAT_OTP_ID_IAK_TYPE:
163 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, iak_type), in_len, in);
164 case PLAT_OTP_ID_IAK_ID:
165 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, iak_id), in_len, in);
166
167 case PLAT_OTP_ID_BOOT_SEED:
168 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, boot_seed), in_len, in);
169 case PLAT_OTP_ID_LCS:
170 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, lcs), in_len, in);
171 case PLAT_OTP_ID_IMPLEMENTATION_ID:
172 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, implementation_id), in_len, in);
173 case PLAT_OTP_ID_HW_VERSION:
174 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, hw_version), in_len, in);
175 case PLAT_OTP_ID_VERIFICATION_SERVICE_URL:
176 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, verification_service_url), in_len, in);
177 case PLAT_OTP_ID_PROFILE_DEFINITION:
178 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, profile_definition), in_len, in);
179
180#ifdef BL2
181 case PLAT_OTP_ID_BL2_ROTPK_0:
182 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_rotpk_0), in_len, in);
183 case PLAT_OTP_ID_BL2_ROTPK_1:
184 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_rotpk_1), in_len, in);
185 case PLAT_OTP_ID_BL2_ROTPK_2:
186 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_rotpk_2), in_len, in);
187
188 case PLAT_OTP_ID_NV_COUNTER_BL2_0:
189 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_nv_counter_0), in_len, in);
190 case PLAT_OTP_ID_NV_COUNTER_BL2_1:
191 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_nv_counter_1), in_len, in);
192 case PLAT_OTP_ID_NV_COUNTER_BL2_2:
193 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl2_nv_counter_2), in_len, in);
194#endif /* Bl2 */
195
196#ifdef BL1
197 case PLAT_OTP_ID_BL1_ROTPK_0:
198 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl1_rotpk_0), in_len, in);
199
200 case PLAT_OTP_ID_NV_COUNTER_BL1_0:
201 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, bl1_nv_counter_0), in_len, in);
202#endif /* BL1 */
203
204 case PLAT_OTP_ID_ENTROPY_SEED:
205 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, entropy_seed), in_len, in);
206
Satish Kumara5312fd2021-10-26 07:08:57 +0100207 case PLAT_OTP_ID_SECURE_DEBUG_PK:
208 return read_from_input(id, offsetof(struct flash_otp_nv_counters_region_t, secure_debug_pk), in_len, in);
209
Raef Coles148b9472021-06-18 08:48:17 +0100210 default:
211 return TFM_PLAT_ERR_UNSUPPORTED;
212 }
213}
Michel Jaouend0fd8d92021-10-14 09:22:41 +0200214#else
215enum tfm_plat_err_t tfm_plat_otp_write(enum tfm_otp_element_id_t id,
216 size_t in_len, const uint8_t *in)
217{
218 (void)id;
219 (void)in_len;
220 (void)in;
221 return TFM_PLAT_ERR_UNSUPPORTED;
222}
223#endif
Raef Coles148b9472021-06-18 08:48:17 +0100224
225enum tfm_plat_err_t tfm_plat_otp_get_size(enum tfm_otp_element_id_t id,
226 size_t *size)
227{
228 switch (id) {
229 case PLAT_OTP_ID_HUK:
230 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->huk);
231 break;
232 case PLAT_OTP_ID_IAK:
233 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->iak);
234 break;
235 case PLAT_OTP_ID_IAK_LEN:
236 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->iak_len);
237 break;
238 case PLAT_OTP_ID_IAK_TYPE:
239 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->iak_type);
240 break;
241 case PLAT_OTP_ID_IAK_ID:
242 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->iak_id);
243 break;
244
245 case PLAT_OTP_ID_BOOT_SEED:
246 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->boot_seed);
247 break;
248 case PLAT_OTP_ID_LCS:
249 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->lcs);
250 break;
251 case PLAT_OTP_ID_IMPLEMENTATION_ID:
252 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->implementation_id);
253 break;
254 case PLAT_OTP_ID_HW_VERSION:
255 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->hw_version);
256 break;
257 case PLAT_OTP_ID_VERIFICATION_SERVICE_URL:
258 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->verification_service_url);
259 break;
260 case PLAT_OTP_ID_PROFILE_DEFINITION:
261 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->profile_definition);
262 break;
263
264#ifdef BL2
265 case PLAT_OTP_ID_BL2_ROTPK_0:
266 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl2_rotpk_0);
267 break;
268 case PLAT_OTP_ID_BL2_ROTPK_1:
269 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl2_rotpk_1);
270 break;
271 case PLAT_OTP_ID_BL2_ROTPK_2:
272 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl2_rotpk_2);
273 break;
274
275 case PLAT_OTP_ID_NV_COUNTER_BL2_0:
276 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl2_nv_counter_0);
277 break;
278 case PLAT_OTP_ID_NV_COUNTER_BL2_1:
279 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl2_nv_counter_1);
280 break;
281 case PLAT_OTP_ID_NV_COUNTER_BL2_2:
282 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl2_nv_counter_2);
283 break;
284#endif /* BL2 */
285
286#ifdef BL1
287 case PLAT_OTP_ID_BL1_ROTPK_0:
288 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl1_rotpk_0);
289 break;
290
291 case PLAT_OTP_ID_NV_COUNTER_BL1_0:
292 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->bl1_nv_counter_0);
293 break;
294#endif /* BL1 */
295
296 case PLAT_OTP_ID_ENTROPY_SEED:
297 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->entropy_seed);
298 break;
299
Satish Kumara5312fd2021-10-26 07:08:57 +0100300 case PLAT_OTP_ID_SECURE_DEBUG_PK:
301 *size = sizeof(((struct flash_otp_nv_counters_region_t*)0)->secure_debug_pk);
302 break;
303
Raef Coles148b9472021-06-18 08:48:17 +0100304 default:
305 return TFM_PLAT_ERR_UNSUPPORTED;
306 }
307
308 return TFM_PLAT_ERR_SUCCESS;
309}