Multiple MCUBoot Keys and Securing a Private Key

Using SDK 2.4.2

1) Is there a way to specify multiple MCUBoot keys in the same way they can be specified for NSIB? 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?

2) NSIB also provides a hook for a custom signing script with SB_SIGNING_COMMAND. This means the private key can be stored on a secure server and not in our code repository. MCUBoot doesn't have a similar mechanism, correct? If I want to insert my own signature, what would prevent me from using a signed image and just replacing the signature in the trailer?

3) If I were able to securely sign an image for MCUBoot, how should I go about getting the public key to the MCUBoot application? The public key array is generated at build time, and I don't see a way to specify my own key c-file or public pem to be used to generate said file.

Thanks!

Parents
  • Hi,

    1. We do not support mutliple revokable keys for MCUboot. It should not be needed if MCUboot is used as second stange bootloader though, as in that case, revoking a the public key in MCUboot can be in form of updating to a newer MCUboot version.

    2. There is no equivablent for MCUboot as far as I am aware. However, nothing prevents you from replacing the dignature trailer in the hex file directly as yo write, that will work. Or take the un-signed binary and sign it yourself with imgtool.py and use the resulting signed image.

    3. Pointing to just the public key (which is what you want if you are signing separately to better protect the private key) is not directly support in Kconfig, but there is a unofficial sample that demonstrate how you can do it: MCUBoot sample using SMP Server and manually signed images.

Reply
  • Hi,

    1. We do not support mutliple revokable keys for MCUboot. It should not be needed if MCUboot is used as second stange bootloader though, as in that case, revoking a the public key in MCUboot can be in form of updating to a newer MCUboot version.

    2. There is no equivablent for MCUboot as far as I am aware. However, nothing prevents you from replacing the dignature trailer in the hex file directly as yo write, that will work. Or take the un-signed binary and sign it yourself with imgtool.py and use the resulting signed image.

    3. Pointing to just the public key (which is what you want if you are signing separately to better protect the private key) is not directly support in Kconfig, but there is a unofficial sample that demonstrate how you can do it: MCUBoot sample using SMP Server and manually signed images.

Children
  • Einar,

    Thanks. I think using NSIB as the first stage bootloader might work. I like that it has all the right elements to keep keys secure and to be able to revoke keys. Can you confirm my understanding of how image validation, boot, and update would work in this case:

    • Understanding so far:
      • NSIB validates the current MCUboot version and new MCUboot images to be installed.
      • MCUboot validates the current and new application images. We can change keys used to sign the application by upgrading MCUboot. But still, the keys used to sign the application are potentially exposed.
    • Concerns:
      • Won’t we need to do a multi-image OTA so that the new MCUboot and newly signed application are able to be installed consecutively. Otherwise, we could install a new MCUboot version with an old application which it can’t boot. I don’t quite understand how to do this with the two bootloaders.
      • With MCUboot I can use the DFU target library, what’s the corresponding API or library to use with NSIB?
      • How do I setup the multi-image update so I don’t brick my devices?
      • If I want to also use MCUboot with external flash to make room for a large application, is this still possible?

    As an alternative idea, what would prevent the use of NSIB by itself without MCUboot? We would need to use the PCD library to perform a netcore update, but that could be run from the application or the application bootloader, right?

  • Hi,

    Your understanding is mostly correct.

    EDLT said:
    But still, the keys used to sign the application are potentially exposed.

    I do not understand what you refer to here though? MCUBoot contains the public key needed to verify the application images, but this is not a secret. The private key does not reside on the device, so this is not exposed.

    EDLT said:
    Won’t we need to do a multi-image OTA so that the new MCUboot and newly signed application are able to be installed consecutively.

    Yes, if you change the MCUboot key used to validate the application, you will need to update both MCUboot and the application simultaniously. This should not be a problem though. Wiht an upgradable bootloader, you have a secondary slot for the bootloader, and you also have a separate secondary slot for the application. In order to simultaniously update, transver both the new MCUboot and the new application, which then reside in their separate secondary slots, and activate the new applicatio image. What happens then is that when the device is reset, the secure immutable bootloader which is the first stage bootloader will see that there is a newer MCUboot version, and boot that. This in turn will check the metadata on the secondary slot and see that there is a new image to be activated, and activate that.

    Note that if you want revokable keys in MCUboot you should validate that this works, but most likely, you will never have to do this operation in the field (it is only relevant if you suspect that the private key used to sign applications has been leaked or otherwise compromised).

    EDLT said:
    With MCUboot I can use the DFU target library, what’s the corresponding API or library to use with NSIB?

    You can use the DFU target library for NSIB updates as well (it is covered by the MCUboot style upgrades). But there are also other posibilities, like SMP, as demonstrated by the SMP Server sample.

    EDLT said:
    How do I setup the multi-image update so I don’t brick my devices?

    Multi image DFU for the nRF53 in general (including net core image) is perhaps a separate discussion, but in the context of this case the potential problem is with mismatch of the application and immutable bootloader key. I must say that I have not tested this myself nor seen an example of it being used, but from what I can see, this order of operation should be safe:

    1. First write the application update signed with the new key (for instance via SMP) image to the secondary slot and mark for activation.
      1. If for some reason a reset happens at this point, the old MCUboot will not activate the image, and it will not be activated. So the device will still bot into the old application.
    2. Secondly, write the MCUboot application.
      1. Uplon reset, NSIB will boot the new MCUboot (as it has the highest version number).
      2. The new MCUboot has the new public key and will validate the new application image in the secondary slot, activate and boot it.
    EDLT said:
    If I want to also use MCUboot with external flash to make room for a large application, is this still possible?

    Yes, using MCUboot with external flash is common and supported. The secondary slot for the applicaiton can be placed in external flash.

    EDLT said:
    As an alternative idea, what would prevent the use of NSIB by itself without MCUboot?

    NSIB is a minimal bootloader that does not support network core updates (or any other features othar than what is strictly needed for the indended use case). So then you would have to implement that youself, and I am not sure you would gain much?

  • Thanks for the lengthy response. This makes sense.

    The private key does not reside on the device, so this is not exposed.

    I mean to say the key has to exist alongside the code base during compile time. It just means there are ways to leak the key (e.g. modify the script) as opposed to using a separate signing service that never reveals the key.

    NSIB is a minimal bootloader that does not support network core updates (or any other features othar than what is strictly needed for the indended use case). So then you would have to implement that youself, and I am not sure you would gain much?

    The real gain would be reduced complexity and need to juggle another image for MCUboot in addition to the ability to use the existing hooks NISB provides for signing services and multiple public keys that can be revoked.

    Thanks again.

  • Hi,

    EDLT said:
    It just means there are ways to leak the key (e.g. modify the script) as opposed to using a separate signing service that never reveals the key.

    Yes, that is correct. But you are free to change this and sign the image separately outside of the build process, even though it is not directly supported in the SDK. Oen way to do this is shown in this unoficcial sample.

    EDLT said:
    The real gain would be reduced complexity and need to juggle another image for MCUboot in addition to the ability to use the existing hooks NISB provides for signing services and multiple public keys that can be revoked.

    I see. That is a valid point. But then you would end up expanding NCIB a lot, so I am not sure the compexity would be that much smaller (though you would have one less bootloader).  And as this is non-upgradable, you would incrase the risk of discovering a critical bug in a software component that cannot be updated in the field. That is at least worth keeping in mind.

Related