Skip to content

Commit c7501f4

Browse files
committed
[nrf noup] bootutil: key revocation
Disable previous generation key when update comes with new valid key and application is confirmed. Signed-off-by: Mateusz Michalek <[email protected]>
1 parent b014be2 commit c7501f4

File tree

6 files changed

+128
-0
lines changed

6 files changed

+128
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef H_KEY_REVOCATION_
8+
#define H_KEY_REVOCATION_
9+
10+
#include <inttypes.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
#define BOOT_KEY_REVOKE_OK 0
17+
#define BOOT_KEY_REVOKE_NOT_READY 1
18+
#define BOOT_KEY_REVOKE_INVALID 2
19+
#define BOOT_KEY_REVOKE_FAILED 2
20+
21+
22+
void allow_revoke(void);
23+
24+
int revoke(void);
25+
26+
#ifdef __cplusplus
27+
}
28+
#endif
29+
30+
#endif

boot/bootutil/src/ed25519_psa.c

+41
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ static psa_key_id_t kmu_key_ids[3] = {
3232
MAKE_PSA_KMU_KEY_ID(230)
3333
};
3434

35+
#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION)
36+
#include <bootutil/key_revocation.h>
37+
static psa_key_id_t *validated_with = NULL;
38+
#endif
39+
3540
BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids),
3641
"Invalid number of KMU slots, up to 3 are supported on nRF54L15");
3742
#endif
@@ -114,6 +119,9 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
114119
EDDSA_SIGNAGURE_LENGTH);
115120
if (status == PSA_SUCCESS) {
116121
ret = 1;
122+
#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION)
123+
validated_with = kmu_key_ids + i;
124+
#endif
117125
break;
118126
}
119127

@@ -122,4 +130,37 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
122130

123131
return ret;
124132
}
133+
#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION)
134+
int exec_revoke(void)
135+
{
136+
int ret = BOOT_KEY_REVOKE_OK;
137+
psa_status_t status = psa_crypto_init();
138+
139+
if (!validated_with) {
140+
ret = BOOT_KEY_REVOKE_INVALID;
141+
goto out;
142+
}
143+
144+
if (status != PSA_SUCCESS) {
145+
BOOT_LOG_ERR("PSA crypto init failed with error %d", status);
146+
ret = BOOT_KEY_REVOKE_FAILED;
147+
goto out;
148+
}
149+
for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) {
150+
if ((kmu_key_ids + i) == validated_with) {
151+
break;
152+
}
153+
BOOT_LOG_DBG("Invalidating key ID %d", i);
154+
155+
status = psa_destroy_key(kmu_key_ids[i]);
156+
if (status == PSA_SUCCESS) {
157+
BOOT_LOG_DBG("Success on key ID %d", i);
158+
} else {
159+
BOOT_LOG_ERR("Key invalidation failed with: %d", status);
160+
}
161+
}
162+
out:
163+
return ret;
164+
}
165+
#endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */
125166
#endif

boot/bootutil/src/key_revocation.c

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <bootutil/key_revocation.h>
8+
9+
extern int exec_revoke(void);
10+
11+
static uint8_t ready_to_revoke;
12+
13+
void allow_revoke(void)
14+
{
15+
ready_to_revoke = 1;
16+
}
17+
18+
int revoke(void)
19+
{
20+
if (ready_to_revoke) {
21+
return exec_revoke();
22+
}
23+
return BOOT_KEY_REVOKE_NOT_READY;
24+
}

boot/bootutil/src/loader.c

+15
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr);
7676

7777
#include "mcuboot_config/mcuboot_config.h"
7878

79+
#if defined(CONFIG_BOOT_KEYS_REVOCATION)
80+
#include "bootutil/key_revocation.h"
81+
#endif
82+
7983
BOOT_LOG_MODULE_DECLARE(mcuboot);
8084

8185
static struct boot_loader_state boot_data;
@@ -2819,6 +2823,11 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
28192823
}
28202824
}
28212825

2826+
#if defined(CONFIG_BOOT_KEYS_REVOCATION)
2827+
if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
2828+
allow_revoke();
2829+
}
2830+
#endif
28222831
/* Iterate over all the images. At this point all required update operations
28232832
* have finished. By the end of the loop each image in the primary slot will
28242833
* have been re-validated.
@@ -2924,6 +2933,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
29242933
fill_rsp(state, rsp);
29252934

29262935
fih_rc = FIH_SUCCESS;
2936+
#if defined(CONFIG_BOOT_KEYS_REVOCATION)
2937+
rc = revoke();
2938+
if (rc != BOOT_KEY_REVOKE_OK) {
2939+
FIH_SET(fih_rc, FIH_FAILURE);
2940+
}
2941+
#endif /* CONFIG_BOOT_KEYS_REVOCATION */
29272942
out:
29282943
/*
29292944
* Since the boot_status struct stores plaintext encryption keys, reset

boot/zephyr/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ if(DEFINED CONFIG_BOOT_SHARE_BACKEND_RETENTION)
9999
)
100100
endif()
101101

102+
if(DEFINED CONFIG_BOOT_KEYS_REVOCATION)
103+
zephyr_library_sources(
104+
${BOOT_DIR}/bootutil/src/key_revocation.c
105+
)
106+
endif()
107+
102108
# Generic bootutil sources and includes.
103109
zephyr_library_include_directories(${BOOT_DIR}/bootutil/include)
104110
zephyr_library_sources(

boot/zephyr/Kconfig

+12
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,18 @@ config BOOT_SIGNATURE_KMU_SLOTS
359359

360360
endif
361361

362+
config BOOT_KEYS_REVOCATION
363+
bool "Auto revoke previous gen key"
364+
help
365+
Automatically revoke previous generation key upon new valid key usage.
366+
367+
config BOOT_KMU_KEYS_REVOCATION
368+
bool
369+
depends on BOOT_KEYS_REVOCATION
370+
default y if BOOT_SIGNATURE_USING_KMU
371+
help
372+
Enabling KMU key revocation backend.
373+
362374
if !BOOT_SIGNATURE_USING_KMU
363375

364376
config BOOT_SIGNATURE_KEY_FILE

0 commit comments

Comments
 (0)