Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions boot/bootutil/include/bootutil/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ extern "C" {
* ...
* 0xffa0 - 0xfffe
*/
#define IMAGE_TLV_UUID_VID 0x80 /* Vendor unique identifier */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These go above comment explaining vendor specific ids. If these are vendor specific ids, then they have in-proper codes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And should't really be here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "comment explaining vendor specific ids"?

#define IMAGE_TLV_UUID_CID 0x81 /* Device class unique identifier */
#define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */

#define VERSION_DEP_SLOT_ACTIVE 0x00 /* Check dependency against active slot. */
Expand Down
63 changes: 63 additions & 0 deletions boot/bootutil/include/bootutil/mcuboot_uuid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef __MCUBOOT_UUID_H__
#define __MCUBOOT_UUID_H__

/**
* @file uuid.h
*
* @note A vendor ID as well as class ID values may be statically generated
* using CMake, based on the vendor domain name as well as product name.
* It is advised to use vendor ID as an input while generating device
* class ID to avoid collisions between UUIDs from two different vendors.
*/

#include <stdint.h>
#include "bootutil/fault_injection_hardening.h"

#ifdef __cplusplus
extern "C" {
#endif


/** The 128-bit UUID, used for identifying vendors as well as image classes. */
struct image_uuid {
uint8_t raw[16];
};

/**
* @brief Initialises the UUID module.
*
* @return FIH_SUCCESS on success
*/
fih_ret boot_uuid_init(void);

/**
* @brief Check if the specified vendor UUID is allowed for a given image.
*
* @param[in] image_id Index of the image (from 0).
* @param[in] uuid_vid The reference to the image's vendor ID value.
*
* @return FIH_SUCCESS on success.
*/
fih_ret boot_uuid_vid_match(uint32_t image_id, const struct image_uuid *uuid_vid);

/**
* @brief Check if the specified image class UUID is allowed for a given image.
*
* @param[in] image_id Index of the image (from 0).
* @param[in] uuid_cid The reference to the image's class ID value.
*
* @return FIH_SUCCESS on success
*/
fih_ret boot_uuid_cid_match(uint32_t image_id, const struct image_uuid *uuid_cid);

#ifdef __cplusplus
}
#endif

#endif /* __MCUBOOT_UUID_H__ */
85 changes: 84 additions & 1 deletion boot/bootutil/src/image_validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
#include "bootutil/bootutil_log.h"

BOOT_LOG_MODULE_DECLARE(mcuboot);
#if defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID)
#include "bootutil/mcuboot_uuid.h"
#endif /* MCUBOOT_UUID_VID || MCUBOOT_UUID_CID */

#ifdef MCUBOOT_ENC_IMAGES
#include "bootutil/enc_key.h"
Expand Down Expand Up @@ -198,7 +201,8 @@ bootutil_img_validate(struct boot_loader_state *state,
int seed_len, uint8_t *out_hash
)
{
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT)
#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \
|| defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID)
int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state));
#endif
uint32_t off;
Expand Down Expand Up @@ -235,6 +239,14 @@ bootutil_img_validate(struct boot_loader_state *state,
uint32_t img_security_cnt = 0;
FIH_DECLARE(security_counter_valid, FIH_FAILURE);
#endif
#ifdef MCUBOOT_UUID_VID
struct image_uuid img_uuid_vid = {0x00};
FIH_DECLARE(uuid_vid_valid, FIH_FAILURE);
#endif
#ifdef MCUBOOT_UUID_CID
struct image_uuid img_uuid_cid = {0x00};
FIH_DECLARE(uuid_cid_valid, FIH_FAILURE);
#endif

BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap);

