1 /*
2 * Copyright (c) 2018-2024, 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_nv_counters.h"
15
16 #include <limits.h>
17 #include "Driver_Flash.h"
18 #include "flash_layout.h"
19 #include "tfm_plat_otp.h"
20 #include "cmsis_compiler.h"
21 #include "device_definition.h"
22
23 #include <string.h>
24
25 #define OTP_COUNTER_MAX_SIZE (16u * sizeof(uint32_t))
26 #define NV_COUNTER_SIZE 4
27 #define OTP_COUNTER_MAGIC 0x3333CAFE
28
tfm_plat_init_nv_counter(void)29 enum tfm_plat_err_t tfm_plat_init_nv_counter(void)
30 {
31 return TFM_PLAT_ERR_SUCCESS;
32 }
33
34 #ifdef INTEGRITY_CHECKER_S
count_zero_bits(const uint32_t * addr,uint32_t len,uint32_t * zero_bits)35 static enum tfm_plat_err_t count_zero_bits(const uint32_t *addr, uint32_t len,
36 uint32_t *zero_bits)
37 {
38 enum integrity_checker_error_t ic_err;
39
40 ic_err = integrity_checker_compute_value(&INTEGRITY_CHECKER_DEV_S,
41 INTEGRITY_CHECKER_MODE_ZERO_COUNT,
42 addr, len, zero_bits, sizeof(uint32_t),
43 NULL);
44
45 if (ic_err == INTEGRITY_CHECKER_ERROR_NONE) {
46 return TFM_PLAT_ERR_SUCCESS;
47 } else {
48 return TFM_PLAT_ERR_SYSTEM_ERR;
49 }
50 }
51 #else
count_zero_bits(const uint32_t * addr,uint32_t len,uint32_t * zero_bits)52 static enum tfm_plat_err_t count_zero_bits(const uint32_t *addr, uint32_t len,
53 uint32_t *zero_bits)
54 {
55 uint32_t idx;
56 uint32_t word;
57 uint32_t bit_index;
58
59 *zero_bits = 0;
60
61 for (idx = 0; idx < len / sizeof(uint32_t); idx ++) {
62 word = addr[idx];
63
64 for (bit_index = 0; bit_index < sizeof(word) * 8; bit_index++) {
65 *zero_bits += 1 - ((word >> bit_index) & 1);
66 }
67 }
68
69 return TFM_PLAT_ERR_SUCCESS;
70 }
71 #endif /* INTEGRITY_CHECKER_DEV_S */
72
73 #ifdef RSE_BIT_PROGRAMMABLE_OTP
read_otp_counter(enum tfm_otp_element_id_t id,uint8_t * val)74 static enum tfm_plat_err_t read_otp_counter(enum tfm_otp_element_id_t id,
75 uint8_t *val)
76 {
77 size_t counter_size;
78 enum tfm_plat_err_t err;
79 uint32_t counter_value[OTP_COUNTER_MAX_SIZE / sizeof(uint32_t)] = {0};
80 uint32_t count;
81
82 err = tfm_plat_otp_get_size(id, &counter_size);
83 if (err != TFM_PLAT_ERR_SUCCESS) {
84 return err;
85 }
86
87 counter_size = counter_size > OTP_COUNTER_MAX_SIZE ? OTP_COUNTER_MAX_SIZE
88 : counter_size;
89
90 err = tfm_plat_otp_read(id, counter_size, (uint8_t *)counter_value);
91 if (err != TFM_PLAT_ERR_SUCCESS) {
92 return err;
93 }
94
95 err = count_zero_bits(counter_value, counter_size, &count);
96 if (err != TFM_PLAT_ERR_SUCCESS) {
97 return err;
98 }
99
100 count = (counter_size * 8) - count;
101
102 memcpy(val, &count, NV_COUNTER_SIZE);
103
104 return TFM_PLAT_ERR_SUCCESS;
105 }
106 #else
read_otp_counter(enum tfm_otp_element_id_t id,uint8_t * val)107 static enum tfm_plat_err_t read_otp_counter(enum tfm_otp_element_id_t id,
108 uint8_t *val)
109 {
110 size_t counter_size;
111 enum tfm_plat_err_t err;
112 size_t idx;
113 uint32_t counter_value[OTP_COUNTER_MAX_SIZE / sizeof(uint32_t)] = {0};
114 uint32_t count;
115
116 err = tfm_plat_otp_get_size(id, &counter_size);
117 if (err != TFM_PLAT_ERR_SUCCESS) {
118 return err;
119 }
120
121 counter_size = counter_size > OTP_COUNTER_MAX_SIZE ? OTP_COUNTER_MAX_SIZE
122 : counter_size;
123
124 err = tfm_plat_otp_read(id, counter_size, (uint8_t *)counter_value);
125 if (err != TFM_PLAT_ERR_SUCCESS) {
126 return err;
127 }
128
129 count = 0;
130 for (idx = 0; idx < counter_size / sizeof(uint32_t); idx++) {
131 if (counter_value[idx] == OTP_COUNTER_MAGIC) {
132 count += 1;
133 } else if (counter_value[idx] == 0) {
134 break;
135 } else {
136 return TFM_PLAT_ERR_SYSTEM_ERR;
137 }
138 }
139
140 memcpy(val, &count, NV_COUNTER_SIZE);
141
142 return TFM_PLAT_ERR_SUCCESS;
143 }
144 #endif /* RSE_BIT_PROGRAMMABLE_OTP */
145
tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,uint32_t size,uint8_t * val)146 enum tfm_plat_err_t tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,
147 uint32_t size, uint8_t *val)
148 {
149 if (size != NV_COUNTER_SIZE) {
150 return TFM_PLAT_ERR_SYSTEM_ERR;
151 }
152
153 /* Assumes Platform nv counters are contiguous*/
154 if (counter_id >= PLAT_NV_COUNTER_BL2_0 &&
155 counter_id < (PLAT_NV_COUNTER_BL2_0 + MCUBOOT_IMAGE_NUMBER)) {
156 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_BL2_0 +
157 (counter_id - PLAT_NV_COUNTER_BL2_0),
158 val);
159 }
160
161 switch (counter_id) {
162 #ifdef PLATFORM_HAS_PS_NV_OTP_COUNTERS
163 case (PLAT_NV_COUNTER_PS_0):
164 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_PS_0, val);
165 case (PLAT_NV_COUNTER_PS_1):
166 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_PS_1, val);
167 case (PLAT_NV_COUNTER_PS_2):
168 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_PS_2, val);
169 #endif /* PLATFORM_HAS_PS_NV_OTP_COUNTERS */
170 case (PLAT_NV_COUNTER_NS_0):
171 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_0, val);
172 case (PLAT_NV_COUNTER_NS_1):
173 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_1, val);
174 case (PLAT_NV_COUNTER_NS_2):
175 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_2, val);
176
177 case (PLAT_NV_COUNTER_BL1_0):
178 return read_otp_counter(PLAT_OTP_ID_NV_COUNTER_BL1_0, val);
179
180 default:
181 return TFM_PLAT_ERR_UNSUPPORTED;
182 }
183 }
184
185
186 #ifdef RSE_BIT_PROGRAMMABLE_OTP
set_otp_counter(enum tfm_otp_element_id_t id,uint32_t val)187 static enum tfm_plat_err_t set_otp_counter(enum tfm_otp_element_id_t id,
188 uint32_t val)
189 {
190 size_t counter_size;
191 enum tfm_plat_err_t err;
192 size_t idx;
193 uint32_t counter_value[OTP_COUNTER_MAX_SIZE / sizeof(uint32_t)] = {0};
194
195 err = tfm_plat_otp_get_size(id, &counter_size);
196 if (err != TFM_PLAT_ERR_SUCCESS) {
197 return err;
198 }
199
200 counter_size = counter_size > OTP_COUNTER_MAX_SIZE ? OTP_COUNTER_MAX_SIZE
201 : counter_size;
202
203 if (val > counter_size * 8) {
204 return TFM_PLAT_ERR_MAX_VALUE;
205 }
206
207 for (idx = 0; idx < val / 32; idx++) {
208 counter_value[idx] = 0xFFFFFFFFu;
209 }
210
211 if (val % 32 != 0) {
212 counter_value[idx] = (1 << (val % 32)) - 1;
213 }
214
215 err = tfm_plat_otp_write(id, sizeof(counter_value),
216 (uint8_t *)counter_value);
217
218 return err;
219 }
220 #else
set_otp_counter(enum tfm_otp_element_id_t id,uint32_t val)221 static enum tfm_plat_err_t set_otp_counter(enum tfm_otp_element_id_t id,
222 uint32_t val)
223 {
224 size_t counter_size;
225 enum tfm_plat_err_t err;
226 size_t idx;
227 uint32_t counter_value[OTP_COUNTER_MAX_SIZE / sizeof(uint32_t)] = {0};
228
229 err = tfm_plat_otp_get_size(id, &counter_size);
230 if (err != TFM_PLAT_ERR_SUCCESS) {
231 return err;
232 }
233
234 counter_size = counter_size > OTP_COUNTER_MAX_SIZE ? OTP_COUNTER_MAX_SIZE
235 : counter_size;
236
237 if (val > counter_size) {
238 return TFM_PLAT_ERR_MAX_VALUE;
239 }
240
241 for (idx = 0; idx < val; idx++) {
242 counter_value[idx] = OTP_COUNTER_MAGIC;
243 }
244
245 err = tfm_plat_otp_write(id, sizeof(counter_value),
246 (uint8_t *)counter_value);
247
248 return err;
249 }
250 #endif /* RSE_BIT_PROGRAMMABLE_OTP */
251
tfm_plat_set_nv_counter(enum tfm_nv_counter_t counter_id,uint32_t value)252 enum tfm_plat_err_t tfm_plat_set_nv_counter(enum tfm_nv_counter_t counter_id,
253 uint32_t value)
254 {
255 /* Assumes Platform nv counters are contiguous*/
256 if (counter_id >= PLAT_NV_COUNTER_BL2_0 &&
257 counter_id < (PLAT_NV_COUNTER_BL2_0 + MCUBOOT_IMAGE_NUMBER)) {
258 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_BL2_0 +
259 (counter_id - PLAT_NV_COUNTER_BL2_0),
260 value);
261 }
262
263 switch (counter_id) {
264 #ifdef PLATFORM_HAS_PS_NV_OTP_COUNTERS
265 case (PLAT_NV_COUNTER_PS_0):
266 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_PS_0, value);
267 case (PLAT_NV_COUNTER_PS_1):
268 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_PS_1, value);
269 case (PLAT_NV_COUNTER_PS_2):
270 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_PS_2, value);
271 #endif /* PLATFORM_HAS_PS_NV_OTP_COUNTERS */
272
273 case (PLAT_NV_COUNTER_NS_0):
274 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_0, value);
275 case (PLAT_NV_COUNTER_NS_1):
276 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_1, value);
277 case (PLAT_NV_COUNTER_NS_2):
278 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_NS_2, value);
279
280 case (PLAT_NV_COUNTER_BL1_0):
281 return set_otp_counter(PLAT_OTP_ID_NV_COUNTER_BL1_0, value);
282
283 default:
284 return TFM_PLAT_ERR_UNSUPPORTED;
285 }
286 }
287
tfm_plat_increment_nv_counter(enum tfm_nv_counter_t counter_id)288 enum tfm_plat_err_t tfm_plat_increment_nv_counter(
289 enum tfm_nv_counter_t counter_id)
290 {
291 uint32_t security_cnt;
292 enum tfm_plat_err_t err;
293
294 err = tfm_plat_read_nv_counter(counter_id,
295 sizeof(security_cnt),
296 (uint8_t *)&security_cnt);
297 if (err != TFM_PLAT_ERR_SUCCESS) {
298 return err;
299 }
300
301 if (security_cnt == UINT32_MAX) {
302 return TFM_PLAT_ERR_MAX_VALUE;
303 }
304
305 return tfm_plat_set_nv_counter(counter_id, security_cnt + 1u);
306 }
307