problem updating mcuboot over FOTA in dual stage bootloader configuration

My main goal is to update the firmware over FOTA on a nRF5340, but with a signed firmware update file, and the bootloader verifies it. This is possible with mcuboot and works. But I also want to change the public key which mcuboot uses to verify the firmware updates, in case the private key got compromised, or is not available anymore. My idea for this is to use the dual stage bootloader setup, with b0 as the first bootloader, then mcuboot, and then the application. Since b0 can be configured with multiple keys, and the previous keys are not possible anymore when a new key is used, it would be possible to sign mcuboot with a new key for updating it in case it is needed.

I tried to set all config variables for it to my existing application, but got a few compiling problems. So for easier testing and getting help, I created a minimal application with the nRF5340-DK. It has a similar configuration, most important the external flash, which allows a bigger internal partition size for the internal application image.

It runs with the sdk-nrf 2.3.0. First checkout this version in a new directory:

west init -m github.com/.../sdk-nrf --mr v2.3.0

Then replace the "zephyr/samples/basic/blinky" project with this project: www.frank-buss.de/.../blinky.zip (a modified blinky app with the new settings and Bluetooth). It can then be compiled like this:

west build --board=nrf5340dk_nrf5340_cpuapp -p always

I can initially flash it with "west flash --recover". On ttyACM1 (in Linux) you can see this debug output, which shows first the b0 bootloader loading mcuboot, and then mcuboot loading the image:

*** Booting Zephyr OS build v3.2.99-ncs2 ***
Attempting to boot slot 0.
Attempting to boot from address 0x8200.
Verifying signature against key 0.
Hash: 0xa3...0d
Firmware signature verified.
Firmware version 1
I: Starting bootloader
I: Swap type: none
I: Swap type: none
I: Bootloader chainload address offset: 0x30000
�: Jumping to the first image slot

*** Booting Zephyr OS build v3.2.99-ncs2 ***
[00:00:00.002,288] <inf> main: Blinky application version 1 started

With "west build -t partition_manager_report" you can see the partition table, it should use the external flash for updating the app and network images:

 external_flash (0x800000 - 8192kB):  
+------------------------------------------------+
| 0x0: mcuboot_secondary (0xc0000 - 768kB)       |
| 0xc0000: mcuboot_secondary_1 (0x40000 - 256kB) |
| 0x100000: external_flash (0x700000 - 7168kB)   |
+------------------------------------------------+

 flash_primary (0x100000 - 1024kB):  
+--------------------------------------------------+
+---0x0: b0_container (0x8000 - 32kB)--------------+
| 0x0: b0 (0x8000 - 32kB)                          |
+---0x8000: s0 (0x10200 - 64kB)--------------------+
| 0x8000: s0_pad (0x200 - 512B)                    |
+---0x8200: s0_image (0x10000 - 64kB)--------------+
| 0x8200: mcuboot (0x10000 - 64kB)                 |
+--------------------------------------------------+
| 0x18200: EMPTY_0 (0x3e00 - 15kB)                 |
+---0x1c000: s1 (0x10200 - 64kB)-------------------+
| 0x1c000: s1_pad (0x200 - 512B)                   |
| 0x1c200: s1_image (0x10000 - 64kB)               |
+--------------------------------------------------+
| 0x2c200: EMPTY_1 (0x3e00 - 15kB)                 |
+---0x30000: mcuboot_primary (0xc0000 - 768kB)-----+
| 0x30000: mcuboot_pad (0x200 - 512B)              |
+---0x30200: app_image (0xbfe00 - 767kB)-----------+
+---0x30200: mcuboot_primary_app (0xbfe00 - 767kB)-+
| 0x30200: app (0xbfe00 - 767kB)                   |
+--------------------------------------------------+
| 0xf0000: nvs_storage (0x10000 - 64kB)            |
+--------------------------------------------------+

 otp (0x2fc - 764B):  
+------------------------------------+
| 0xff8100: provision (0x280 - 640B) |
| 0xff8380: otp (0x7c - 124B)        |
+------------------------------------+

 ram_flash (0x40000 - 256kB):  
+------------------------------------------+
| 0x0: mcuboot_primary_1 (0x40000 - 256kB) |
| 0x40000: ram_flash (0x0 - 0B)            |
+------------------------------------------+

 sram_primary (0x80000 - 512kB):  
