Summary
The Zephyr port of MCUboot currently supports embedding only a single signing-verification public key, even though MCUboot's core key-management infrastructure (bootutil_keys[] + bootutil_key_cnt) already supports multiple keys. This is stated explicitly in docs/readme-zephyr.md:
Currently, the Zephyr RTOS port limits its support to one keypair at the time, although MCUboot's key management infrastructure supports multiple keypairs.
And the multi-key use case is already described as a design intent in docs/signed_images.md:
This facility allows you to use multiple signing keys. This would be useful when you want to prevent production units from booting development images, but want development units to be able to boot both production images and development images.
This issue tracks extending the Zephyr port to expose that capability via Kconfig, so users no longer have to fork MCUboot or patch the SDK to achieve it.
Use case
The canonical motivation, paraphrased from signed_images.md:
- Production bootloaders must accept only images signed by the production key. (No change from today.)
- Development bootloaders (same hardware, same firmware image format, different bootloader binary) must accept images signed by either the production key or a separate development key. This lets engineers run dev builds on dev units and flash production builds onto those same units without re-signing, while ensuring production units will never boot a dev image.
Today, achieving this on Zephyr requires either (a) forking/patching boot/zephyr/keys.c and boot/zephyr/CMakeLists.txt, or (b) falling back to CONFIG_BOOT_SIGNATURE_TYPE_NONE on dev units, which removes all signature protection. Neither is acceptable as a long-term path.
This is a real and recurring user need. For example, the Nordic DevZone thread Multiple MCUBoot Keys and Securing a Private Key arrives at exactly the same conclusion:
MCU Boot allows an array of keys, but it looks like zephyr hardcodes it to one key, and I would have to modify keys.c to accommodate an array of public keys. Is this correct? Might there be a simpler way to handle this than having to patch the SDK?
Proposed approach (high level)
Add CONFIG_BOOT_SIGNATURE_KEY_FILE_2 as an optional second PEM file. When empty (the default), behaviour is bit-identical to current upstream. When set, the bootloader embeds both public keys and accepts images signed by either, via the existing bootutil_find_key() loop in boot/bootutil/src/bootutil_find_key.c.
Scope of the change:
- A new
imgtool option to disambiguate emitted C/Rust symbol names when two keys of the same type are embedded.
- The new Kconfig option plus corresponding changes in
boot/zephyr/{CMakeLists.txt, keys.c}.
- Simulator support and a multi-key test matrix (because
boot/zephyr/keys.c is compiled by the simulator too).
- Docs updates to
readme-zephyr.md, signed_images.md, and imgtool.md.
- Updated twister coverage at Zephyr when in the same commit that updates the mcuboot lock.
Non-goals
- No change to key-matching semantics. Core
bootutil_find_key() already handles N keys correctly by hashing the KEYHASH TLV against each embedded key.
- No image-format changes. Images are signed exactly as today.
- Not a replacement for
MCUBOOT_HW_KEY / MCUBOOT_BUILTIN_KEY. Those decouple the key from the bootloader binary; this option is for deployments that embed keys in the bootloader and want more than one. The new Kconfig is mutually exclusive with both.
- No increase beyond two keys for now. The
_2 naming leaves room for _3, _4 if demand justifies it. In practice multi-key fleets are almost always "prod + dev", so two is the right first step.
Implementation
Draft impl here: #2701
Summary
The Zephyr port of MCUboot currently supports embedding only a single signing-verification public key, even though MCUboot's core key-management infrastructure (
bootutil_keys[]+bootutil_key_cnt) already supports multiple keys. This is stated explicitly indocs/readme-zephyr.md:And the multi-key use case is already described as a design intent in
docs/signed_images.md:This issue tracks extending the Zephyr port to expose that capability via Kconfig, so users no longer have to fork MCUboot or patch the SDK to achieve it.
Use case
The canonical motivation, paraphrased from
signed_images.md:Today, achieving this on Zephyr requires either (a) forking/patching
boot/zephyr/keys.candboot/zephyr/CMakeLists.txt, or (b) falling back toCONFIG_BOOT_SIGNATURE_TYPE_NONEon dev units, which removes all signature protection. Neither is acceptable as a long-term path.This is a real and recurring user need. For example, the Nordic DevZone thread Multiple MCUBoot Keys and Securing a Private Key arrives at exactly the same conclusion:
Proposed approach (high level)
Add
CONFIG_BOOT_SIGNATURE_KEY_FILE_2as an optional second PEM file. When empty (the default), behaviour is bit-identical to current upstream. When set, the bootloader embeds both public keys and accepts images signed by either, via the existingbootutil_find_key()loop inboot/bootutil/src/bootutil_find_key.c.Scope of the change:
imgtooloption to disambiguate emitted C/Rust symbol names when two keys of the same type are embedded.boot/zephyr/{CMakeLists.txt, keys.c}.boot/zephyr/keys.cis compiled by the simulator too).readme-zephyr.md,signed_images.md, andimgtool.md.Non-goals
bootutil_find_key()already handles N keys correctly by hashing the KEYHASH TLV against each embedded key.MCUBOOT_HW_KEY/MCUBOOT_BUILTIN_KEY. Those decouple the key from the bootloader binary; this option is for deployments that embed keys in the bootloader and want more than one. The new Kconfig is mutually exclusive with both._2naming leaves room for_3,_4if demand justifies it. In practice multi-key fleets are almost always "prod + dev", so two is the right first step.Implementation
Draft impl here: #2701