Expand Down Expand Up @@ -463,6 +475,64 @@ bootutil_img_validate(struct boot_loader_state *state,
break;
}
#endif /* MCUBOOT_HW_ROLLBACK_PROT */
#ifdef MCUBOOT_UUID_VID
case IMAGE_TLV_UUID_VID:
{
/*
* Verify the image's vendor ID length.
* This must always be present.
*/
if (len != sizeof(img_uuid_vid)) {
/* Vendor UUID is not valid. */
rc = -1;
goto out;
}

rc = LOAD_IMAGE_DATA(hdr, fap, off, img_uuid_vid.raw, len);
if (rc) {
goto out;
}
Comment on lines +485 to +494
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it was decided to wrap uuid in fih, these should probably also report fih failure; i do not understand a difference between a failure in uuid check and inability to perform the check. And I know that we are inconsistent here, and maybe that is a good point to discuss it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a translation logic, based on the rc value:

   if (rc) {
        FIH_SET(fih_rc, FIH_FAILURE);

and the default value of uuid_vid_valid and uuid_cid_valid will either way mask the other failure reasons.

The difference is just that - inability (if possible) can report "incompatible image format" and the uuid check can report "invalid UUID value".
There is though no way to distinguish between those error reasons as there is just a single FIH_FAILURE error code.


FIH_CALL(boot_uuid_vid_match, fih_rc, image_index, &img_uuid_vid);
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
FIH_SET(uuid_vid_valid, FIH_FAILURE);
goto out;
}

/* The image's vendor identifier has been successfully verified. */
uuid_vid_valid = fih_rc;
break;
}
#endif
#ifdef MCUBOOT_UUID_CID
case IMAGE_TLV_UUID_CID:
{
/*
* Verify the image's class ID length.
* This must always be present.
*/
if (len != sizeof(img_uuid_cid)) {
/* Image class UUID is not valid. */
rc = -1;
goto out;
}

rc = LOAD_IMAGE_DATA(hdr, fap, off, img_uuid_cid.raw, len);
if (rc) {
goto out;
}

FIH_CALL(boot_uuid_cid_match, fih_rc, image_index, &img_uuid_cid);
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
FIH_SET(uuid_cid_valid, FIH_FAILURE);
goto out;
}

/* The image's class identifier has been successfully verified. */
uuid_cid_valid = fih_rc;
break;
}
#endif
}
}

Expand All @@ -485,6 +555,19 @@ bootutil_img_validate(struct boot_loader_state *state,
}
#endif

#ifdef MCUBOOT_UUID_VID
if (FIH_NOT_EQ(uuid_vid_valid, FIH_SUCCESS)) {
rc = -1;
goto out;
}
#endif
#ifdef MCUBOOT_UUID_CID
if (FIH_NOT_EQ(uuid_cid_valid, FIH_SUCCESS)) {
rc = -1;
goto out;
}
#endif

out:
if (rc) {
FIH_SET(fih_rc, FIH_FAILURE);
Expand Down
53 changes: 53 additions & 0 deletions boot/zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,59 @@ if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA)
)
endif()

# Include the sample implementation.
if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID)
zephyr_library_sources(
mcuboot_uuid.c
)
endif()

# Generate VID value and raw value definition
if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID)
string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts ${CONFIG_MCUBOOT_UUID_VID_VALUE})
if ("${match_parts}" STREQUAL "${CONFIG_MCUBOOT_UUID_VID_VALUE}")
set(UUID_VID ${match_parts})
else()
set(UUID_DNS_NAMESPACE 6ba7b810-9dad-11d1-80b4-00c04fd430c8)
string(
UUID UUID_VID
NAMESPACE ${UUID_DNS_NAMESPACE}
NAME ${CONFIG_MCUBOOT_UUID_VID_VALUE}
TYPE SHA1 UPPER
)
endif()

# Convert UUID into C array.
string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_VID_RAW ${UUID_VID})
add_compile_definitions(MCUBOOT_UUID_VID_VALUE=${UUID_VID_RAW})
endif()

# Generate VID value(s) and raw value definition(s)
if(CONFIG_MCUBOOT_UUID_CID)
set(MCUBOOT_IMAGES_COUNT 4)
foreach(image_id RANGE ${MCUBOOT_IMAGES_COUNT})
if(CONFIG_MCUBOOT_UUID_CID_IMAGE_${image_id})
# Check if RAW UUID format is used
string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts ${CONFIG_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE})
if ("${match_parts}" STREQUAL "${CONFIG_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}")
set(UUID_CID_IMAGE_${image_id} ${match_parts})
else()
# If not - generate UUID based on VID and CID values
string(
UUID UUID_CID_IMAGE_${image_id}
NAMESPACE ${UUID_VID}
NAME ${CONFIG_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}
TYPE SHA1 UPPER
)
endif()