+-----------------------------------------------+
| 0x20000000: pcd_sram (0x2000 - 8kB)           |
| 0x20002000: sram_primary (0x6e000 - 440kB)    |
| 0x20070000: rpmsg_nrf53_sram (0x10000 - 64kB) |
+-----------------------------------------------+

CPUNET flash_primary (0x40000 - 256kB):  
+--------------------------------------------+
+---0x1000000: b0n_container (0x8800 - 34kB)-+
| 0x1000000: b0n (0x8580 - 33kB)             |
| 0x1008580: provision (0x280 - 640B)        |
+---0x1008800: app (0x37800 - 222kB)---------+
| 0x1008800: hci_rpmsg (0x37800 - 222kB)     |
+--------------------------------------------+

CPUNET sram_primary (0x10000 - 64kB):  
+-------------------------------------------+
| 0x21000000: sram_primary (0x10000 - 64kB) |
+-------------------------------------------+

When I change the message in the app, and compile it again, and want to update it over FOTA with the file "build/zephyr/dfu_application.zip" and nRF Connect, then looks like the mobile app hangs, says just "Connecting", but it doesn't upload. This used to work without the extra settings for b0 etc. Is there some setting wrong or missing?

It also asked for pairing on the phone. It didn't do this before.

And it created the file "build/zephyr/dfu_mcuboot.zip". I guess this is for updating the mcuboot, but same problem hanging in nRF Connect. The LED still blinks, so the application still runs, and I can't see any error message on the console.

Another possible problem later will be the size of mcuboot. Looks like mcuboot is stored twice for the update process, instead also with the same concept as the app and network core in the external flash. This reduces the available flash for the app core a lot (I guess in parts because of the very big fash sector size of the internal flash as well). Is there any setting to reduce the mcuboot size, or even better, to store the update image in the external flash as well?

And can I combine the mcuboot update zip file with the application and network update zip file?

Parents
  • Hi, 

    When I change the message in the app, and compile it again, and want to update it over FOTA with the file "build/zephyr/dfu_application.zip" and nRF Connect, then looks like the mobile app hangs, says just "Connecting", but it doesn't upload. This used to work without the extra settings for b0 etc. Is there some setting wrong or missing?

    Try to add this config CONFIG_MCUMGR_SMP_BT_AUTHEN=n to prj.conf.

    can I combine the mcuboot update zip file with the application and network update zip file?

    Unfortunately, no. the app doesn't support that. 

    Regards,
    Amanda H.

  • Thanks, this works, now I can update the application with the dfu_application.zip file. But updating mcuboot with dfu_mcuboot.zip doesn't work. nRF Connect shows the upload graph, but then looks like it closes without uploading. I also tried to increase CONFIG_FW_INFO_FIRMWARE_VERSION to 2.

    But if this works, I might be in trouble anyway, because the 2 instances of mcuboot and B0 reduces the space for the application. Best would be if B0 could update the application from the external flash, because I can use multiple keys with B0, so I could revoke compromised keys, as described here:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/libraries/security/bootloader/bl_storage.html

    But I guess B0 can't update the application image from external flash, and mucboot can't use the keys in the Bootloader storage? If mcuboot could use the keys from this storage, this would be probably the best solution. I could provision it then with the normal public key, and a disaster public key (or multiple) in case the first key gets compromised. How many keys can I store in this OTP place?

  • frankbuss said:
    But updating mcuboot with dfu_mcuboot.zip doesn't work.

    Check out this post.

    frankbuss said:
    How many keys can I store in this OTP place?

    One-time programmable (OTP) memory is typically used for holding values that are written once, and then never to be changed again throughout the product lifetime. The OTP region of UICR is emulated by placing a write-once per halfword limitation on registers defined here.

    The key storage region contains multiple key slots, where each slot consists of a key header and an associated key value. The key value is limited to 128 bits. Any key size greater than 128 bits must be divided and distributed over multiple key slot instances.

    Key headers are allocated an address range of 0x400 in the UICR memory map, allowing a total of 128 keys to be addressable inside the key storage region. See nRF5340 PS

    Also see https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.6.1/nrf/samples/bootloader/README.html#otp-regions 

