Skip to content

Commit ae8bd88

Browse files
committed
[nrf noup] zephyr: Add basic UUID checks implementation
Provide an implementation for MCUboot UUID checks that specify a single, common vendor identifier and a unique class identifier for each image. Ref: NCSDK-34175 Signed-off-by: Tomasz Chyrowicz <[email protected]>
1 parent 05b0d5e commit ae8bd88

File tree

6 files changed

+234
-0
lines changed

6 files changed

+234
-0
lines changed

boot/zephyr/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ if(CONFIG_BOOT_USE_NRF_CC310_BL)
5151
endif()
5252
endif()
5353

54+
# Include the UUID generation code
55+
add_subdirectory(uuid)
56+
5457
zephyr_library_include_directories(
5558
include
5659
)

boot/zephyr/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,8 @@ config MCUBOOT_UUID_CID
11251125
Provide an image class identification scheme to prevent processing
11261126
images for a different CPU or device produced by the same vendor.
11271127

1128+
rsource "uuid/Kconfig"
1129+
11281130
config BOOT_WATCHDOG_FEED
11291131
bool "Feed the watchdog while doing swap"
11301132
default y if WATCHDOG

boot/zephyr/uuid/CMakeLists.txt

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
if(CONFIG_NCS_MCUBOOT_UUID_SINGLE_VID)
8+
if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID)
9+
zephyr_library_sources(
10+
uuid.c
11+
)
12+
endif()
13+
14+
# Generate VID value and raw value definition
15+
if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID)
16+
if("${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}" STREQUAL "" AND CONFIG_MCUBOOT_UUID_VID)
17+
message(FATAL_ERROR "VID value not set")
18+
endif()
19+
20+
string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}")
21+
if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}")
22+
set(UUID_VID ${match_parts})
23+
else()
24+
set(UUID_DNS_NAMESPACE 6ba7b810-9dad-11d1-80b4-00c04fd430c8)
25+
string(
26+
UUID UUID_VID
27+
NAMESPACE ${UUID_DNS_NAMESPACE}
28+
NAME ${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}
29+
TYPE SHA1 UPPER
30+
)
31+
endif()
32+
33+
if(CONFIG_MCUBOOT_UUID_VID)
34+
# Convert UUID into C array.
35+
string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_VID_RAW "${UUID_VID}")
36+
zephyr_compile_definitions(NCS_MCUBOOT_UUID_VID_VALUE=${UUID_VID_RAW})
37+
endif()
38+
endif()
39+
40+
# Generate VID value(s) and raw value definition(s)
41+
if(CONFIG_MCUBOOT_UUID_CID)
42+
set(MCUBOOT_IMAGES_COUNT ${CONFIG_UPDATEABLE_IMAGE_NUMBER})
43+
foreach(image_id RANGE ${MCUBOOT_IMAGES_COUNT})
44+
if(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id})
45+
if("${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}" STREQUAL "")
46+
message(FATAL_ERROR "CID value not set for image ${image_id}")
47+
endif()
48+
49+
# Check if RAW UUID format is used
50+
string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}")
51+
if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}")
52+
set(UUID_CID_IMAGE_${image_id} ${match_parts})
53+
elseif(NOT "${UUID_VID}" STREQUAL "")
54+
# If not - generate UUID based on VID and CID values
55+
string(
56+
UUID UUID_CID_IMAGE_${image_id}
57+
NAMESPACE ${UUID_VID}
58+
NAME ${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}
59+
TYPE SHA1 UPPER
60+
)
61+
else()
62+
message(FATAL_ERROR "VID value not set, cannot generate CID for image ${image_id}")
63+
endif()
64+
65+
# Convert UUID into C array.
66+
string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_CID_IMAGE_${image_id}_RAW "${UUID_CID_IMAGE_${image_id}}")
67+
zephyr_compile_definitions(NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE=${UUID_CID_IMAGE_${image_id}_RAW})
68+
endif()
69+
endforeach()
70+
endif()
71+
endif()

boot/zephyr/uuid/Kconfig

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
if MCUBOOT && (MCUBOOT_UUID_VID || MCUBOOT_UUID_CID)
8+
9+
menu "Vendor and image Class UUIDs"
10+
11+
choice NCS_MCUBOOT_UUID_IMPLEMENTATION
12+
prompt "UUID checks implementation"
13+
default NCS_MCUBOOT_UUID_SINGLE_VID
14+
15+
config NCS_MCUBOOT_UUID_SINGLE_VID
16+
bool "Single VID and one CID per image"
17+
help
18+
This implementation allows to specify a single, common Vendor UUID
19+
(VID) for all images and a unique Class UUID (CID) for each image.
20+
21+
endchoice # NCS_MCUBOOT_UUID_IMPLEMENTATION
22+
23+
if NCS_MCUBOOT_UUID_SINGLE_VID
24+
25+
config NCS_MCUBOOT_UUID_VID_VALUE
26+
string "Vendor name"
27+
default ""
28+
help
29+
The vendor unique identifier.
30+
The following formats are supported:
31+
- Domain name (i.e. amce.corp) used to generate RFC 9562 UUID5
32+
identifier.
33+
- Raw UUID (i.e. 12345678-1234-5678-1234-567812345678)
34+
- Raw HEX UUID (i.e. 12345678123456781234567812345678)
35+
36+
if MCUBOOT_UUID_CID
37+
38+
image=0
39+
rsource "Kconfig.uuid.template"
40+
image=1
41+
rsource "Kconfig.uuid.template"
42+
image=2
43+
rsource "Kconfig.uuid.template"
44+
image=3
45+
rsource "Kconfig.uuid.template"
46+
image=4
47+
rsource "Kconfig.uuid.template"
48+
49+
endif # MCUBOOT_UUID_CID
50+
51+
endif # NCS_MCUBOOT_UUID_SINGLE_VID
52+
53+
endmenu
54+
55+
endif # BOOTLOADER_MCUBOOT && (MCUBOOT_UUID_VID || MCUBOOT_UUID_CID)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
if UPDATEABLE_IMAGE_NUMBER > $(image)
8+
9+
config NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE
10+
string "Image class name (image $(image))"
11+
default ""
12+
help
13+
The image class unique identifier.
14+
The following formats are supported:
15+
- Image class name (i.e. nRF5340_door_lock_btperipheral).
16+
This format requires NCS_MCUBOOT_UUID_VID_VALUE to be defined
17+
as the VID UUID is used as the namespace for generating RFC 9562
18+
UUID5 identifier.
19+
- Raw UUID (i.e. 12345678-1234-5678-1234-567812345678)
20+
- Raw HEX UUID (i.e. 12345678123456781234567812345678)
21+
22+
config NCS_MCUBOOT_UUID_CID_IMAGE_$(image)
23+
bool
24+
default y
25+
depends on NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE != ""
26+
help
27+
Helper symbol to simplify the active CId list generation.
28+
29+
endif # UPDATEABLE_IMAGE_NUMBER > $(image)

boot/zephyr/uuid/uuid.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2018 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <bootutil/mcuboot_uuid.h>
8+
9+
#define IMAGE_ID_COUNT CONFIG_UPDATEABLE_IMAGE_NUMBER
10+
#define CID_INIT(index, label) \
11+
static const struct image_uuid label = {{ \
12+
NCS_MCUBOOT_UUID_CID_IMAGE_## index ##_VALUE \
13+
}}
14+
#define CID_CONFIG(index) UTIL_CAT(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_, index)
15+
#define CID_DEFINE(index, prefix) \
16+
IF_ENABLED(CID_CONFIG(index), (CID_INIT(index, prefix##index)))
17+
18+
#define CID_CONDITION(index, label) \
19+
if (image_id == index) { \
20+
*uuid_cid = &label; \
21+
FIH_RET(FIH_SUCCESS); \
22+
}
23+
#define CID_CHECK(index, prefix) \
24+
IF_ENABLED(CID_CONFIG(index), (CID_CONDITION(index, prefix##index)))
25+
26+
static fih_ret boot_uuid_compare(const struct image_uuid *uuid1, const struct image_uuid *uuid2)
27+
{
28+
return fih_ret_encode_zero_equality(memcmp(uuid1->raw, uuid2->raw,
29+
ARRAY_SIZE(uuid1->raw)));
30+
}
31+
32+
#ifdef CONFIG_MCUBOOT_UUID_CID
33+
LISTIFY(IMAGE_ID_COUNT, CID_DEFINE, (;), uuid_cid_image_);
34+
35+
static fih_ret boot_uuid_cid_get(uint32_t image_id, const struct image_uuid **uuid_cid)
36+
{
37+
if (uuid_cid != NULL) {
38+
LISTIFY(IMAGE_ID_COUNT, CID_CHECK, (), uuid_cid_image_)
39+
}
40+
41+
FIH_RET(FIH_FAILURE);
42+
}
43+
#endif /* CONFIG_MCUBOOT_UUID_CID */
44+
45+
fih_ret boot_uuid_init(void)
46+
{
47+
FIH_RET(FIH_SUCCESS);
48+
}
49+
50+
#ifdef CONFIG_MCUBOOT_UUID_VID
51+
fih_ret boot_uuid_vid_match(uint32_t image_id, const struct image_uuid *uuid_vid)
52+
{
53+
const struct image_uuid uuid_vid_c = {{
54+
NCS_MCUBOOT_UUID_VID_VALUE
55+
}};
56+
57+
return boot_uuid_compare(uuid_vid, &uuid_vid_c);
58+
}
59+
#endif /* CONFIG_MCUBOOT_UUID_VID */
60+
61+
#ifdef CONFIG_MCUBOOT_UUID_CID
62+
fih_ret boot_uuid_cid_match(uint32_t image_id, const struct image_uuid *uuid_cid)
63+
{
64+
FIH_DECLARE(ret_code, FIH_FAILURE);
65+
const struct image_uuid *exp_uuid_cid = NULL;
66+
67+
FIH_CALL(boot_uuid_cid_get, ret_code, image_id, &exp_uuid_cid);
68+
if (FIH_NOT_EQ(ret_code, FIH_SUCCESS) && FIH_NOT_EQ(ret_code, FIH_FAILURE)) {
69+
FIH_RET(FIH_FAILURE);
70+
}
71+
72+
return boot_uuid_compare(uuid_cid, exp_uuid_cid);
73+
}
74+
#endif /* CONFIG_MCUBOOT_UUID_CID */

0 commit comments

Comments
 (0)