Skip to content

Add key generation for private encryption key#2559

Open
Wika-Group-IIoT-RD wants to merge 1 commit into
mcu-tools:mainfrom
Wika-Group-IIoT-RD:feat/gen_enc_key_Zephyr_exp
Open

Add key generation for private encryption key#2559
Wika-Group-IIoT-RD wants to merge 1 commit into
mcu-tools:mainfrom
Wika-Group-IIoT-RD:feat/gen_enc_key_Zephyr_exp

Conversation

@Wika-Group-IIoT-RD
Copy link
Copy Markdown

Current Implementation

In the default Mcuboot implementation, the private key used for firmware decryption is compiled directly into the bootloader binary.

  • The key pair is generated externally (e.g, on a production machine).
  • The public is used to encrypt the firmware image.
  • The private key is embedded in the bootloader and used to decrypt and verify the firmware during boot.

New functionalities in this PR

During the first boot, the microcontroller automatically generates a key pair. The process includes:

  1. Secure random number generation using hardware TRNG (True Random Generator).
  2. ECC key pair creation (SECP256R1) using the mbedTLS library.
  3. Conversion of the private key to DER format following the PKCS#8 standard.
  4. Conversion of the public key to PEM format for export.

The private key remains stored in a secure area of the microcontroller and is never exposed. The public key can be retrieved during the update.

Copy link
Copy Markdown
Collaborator

@de-nordic de-nordic left a comment

Choose a reason for hiding this comment

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

No. Heh, I did not even see feature proposal for that in issues.

I am not sure whether description in this PR is just making shortcuts, but as far as I can tell AES is used for encryption, ec255 is used for encryption key exchange using DH.

Anyway, my main issue with the PR: if you have a way to ask a device for a key on the first boot, that has been written by a device itself to itself, you have a way to provision one of the pair you generate outside of a device and just obliterate the original private key.

And why bloat the device into certificate generator, by adding the der and pem encoder.

@Wika-Group-IIoT-RD
Copy link
Copy Markdown
Author

@de-nordic we reached out to David on Discord regarding this topic, and he suggested opening a PR.
About the PR:
MCUboot uses the Elliptic-Curve Integrated Encryption Scheme (ECIES), which relies on Diffie-Hellman (DH) to establish a shared secret. This shared secret is then used as the AES key to encrypt the firmware.

For ECIES, each device needs its own key pair. Currently, these key pairs are generated by the imagetool (we refer to them as “encryption keys” for simplicity). The private key is compiled into the bootloader code via the key.h file.

This approach means that once the bootloader is compiled, all devices flashed with that image share the same encryption key pair. In a large fleet of devices, having identical encryption keys is a significant security concern.

To address this, we decided that each device should have its own unique encryption key pair. There are two possible approaches:

  1. Build a separate bootloader image for every device with a different key embedded.
  2. Enable the device to generate its own key pair during initialization.
    The PR focuses on the second approach: device-side generation of the encryption key pair.

The idea is to generate the encryption key pair during the first boot of the device, store the private key in a secure key storage unit inside the chip, and expose the public key over a secure production interface.
Since storing and exposing the public key is chip/solution-dependent, this part is not included in the PR.

@Wika-Group-IIoT-RD
Copy link
Copy Markdown
Author

@de-nordic If I understand your concern correctly, it’s about preventing the device from generating a new key pair on the next boot?
The PR does not introduce any mechanism to provision keys from the outside. The idea is that the device generates a key pair internally during its first boot and then exposes only the public key for encryption purposes. The idea was that the key generation inside the device is a strictly one-time function. Meaning when the device generates the key once during boot it will skips the key generation step on all subsequent boots.

If i get it wrong please correct me

@nordicjm
Copy link
Copy Markdown
Collaborator

nordicjm commented Dec 1, 2025

To address this, we decided that each device should have its own unique encryption key pair. There are two possible approaches:

I think you are overlooking the third method which is simple and easy and something anyone can do, you build MCUboot as it is today, you look in the .map file to get the address of the encryption key, you then modify the buffer at that address in the hex file with your device's unique encryption key, program the new hex, and move on to the next unit. No code changes in MCUboot needed, editing a hex is incredible simple

@Wika-Group-IIoT-RD
Copy link
Copy Markdown
Author