Reply Children
  • I checked the posting about dfu_mcuboot.zip. They tried signed_by_mcuboot_and_b0_s0_image_update.bin and signed_by_mcuboot_and_b0_s1_image_update.bin, but it doesn't work. I also changed 

    CONFIG_FW_INFO_FIRMWARE_VERSION in mcuboot.conf to 2.
    I looked at the nRF log when I tried the zip file, and it looks like it is something on the device:
  • This is the same posting, but I'll try their project zip, maybe some setting is different.

  • I tried the peripheral_hr_smp_b0.zip file from the link you posted, but still doesn't work. First I had to change the source file, because some includes where outdated. Then I removed the hardcoded private file, which should cause it to use the internal key. I flashed then the version 11 Then I changed it to version 12 and compiled it again. This it looks like I could use the dfu_mcuboot.zip file, I got the progress graph, and looks like it flashed both files. But after booting it was still version 11. See below for the log on the serial terminal.

    I also tried the 2 files signed_by_mcuboot_and_b0_s0_image_update.bin and signed_by_mcuboot_and_b0_s1_image_update.bin with the peripheral_hr_smp_b0 demo project, but didn't work either. Looks like they didn't flash anything

    I'm out of ideas. Could you try the peripheral_hr_smp_b0 sample on a nrf5340dk board, and fix it if required, or describe in detail how I can compile and flash it so that mcuboot gets updated?


    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    Attempting to boot slot 0.
    Attempting to boot from address 0x8200.
    Verifying signature against key 0.
    Hash: 0x7f...07
    Firmware signature verified.
    Firmware version 11
    Setting monotonic counter (version: 11, slot: 0)
    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    Attempting to boot slot 0.
    Attempting to boot from address 0x8200.
    Verifying signature against key 0.
    Hash: 0x7f...07
    Firmware signature verified.
    Firmware version 11
    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    [00:00:00.030,242] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.030,303] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF53x (0x0003)
    [00:00:00.030,334] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 216.11532 Build 3803067951
    [00:00:00.032,318] <inf> bt_hci_core: bt_dev_show_info: Identity: F2:7C:B6:5D:C3:74 (random)
    [00:00:00.032,348] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x224b, manufacturer 0x0059
    [00:00:00.032,379] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0x224b
    Bluetooth initialized
    Advertising successfully started
    build time: May  6 2024 a 17:30:00
    Connected
    [00:14:17.292,266] <inf> mcuboot_util: boot_swap_type_multi: Swap type: none
    [00:14:17.433,807] <inf> mcuboot_util: boot_swap_type_multi: Swap type: none
    [00:14:17.433,868] <inf> mcuboot_util: boot_swap_type_multi: Swap type: none
    [00:14:22.428,955] <inf> mcuboot_util: boot_swap_type_multi: Swap type: none
    [00:14:22.429,016] <inf> mcuboot_util: boot_swap_type_multi: Swap type: none
    [00:14:23.293,853] <inf> mcumgr_img_mgmt: img_mgmt_erase_image_data: Erased 0xa000 bytes of image slot
    [00:14:23.380,340] <inf> mcumgr_img_mgmt: img_mgmt_erase_image_data: Erased 0x1000 bytes of image slot trailer
    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    Attempting to boot slot 0.
    Attempting to boot from address 0x8200.
    Verifying signature against key 0.
    Hash: 0x7f...07
    Firmware signature verified.
    Firmware version 11
    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    [00:00:00.030,303] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
    [00:00:00.030,364] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF53x (0x0003)
    [00:00:00.030,364] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 216.11532 Build 3803067951
    [00:00:00.032,379] <inf> bt_hci_core: bt_dev_show_info: Identity: F2:7C:B6:5D:C3:74 (random)
    [00:00:00.032,409] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x224b, manufacturer 0x0059
    [00:00:00.032,440] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0x224b
    Bluetooth initialized
    Advertising successfully started
    build time: May  6 2024 a 17:30:00

  • Do you make a change to MCUBoot?

    To make the change visible, make a change to MCUBoot, for example add a log in $NRF_CONNECT_SDK/bootloader/mcuboot/boot/zephyr/main.c.

Related