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