arduino / mcuboot-arduino-stm32h7

27 stars 5 forks source link

MCUboot Arduino

MCUboot bootloader porting for Arduino Mbed OS based boards.

The following boards are supported:

:grey_question: What

MCUboot provides secure boot for 32-bit microcontrollers. For a detailed description on what MCUboot does and how it works please read the official documentaion.

:zap: Main features

Signed and encrypted updates

MCUboot has support for encrypting/decrypting images on-the-fly while upgrading; furthermore, before booting a Sketch, it will check if the computed signature is matching the one embedded in the image.

Confirm or revert updates

After an update the new Sketch can update the content of the flash at runtime to mark itself as OK. MCUboot will then still choose to run it during the next boot. When this happens, the swap is made permanent. If this doesn’t happen, MCUboot will perform a revert swap during the next boot by swapping the image back into its original location, and attempting to boot the old Sketch.

Sketch bootstrap

If no valid image is found in the primary slot MCUboot will search a valid image in the secondary slot and if any it will load it inside the primary slot.

Reset recovery

If a reset occurs in the middle of a swap operation, the two images may be discontiguous in flash. MCUboot recovers from this condition by using the image trailers to determine how the image parts are distributed in flash and restarting the swap.

Backward compatible with default Arduino booloader

If signing and encryption keys are not stored in flash alongside MCUboot, the Sketch signature verification is skipped and any valid Sketch can be booted.

:gear: How

Switch to MCUboot

Enable signature and encryption

By default signature verification and encryption support are disabled. To enable them you have to write your signature and encryption keys inside your board. In this project MCUboot is configured to support ecdsa-p256 keys for both signature and encryption.

To write the default keys in flash you can use this Sketch

:warning: WARNING :warning: The default keys are public therefore is not safe to use them for production, they are included only for evaluation purpose.

Customize signing and encryption keys

You can use your preferred tool the generate your ecdsa-p256 keys. With imgtool:

imgtool keygen -k ecdsa-p256-signing-priv-key.pem -t ecdsa-p256
imgtool keygen -k ecdsa-p256-encrypt-priv-key.pem -t ecdsa-p256

The public signing key and the private encryption key have to be written in flash at this addresses:

signing key @ 0x8000300
encrypt key @ 0x8000400

To get this data from the generated pem files with imgtool:

imgtool getpub -k ecdsa-p256-signing-priv-key.pem > ecdsa-p256-signing-pub-key.h
imgtool getpriv -k ecdsa-p256-encrypt-priv-key.pem > ecdsa-p256-encrypt-priv-key.h

Copy and paste the key data in this Sketch and run it to flash the keys alongside the bootloader.

Substitute default keys for sketch generation

By default the IDE uses the keys located in {runtime.platform.path}/libraries/MCUboot/default_keys

To use your custom keys follow this steps:

  1. Remove default keys
    cd {runtime.platform.path}/libraries/MCUboot/default_keys
    rm -f *.pem
  2. Generate encryption public key
    openssl pkey -in ecdsa-p256-encrypt-priv-key.pem -pubout > ecdsa-p256-encrypt-pub-key.pem

    or

    ssh-keygen -e -f ecdsa-p256-encrypt-priv-key.pem -y -m "PEM" > ecdsa-p256-encrypt-pub-key.pem
  3. Move keys in the MCUboot library folder
    mv ecsdsa-p256-signing-priv-key.pem `{runtime.platform.path}/libraries/MCUboot/default_keys/ecdsa-p256-signing-priv-key.pem`
    mv ecdsa-p256-encrypt-pub-key.pem `{runtime.platform.path}/libraries/MCUboot/default_keys/ecdsa-p256-encrypt-pub-key.pem`

    Alternatively you can customize your board.txt file following this guide

Manually create a signed and encrypted update Sketch

To create a signed and encrypted Sketch an additional step is needed after the Sketch binary is generated. This additional step is done passing the binary through imgtool. The flags used by the board to create a secure Sketch are defined here. The resulting command resembles as follows:

imgtool sign --key ecdsa-p256-signing-priv-key.pem --encrypt ecdsa-p256-encrypt-pub-key.pem input.bin output.bin --align 32 --max-align 32 --version 1.2.3+4 --header-size 0x20000 --pad-header --slot-size 0x1E0000

Load an update sketch

The bootloader exposes a DFU interface that can be used to upload a sketch in the QSPI flash of the board as a file. The upload process ends setting the pending flag to the update binary file and resetting the board. After reset MCUboot takes care of applying the update.

dfu-util --device 0x2341:0x035b -D update.ino.bin -a2 --dfuse-address=0xA0000000:leave

Confirm an update sketch

MCUboot expects that every update have to be confirmed otherwise it will revert to the previous running sketch as soon as the board is resetted. To confirm a sketch you have to call MCUboot::confirmSketch() in your setup().

void setup() {
  ...

  if(applicationSelfCheck() == OK) {
    MCUboot::confirmSketch()
  }

  ...
}

Flash is allocated

The diagram below shows the default memory map configuration used for this project:

INTERNAL FLASH                                             QSPI FLASH

Slot 0                                                     Scratch
0x08020000 - 0x081FFFFF                                    MBRBlockDevice partition 2 scratch.bin
  0x08020000 header
  0x08040000 Sketch                                        Slot 1
  0x081E0000 trailer                                       MBRBlockDevice partition 2 update.bin

Bootloader                
0x08000000 - 0x0801FFF    
  0x080002F0 bootloader id
  0x08000300 signing key  
  0x08000400 encrypt key  
  0x0801F000 board data

Build MCUboot from source

The following command will setup the mbed environment and clone the needed repositories before compile for Portenta H7.

mbed config root . && mbed deploy
mbed compile -m PORTENTA_H7_M7 -t GCC_ARM --profile=release --profile custom.json

Additional flags are needed for Lite, Lite Connected and Nicla Vision boards.

Debug

  1. LED

    • MCUboot operations: slot verify, copy, erase or swap the board LED will blink in violet (red+blue).
    • MCUboot idle: The board green LED will fade-in fade-out
  2. Serial

    • MCUboot debug prints are disabled by default. They can be enabled putting BT_SEL (PI8) pin HIGH if available or calling MCUboot::bootDebug(1); in your Sketch.

:mag_right: Other resources