Skip to content

Commit b9b33dd

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]> (cherry picked from commit 3839107)
1 parent 9011170 commit b9b33dd

File tree

5 files changed

+126
-0
lines changed

5 files changed

+126
-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_MANIFEST_UPDATES
11711173
bool "Enable transactional updates"
11721174
select EXPERIMENTAL
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: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
29+
if (security_cnt == NULL) {
30+
FIH_RET(FIH_FAILURE);
31+
}
32+
33+
if (image_id > IRONSIDE_COUNTER_MAX) {
34+
FIH_RET(FIH_FAILURE);
35+
}
36+
37+
/* Since the IronSide service is not protected against fault injection,
38+
* read the counter multiple times and compare the results.
39+
*/
40+
for (i = 0; i < IRONSIDE_COUNTER_READ_RETRIES; i++) {
41+
if (ironside_counter_get(image_id, &cur_sec_cnt[i]) != 0) {
42+
FIH_RET(FIH_FAILURE);
43+
}
44+
}
45+
46+
for (i = 1; i < IRONSIDE_COUNTER_READ_RETRIES; i++) {
47+
if (cur_sec_cnt[0] != cur_sec_cnt[i]) {
48+
FIH_RET(FIH_FAILURE);
49+
}
50+
}
51+
52+
if (cur_sec_cnt[0] > IRONSIDE_COUNTER_MAX_VALUE) {
53+
*security_cnt = fih_int_encode(cur_sec_cnt[0]);
54+
FIH_RET(FIH_SUCCESS);
55+
}
56+
57+
FIH_RET(FIH_FAILURE);
58+
}
59+
60+
int32_t boot_nv_security_counter_update(uint32_t image_id, uint32_t img_security_cnt)
61+
{
62+
if ((img_security_cnt > IRONSIDE_COUNTER_MAX_VALUE) || (image_id > IRONSIDE_COUNTER_MAX)) {
63+
return -BOOT_EBADARGS;
64+
}
65+
66+
if (ironside_counter_set(image_id, img_security_cnt) != 0) {
67+
return -BOOT_EBADSTATUS;
68+
}
69+
70+
return 0;
71+
}
72+
73+
fih_int boot_nv_security_counter_is_update_possible(uint32_t image_id, uint32_t img_security_cnt)
74+
{
75+
fih_int security_cnt;
76+
fih_int fih_err;
77+
78+
FIH_CALL(boot_nv_security_counter_get, fih_err, image_id, &security_cnt);
79+
if (FIH_EQ(fih_err, FIH_SUCCESS)) {
80+
int cnt = fih_int_decode(security_cnt);
81+
82+
if ((cnt <= IRONSIDE_COUNTER_MAX_VALUE) && (cnt <= img_security_cnt)) {
83+
FIH_RET(FIH_SUCCESS);
84+
}
85+
}
86+
87+
FIH_RET(FIH_FAILURE);
88+
}
89+
90+
int32_t boot_nv_security_counter_lock(uint32_t image_id)
91+
{
92+
if (image_id > IRONSIDE_COUNTER_MAX) {
93+
return -BOOT_EBADARGS;
94+
}
95+
96+
if (ironside_counter_lock(image_id) != 0) {
97+
return -BOOT_EBADSTATUS;
98+
}
99+
100+
return 0;
101+
}

0 commit comments

Comments
 (0)