# Convert UUID into C array.
string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_CID_IMAGE_${image_id}_RAW ${UUID_CID_IMAGE_${image_id}})
add_compile_definitions(MCUBOOT_UUIC_CID_IMAGE_${image_id}_VALUE=${UUID_CID_IMAGE_${image_id}_RAW})
endif()
endforeach()
endif()

# library which might be common source code for MCUBoot and an application
zephyr_link_libraries(MCUBOOT_BOOTUTIL)

Expand Down
38 changes: 38 additions & 0 deletions boot/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,44 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED

endchoice

config MCUBOOT_UUID_VID
bool "Expect vendor unique identifier in image's TLV"
help
Provide a vendor identification scheme to prevent processing images
generated by a different vendor.

config MCUBOOT_UUID_CID
bool "Expect image class unique identifier in image's TLV"
help
Provide an image class identification scheme to prevent processing
images for a different CPU or device produced by the same vendor.

config MCUBOOT_UUID_VID_VALUE
string "Vendor name"
default ""
depends on MCUBOOT_UUID_VID || MCUBOOT_UUID_CID
help
The vendor unique identifier.
The following formats are supported:
- Domain name (i.e. amce.corp) used to generate RFC 9562 UUID5
identifier.
- Raw UUID (i.e. 12345678-1234-5678-1234-567812345678)

if MCUBOOT_UUID_CID

image=0
rsource "Kconfig.uuid.template"
image=1
rsource "Kconfig.uuid.template"
image=2
rsource "Kconfig.uuid.template"
image=3
rsource "Kconfig.uuid.template"
image=4
rsource "Kconfig.uuid.template"

endif # MCUBOOT_UUID_CID

config BOOT_WATCHDOG_FEED
bool "Feed the watchdog while doing swap"
default y if WATCHDOG
Expand Down
19 changes: 19 additions & 0 deletions boot/zephyr/Kconfig.uuid.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
config MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE
string "Image class name (image $(image))"
default ""
help
The image class unique identifier.
The following formats are supported:
- Image class name (i.e. nRF5340_door_lock_btperipheral).
This format requires MCUBOOT_UUID_VID_VALUE to be defined
as the VID UUID is used as the namespace for generating RFC 9562
UUID5 identifier.
- Raw UUID (i.e. 12345678-1234-5678-1234-567812345678)

config MCUBOOT_UUID_CID_IMAGE_$(image)
bool
default y
depends on MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE != ""
help
Helper symbol to simplify the active CId list generation.

8 changes: 8 additions & 0 deletions boot/zephyr/include/mcuboot_config/mcuboot_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@
#define MCUBOOT_HW_ROLLBACK_PROT_COUNTER_LIMITED
#endif

#ifdef CONFIG_MCUBOOT_UUID_VID
#define MCUBOOT_UUID_VID
#endif

#ifdef CONFIG_MCUBOOT_UUID_CID
#define MCUBOOT_UUID_CID
#endif

#ifdef CONFIG_MEASURED_BOOT
#define MCUBOOT_MEASURED_BOOT
#endif
Expand Down
12 changes: 12 additions & 0 deletions boot/zephyr/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
#include "bootutil/mcuboot_status.h"
#include "flash_map_backend/flash_map_backend.h"

#if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID)
#include "bootutil/mcuboot_uuid.h"
#endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */

/* Check if Espressif target is supported */
#ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32

Expand Down Expand Up @@ -521,6 +525,14 @@ int main(void)

mcuboot_status_change(MCUBOOT_STATUS_STARTUP);

#if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID)
FIH_CALL(boot_uuid_init, fih_rc);
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
BOOT_LOG_ERR("Unable to initialize UUID module: %d", fih_rc);
FIH_PANIC;
}
#endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */

#ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO
BOOT_LOG_DBG("Checking GPIO for serial recovery");
if (io_detect_pin() &&
Expand Down
Loading
Loading