nRF Connect SDK API 0.1.0
Loading...
Searching...
No Matches
bl_storage.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5 */
6
7#ifndef BL_STORAGE_H_
8#define BL_STORAGE_H_
9
10#include <string.h>
11#include <zephyr/types.h>
12#include <drivers/nrfx_common.h>
13#include <nrfx_nvmc.h>
14#include <errno.h>
15#include <pm_config.h>
16
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22#define EHASHFF 113 /* A hash contains too many 0xFs. */
23#define EREADLCS 114 /* LCS field of OTP is in an invalid state */
24#define EINVALIDLCS 115 /* Invalid LCS*/
25
26/* We truncate the 32 byte sha256 down to 16 bytes before storing it */
27#define SB_PUBLIC_KEY_HASH_LEN 16
28
29/* Counter used by NSIB to check the firmware version */
30#define BL_MONOTONIC_COUNTERS_DESC_NSIB 0x1
31
32/* Counter used by MCUBOOT to check the firmware version. Suffixed
33 * with ID0 as we might support checking the version of multiple
34 * images in the future.
35 */
36#define BL_MONOTONIC_COUNTERS_DESC_MCUBOOT_ID0 0x2
37
49 uint16_t provisioning;
50 uint16_t secure;
51 /* Pad to end the alignment at a 4-byte boundary as the UICR->OTP
52 * only supports 4-byte reads. We place the reserved padding in
53 * the middle of the struct in case we ever need to support
54 * another state.
55 */
58};
59
65 /* NB: When placed in OTP, reads must be 4 bytes and 4 byte aligned */
67 uint8_t implementation_id[32];
68 uint32_t s0_address;
69 uint32_t s1_address;
70 uint32_t num_public_keys; /* Number of entries in 'key_data' list. */
71 struct {
72 uint32_t valid;
75};
76
77#define BL_STORAGE ((const volatile struct bl_storage_data *)(PM_PROVISION_ADDRESS))
78
79/* This must be 32 bytes according to the IETF PSA token specification */
80#define BL_STORAGE_IMPLEMENTATION_ID_SIZE 32
81
91uint32_t s0_address_read(void);
92
98uint32_t s1_address_read(void);
99
105uint32_t num_public_keys_read(void);
106
114
125int public_key_data_read(uint32_t key_idx, uint8_t *p_buf);
126
134void invalidate_public_key(uint32_t key_idx);
135
146int num_monotonic_counter_slots(uint16_t counter_desc, uint16_t *counter_slots);
147
158int get_monotonic_counter(uint16_t counter_desc, uint16_t *counter_value);
159
177int set_monotonic_counter(uint16_t counter_desc, uint16_t new_counter);
178
184enum lcs {
190};
191
200NRFX_STATIC_INLINE void otp_copy32(uint8_t *restrict dst, uint32_t volatile * restrict src,
201 size_t size)
202{
203 for (int i = 0; i < size / 4; i++) {
204 /* OTP is in UICR */
205 uint32_t val = nrfx_nvmc_uicr_word_read(src + i);
206
207 for (int j = 0; j < 4; j++) {
208 dst[i * 4 + j] = (val >> 8 * j) & 0xFF;
209 }
210 }
211}
217NRFX_STATIC_INLINE void read_implementation_id_from_otp(uint8_t *buf)
218{
219 if (buf == NULL) {
220 return;
221 }
222
223 otp_copy32(buf, (uint32_t *)&BL_STORAGE->implementation_id,
225}
226
227/* The OTP is 0xFFFF when erased and, like all flash, can only flip
228 * bits from 0 to 1 when erasing. By setting all bits to zero we
229 * enforce the correct transitioning of LCS until a full erase of the
230 * device.
231 */
232#define STATE_ENTERED 0x0000
233#define STATE_NOT_ENTERED 0xFFFF
234
235/* The bl_storage functions below are static inline in the header file
236 * so that TF-M (that does not include bl_storage.c) can also have
237 * access to them.
238 * This is a temporary solution until TF-M has access to NSIB functions.
239 */
240
249NRFX_STATIC_INLINE int read_life_cycle_state(enum lcs *lcs)
250{
251 if (lcs == NULL) {
252 return -EINVAL;
253 }
254
255 uint16_t provisioning = nrfx_nvmc_otp_halfword_read(
256 (uint32_t) &BL_STORAGE->lcs.provisioning);
257 uint16_t secure = nrfx_nvmc_otp_halfword_read((uint32_t) &BL_STORAGE->lcs.secure);
258 uint16_t decommissioned = nrfx_nvmc_otp_halfword_read(
259 (uint32_t) &BL_STORAGE->lcs.decommissioned);
260
261 if (provisioning == STATE_NOT_ENTERED
262 && secure == STATE_NOT_ENTERED
263 && decommissioned == STATE_NOT_ENTERED) {
265 } else if (provisioning == STATE_ENTERED
266 && secure == STATE_NOT_ENTERED
267 && decommissioned == STATE_NOT_ENTERED) {
269 } else if (provisioning == STATE_ENTERED
270 && secure == STATE_ENTERED
271 && decommissioned == STATE_NOT_ENTERED) {
273 } else if (provisioning == STATE_ENTERED
274 && secure == STATE_ENTERED
275 && decommissioned == STATE_ENTERED) {
277 } else {
278 /* To reach this the OTP must be corrupted or reading failed */
279 return -EREADLCS;
280 }
281
282 return 0;
283}
284
295NRFX_STATIC_INLINE int update_life_cycle_state(enum lcs next_lcs)
296{
297 int err;
298 enum lcs current_lcs = 0;
299
300 if (next_lcs == BL_STORAGE_LCS_UNKNOWN) {
301 return -EINVALIDLCS;
302 }
303
304 err = read_life_cycle_state(&current_lcs);
305 if (err != 0) {
306 return err;
307 }
308
309 if (next_lcs < current_lcs) {
310 /* Is is only possible to transition into a higher state */
311 return -EINVALIDLCS;
312 }
313
314 if (next_lcs == current_lcs) {
315 /* The same LCS is a valid argument, but nothing to do so return success */
316 return 0;
317 }
318
319 /* As the device starts in ASSEMBLY, it is not possible to write it */
320 if (current_lcs == BL_STORAGE_LCS_ASSEMBLY && next_lcs == BL_STORAGE_LCS_PROVISIONING) {
321 nrfx_nvmc_halfword_write((uint32_t)&BL_STORAGE->lcs.provisioning, STATE_ENTERED);
322 return 0;
323 }
324
325 if (current_lcs == BL_STORAGE_LCS_PROVISIONING && next_lcs == BL_STORAGE_LCS_SECURED) {
326 nrfx_nvmc_halfword_write((uint32_t)&BL_STORAGE->lcs.secure, STATE_ENTERED);
327 return 0;
328 }
329
330 if (current_lcs == BL_STORAGE_LCS_SECURED && next_lcs == BL_STORAGE_LCS_DECOMMISSIONED) {
331 nrfx_nvmc_halfword_write((uint32_t)&BL_STORAGE->lcs.decommissioned, STATE_ENTERED);
332 return 0;
333 }
334
335 /* This will be the case if any invalid transition is tried */
336 return -EINVALIDLCS;
337}
338
341#ifdef __cplusplus
342}
343#endif
344
345#endif /* BL_STORAGE_H_ */
#define SB_PUBLIC_KEY_HASH_LEN
Definition: bl_storage.h:27
#define EREADLCS
Definition: bl_storage.h:23
#define BL_STORAGE
Definition: bl_storage.h:77
#define EINVALIDLCS
Definition: bl_storage.h:24
#define BL_STORAGE_IMPLEMENTATION_ID_SIZE
Definition: bl_storage.h:80
#define STATE_ENTERED
Definition: bl_storage.h:232
int verify_public_keys(void)
Function for reading number of public key data slots.
uint32_t s0_address_read(void)
Function for reading address of slot 0.
uint32_t num_public_keys_read(void)
Function for reading number of public key data slots.
#define STATE_NOT_ENTERED
Definition: bl_storage.h:233
void otp_copy32(uint8_t *restrict dst, uint32_t volatile *restrict src, size_t size)
Definition: bl_storage.h:200
int read_life_cycle_state(enum lcs *lcs)
Read the current life cycle state the device is in from OTP,.
Definition: bl_storage.h:249
void invalidate_public_key(uint32_t key_idx)
Function for invalidating a public key.
int num_monotonic_counter_slots(uint16_t counter_desc, uint16_t *counter_slots)
Get the number of monotonic counter slots.
int update_life_cycle_state(enum lcs next_lcs)
Update the life cycle state in OTP.
Definition: bl_storage.h:295
int public_key_data_read(uint32_t key_idx, uint8_t *p_buf)
Function for reading public key hashes.
uint32_t s1_address_read(void)
Function for reading address of slot 1.
int set_monotonic_counter(uint16_t counter_desc, uint16_t new_counter)
Set the current HW monotonic counter.
void read_implementation_id_from_otp(uint8_t *buf)
Definition: bl_storage.h:217
int get_monotonic_counter(uint16_t counter_desc, uint16_t *counter_value)
Get the current HW monotonic counter.
lcs
The PSA life cycle states a device can be in.
Definition: bl_storage.h:184
@ BL_STORAGE_LCS_DECOMMISSIONED
Definition: bl_storage.h:189
@ BL_STORAGE_LCS_UNKNOWN
Definition: bl_storage.h:185
@ BL_STORAGE_LCS_ASSEMBLY
Definition: bl_storage.h:186
@ BL_STORAGE_LCS_PROVISIONING
Definition: bl_storage.h:187
@ BL_STORAGE_LCS_SECURED
Definition: bl_storage.h:188
uint32_t num_public_keys
Definition: bl_storage.h:70
uint8_t implementation_id[32]
Definition: bl_storage.h:67
uint32_t valid
Definition: bl_storage.h:72
struct bl_storage_data::@148 key_data[1]
uint32_t s0_address
Definition: bl_storage.h:68
uint32_t s1_address
Definition: bl_storage.h:69
Definition: bl_storage.h:64
uint16_t decommissioned
Definition: bl_storage.h:57
uint16_t reserved_for_padding
Definition: bl_storage.h:56
uint16_t secure
Definition: bl_storage.h:50
uint16_t provisioning
Definition: bl_storage.h:49
Definition: bl_storage.h:48