Hi @nordicjm,
I’m aware that technically it’s possible to patch the encryption key in the hex file after build.
However, in our company we follow processes derived from the SIL (Safety Integrity Level) world. These processes state that once a hex file has been validated, no bit is allowed to be changed, otherwise it need to be revalidated. I’m aware that SIL rules also foresee an exception for such changes; however, in that case, the tool used to perform the modification must itself be SIL-certified.
Since these rules are well established and shared across multiple projects, our idea was to integrate the key generation into the device itself. This way, we avoid any post-validation modification of the hex file and stay fully compliant with our processes.
I believe other companies may face similar challenges, especially considering Zephyr’s SIL certification plans. This approach could therefore be a benefit for the broader community, which is why we wanted to share it.

@nordicjm
Copy link
Copy Markdown
Collaborator

nordicjm commented Dec 2, 2025

Hi @nordicjm, I’m aware that technically it’s possible to patch the encryption key in the hex file after build. However, in our company we follow processes derived from the SIL (Safety Integrity Level) world. These processes state that once a hex file has been validated, no bit is allowed to be changed, otherwise it need to be revalidated. I’m aware that SIL rules also foresee an exception for such changes; however, in that case, the tool used to perform the modification must itself be SIL-certified. Since these rules are well established and shared across multiple projects, our idea was to integrate the key generation into the device itself. This way, we avoid any post-validation modification of the hex file and stay fully compliant with our processes. I believe other companies may face similar challenges, especially considering Zephyr’s SIL certification plans. This approach could therefore be a benefit for the broader community, which is why we wanted to share it.

That is a fair point. This PR needs tidying up then where there are proper commits, not what looks to be a work in progress, only then will people review it

@Laczen
Copy link
Copy Markdown

Laczen commented Dec 9, 2025

@Wika-Group-IIoT-RD, couldn't this be achieved by adding a get_private_key routine in mcuboot? This could be an extension of the builtin private key in flash. The first time an application is run it could create and store the private key in a location that is accessible by mcuboot (e.g. at the end of the boot partition or in some more secure location) and share the public key.

…key pair. The process includes:

1. Secure random number generation using hardware TRNG (True Random Generator).
2. ECC key pair creation (SECP256R1) using the mbedTLS library.
3. Conversion of the private key to DER format following the PKCS#8 standard.
4. Store the private key into the flash partition.
5. Conversion of the public key to PEM format for export.

The private key remains stored in a secure area of the microcontroller and is never exposed. The public key can be retrived only on boot if the key storage is empty.

Signed-off-by: WIKA IIoT RD <60038@wika.com>
@Wika-Group-IIoT-RD Wika-Group-IIoT-RD force-pushed the feat/gen_enc_key_Zephyr_exp branch from 2cec6d1 to baf382e Compare March 3, 2026 07:46
@de-nordic de-nordic added the crypto Encryption support label Mar 6, 2026
@Wika-Group-IIoT-RD
Copy link
Copy Markdown
Author

Hi @d3zd3z could you find some time to check it out ? Do we need to do some additonal changes ?

Copy link
Copy Markdown
Member

@d3zd3z d3zd3z left a comment

Choose a reason for hiding this comment

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

So a few comments in specific places, and overall, I think the concept is good, but I'm not sure this implementation actually gets us there, especially since @de-nordic concerns make perfect sense with the current code, but the concept of what is wanted do actually address them.

The idea, as I understand, is that the device generates a keypair, and the private key is stored in something protected (not sure how that will work, given that this runs before TZ). and only the public key will be available. This means we don't need to trust the factory to manage the private part of the keypair. The public key is not useful for decrypting any firmware images, so no harm happens if that leaks.

I'm not sure how we can really do this without actually having a way to store the private part of the key, and I guess that is supposed to be store_priv_enc_key. The complexity of pkcs8 does seem difficult to manage, and I'm wondering if we are better off using a simpler key format, similar to how the TLV manages.

We should definitely continue the conversation to make sure we're actually proceeding toward addressing the issue.

Perhaps creating an RFC describing this would be a good approach. The process isn't clearly defined, but I'd start by creating an Issue, and putting a description of the required change there.

@@ -0,0 +1,370 @@
/*
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems to be a copy of internal files from Mbed TLS. Is there a reason we can't use the public PSA Crypto API for this functionality?

CONFIG_BOOT_GEN_ENC_KEY=y
CONFIG_BOOT_ENCRYPT_IMAGE=y

CONFIG_TEST_RANDOM_GENERATOR=y
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The test random number generator is not appropriate for generating keys. It is dangerous to enable this even for an example, likewise with the timer. None of this code makes any sense without a true RNG source on the target.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

crypto Encryption support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants