Skip to content

Commit d72e933

Browse files
committed
[nrf noup] bootloader: Add support for IronSide counters
Add an implementation of HW rollback prevention, based on the IronSide secure counters service. Ref: NCSDK-36295 Signed-off-by: Tomasz Chyrowicz <[email protected]>
1 parent 9720fe6 commit d72e933

File tree

5 files changed

+132
-0
lines changed

5 files changed

+132
-0
lines changed

boot/zephyr/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ endif()
5454
# Include the UUID generation code
5555
add_subdirectory(uuid)
5656

57+
# Include the IronSide-based HW counters implementation
58+
add_subdirectory_ifdef(CONFIG_NRF_MCUBOOT_IRONSIDE_COUNTERS ironside_counters)
59+
5760
zephyr_library_include_directories(
5861
include
5962
)

boot/zephyr/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,8 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION_LOCK
11671167
This prevents the application from accidental updates of the counter,
11681168
that may invalidate the currently running image.
11691169

1170+
rsource "ironside_counters/Kconfig"
1171+
11701172
config MCUBOOT_UUID_VID
11711173
bool "Expect vendor unique identifier in image's TLV"
11721174
help
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
zephyr_library_sources(ironside_counters.c)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
config NRF_MCUBOOT_IRONSIDE_COUNTERS
8+
bool "Use IRonSide counters for MCUBoot hardware downgrade prevention"
9+
depends on MCUBOOT_HW_DOWNGRADE_PREVENTION && NRF_IRONSIDE_COUNTER_SERVICE
10+
imply MCUBOOT_HW_DOWNGRADE_PREVENTION_LOCK
11+
help
12+
Use IronSide SE hardware counters to prevent rollback of firmware images
13+
in MCUBoot bootloader.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief MCUBoot IronSide security counters implementation.
10+
*/
11+
12+
#include <stdint.h>
13+
#include <nrf_ironside/counter.h>
14+
#include "bootutil/fault_injection_hardening.h"
15+
#include "bootutil/bootutil_public.h"
16+
17+
#define IRONSIDE_COUNTER_READ_RETRIES 3
18+
19+
fih_int boot_nv_security_counter_init(void)
20+
{
21+
return FIH_SUCCESS;
22+
}
23+
24+
fih_int boot_nv_security_counter_get(uint32_t image_id, fih_int *security_cnt)
25+
{
26+
uint32_t cur_sec_cnt[IRONSIDE_COUNTER_READ_RETRIES];
27+
size_t i;
28+
int err;
29+
30+
if (security_cnt == NULL) {
31+
FIH_RET(FIH_FAILURE);
32+
}
33+
34+
if (image_id > IRONSIDE_COUNTER_MAX) {
35+
FIH_RET(FIH_FAILURE);
36+
}
37+
38+
/* Since the IronSide service is not protected against fault injection,
39+
* read the counter multiple times and compare the results.
40+
*/
41+
for (i = 0; i < IRONSIDE_COUNTER_READ_RETRIES; i++) {
42+
err = ironside_counter_get(image_id, &cur_sec_cnt[i]);
43+
if (err != 0) {
44+
FIH_RET(FIH_FAILURE);
45+
}
46+
}
47+
48+
for (i = 1; i < IRONSIDE_COUNTER_READ_RETRIES; i++) {
49+
if (cur_sec_cnt[0] != cur_sec_cnt[i]) {
50+
FIH_RET(FIH_FAILURE);
51+
}
52+
}
53+
54+
if (cur_sec_cnt[0] != IRONSIDE_COUNTER_MAX_VALUE) {
55+
*security_cnt = fih_int_encode(cur_sec_cnt[0]);
56+
FIH_RET(FIH_SUCCESS);
57+
}
58+
59+
FIH_RET(FIH_FAILURE);
60+
}
61+
62+
int32_t boot_nv_security_counter_update(uint32_t image_id, uint32_t img_security_cnt)
63+
{
64+
int err;
65+
66+
if ((img_security_cnt > IRONSIDE_COUNTER_MAX_VALUE) || (image_id > IRONSIDE_COUNTER_MAX)) {
67+
return -BOOT_EBADARGS;
68+
}
69+
70+
err = ironside_counter_set(image_id, img_security_cnt);
71+
72+
return err == 0 ? 0 : -BOOT_EBADSTATUS;
73+
}
74+
75+
fih_int boot_nv_security_counter_is_update_possible(uint32_t image_id, uint32_t img_security_cnt)
76+
{
77+
fih_int security_cnt;
78+
fih_int fih_err;
79+
80+
FIH_CALL(boot_nv_security_counter_get, fih_err, image_id, &security_cnt);
81+
if (FIH_NOT_EQ(fih_err, FIH_SUCCESS)) {
82+
FIH_RET(FIH_FAILURE);
83+
}
84+
85+
if (fih_int_decode(security_cnt) == IRONSIDE_COUNTER_MAX_VALUE) {
86+
FIH_RET(FIH_FAILURE);
87+
}
88+
89+
if (fih_int_decode(security_cnt) <= img_security_cnt) {
90+
FIH_RET(FIH_SUCCESS);
91+
}
92+
93+
FIH_RET(FIH_FAILURE);
94+
}
95+
96+
int32_t boot_nv_security_counter_lock(uint32_t image_id)
97+
{
98+
int err;
99+
100+
if (image_id > IRONSIDE_COUNTER_MAX) {
101+
return -BOOT_EBADARGS;
102+
}
103+
104+
err = ironside_counter_lock(image_id);
105+
106+
return err == 0 ? 0 : -BOOT_EBADSTATUS;
107+
}

0 commit comments

Comments
 (0)