Questions about SDFU implentation and security

Hello and thanks for reading,

We are developing for the NRF5340 and one of the features we are very excited about is the OTA firmware updates via the SDFU.

I have followed the instructions here :  Add DFU support to your application and things seem to be working in that the correct services appear when I then look using the NRF app.

I have not yet been able to fully test DFU, because every time I try the app crashes to the homescreen. This is unfortunate; it looks to me like a problem with the mobile app, hopefully it gets fixed soon.

In the meantime, I have two questions about SDFU.

Firstly, does the bootloader perform a full chip erase when new firmware is loaded? Like if I use the DFU to upload a new firmware that is substantially smaller in size, is there a bunch of old code in flash waiting to be stolen?

Secondly, is there any way to tell the NRF to only accept firmware images that are signed or otherwise authenticated? I assume there must be, could you provide me a link to a guide or example or something of how to implement that?

Thank you very much!

Parents
  • Hi,

    I have not yet been able to fully test DFU, because every time I try the app crashes to the homescreen. This is unfortunate; it looks to me like a problem with the mobile app, hopefully it gets fixed soon.

    Which phone are you using?

    Are you using the nRF Connect Device Manager app?

    Which NCS version and sample are you using?

    In NCS v2.5.1, you could enable the DFU function with "CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y" in the peripheral_lbs sample.

    Firstly, does the bootloader perform a full chip erase when new firmware is loaded?

    No, it would swap the image with the current and new image. See my colleague's explanation in https://github.com/hellesvik-nordic/samples_for_nrf_connect_sdk/tree/main/bootloader_samples/smp#firmware-update 

    Secondly, is there any way to tell the NRF to only accept firmware images that are signed or otherwise authenticated?

    See my colleague's explanation in https://github.com/hellesvik-nordic/samples_for_nrf_connect_sdk/tree/main/bootloader_samples/keys_and_signatures

    Regards,
    Amanda H.

  • Thank you for your reply. I am using an Iphone 12 running IOS 16.6. I am using the NRF connect app on the phone. I am using SDK 2.5.0, and per the example simply added

    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y

    to my proj.config file for my existing codebase.

    If the firmware just swaps the images, what is to stop a malicious actor uploading firmware that then dumps the old code out the serial port or otherwise bypasses readback protections? I assume the only solution is, as described in your second link, I need to add keys or something to block those uploads in the first place?

    Regarding the second link, is there anything special I need to know because I am using the nrf5340 with its seperate BLE processor, or will I still be able to use the code broadly as shown?

    Thank you!

  • Hi, 

    I am trying to reproduce it with the Visual Studio. Could you provide the details on how you encrypt?

    -Amanda H.

  • Hello, and thanks for your constant support.

    When I get it to work I manually invoke imgtool.py from windows command prompt with the command

    C:\ncs\v2.5.0\bootloader\mcuboot>python scripts/imgtool.py sign --key C:/Users/Isaac/Documents/peripheral_hids_mouse/enc-ec256-priv.pem --header-size 0x200 --align 4 --version 0.0.0+0 --pad-header --encrypt C:/Users/Isaac/Documents/peripheral_hids_mouse/enc-ec256-priv.pem --slot-size 0x74000 C:/Users/Isaac/Documents/peripheral_hids_mouse/build/zephyr/app_to_sign.bin C:/Users/Isaac/Documents/peripheral_hids_mouse/build/zephyr/app_update.bin"

  • Hi,

    Not sure if this is what you ask for VS Code or not. 

    You could add the following configs to child_image/mcuboot/prj.conf to encrypt the image

    CONFIG_BOOT_ENCRYPT_IMAGE=y
    CONFIG_BOOT_ENCRYPTION_KEY_FILE="enc-ec256-priv.pem"

    -Amanda H.

  • Hello,

    Thank you for all your support. Per your suggestion, I added the two Configs. This has resulted in some strange behaviour from the build in visual studio. Please take a look at the error message below, I have bolded the relevant portion, and then underlined the paths to the key files:

    FAILED: zephyr/app_update.bin
    cmd.exe /C "cd /D C:\Users\Isaac\Documents\peripheral_hids_mouse\build\modules\mcuboot && C:\ncs\toolchains\c57af46cb7\opt\zephyr-sdk\arm-zephyr-eabi\bin\arm-zephyr-eabi-objcopy.exe --input-target=ihex --output-target=binary --gap-fill=0xff C:/Users/Isaac/Documents/peripheral_hids_mouse/build/zephyr/mcuboot_primary_app.hex C:/Users/Isaac/Documents/peripheral_hids_mouse/build/zephyr/app_to_sign.bin && C:\ncs\toolchains\c57af46cb7\opt\bin\python.exe C:/ncs/v2.5.0/bootloader/mcuboot/scripts/imgtool.py sign --key C:/ncs/v2.5.0/bootloader/mcuboot/mcubootenc-ec256-priv.pem --header-size 0x200 --align 4 --version 0.0.0+0 --pad-header --encrypt mcubootenc-ec256-priv.pem --slot-size 0x74000 C:/Users/Isaac/Documents/peripheral_hids_mouse/build/zephyr/app_to_sign.bin C:/Users/Isaac/Documents/peripheral_hids_mouse/build/zephyr/app_update.bin"
    Traceback (most recent call last):

    As you can see, the path to the key file is wrong, and has somehow set itself to the location of the default key files that come with NRF SDK.

    Where did it get this path from, and how do I correct it?

    Earlier in the build it correctly located the key files:

    MCUBoot bootloader key file: C:/Users/Isaac/Documents/peripheral_hids_mouse/child_image/mcuboot/enc-ec256-priv.pem
    MCUBoot bootloader encryption key file: C:/Users/Isaac/Documents/peripheral_hids_mouse/child_image/mcuboot/enc-ec256-priv.pem

    EDIT: It seems to have worked, let me do a little more testing but somehow doing a second clean build seems to have worked.

  • Everything seems to now be working; I can successfully do an update with the correct key, and it rejects attempts to update with an incorrect key.

    Thank you so much for all your help.

    I have one last little question: right now in the mcuboot proj.config file I have

    CONFIG_BOOT_SIGNATURE_KEY_FILE="enc-ec256-priv.pem"

    Could I instead define it in cmakelists.txt, that way I can make it easier to swap between the dev key and the release key? Something like:

    set(CONFIG_BOOT_SIGNATURE_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/child_image/mcuboot/enc-ec256-priv.pem\")
Reply
  • Everything seems to now be working; I can successfully do an update with the correct key, and it rejects attempts to update with an incorrect key.

    Thank you so much for all your help.

    I have one last little question: right now in the mcuboot proj.config file I have

    CONFIG_BOOT_SIGNATURE_KEY_FILE="enc-ec256-priv.pem"

    Could I instead define it in cmakelists.txt, that way I can make it easier to swap between the dev key and the release key? Something like:

    set(CONFIG_BOOT_SIGNATURE_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/child_image/mcuboot/enc-ec256-priv.pem\")
Children
  • Interesting but mixed results.

    I started by making the changes in the sandbox, basically the nrf mouse example we have been playing around with. I change the CMakeLists to include

    if (EXISTS "K/path_to_key/key_priv.pem")
    set(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE \"K/path_to_key/key_priv.pem\")
    set(mcuboot_CONFIG_BOOT_ENCRYPTION_KEY_FILE \"K/path_to_key/key_priv.pem\")
    else()
    add_compile_definitions(USING_DEV_KEY)
    set(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/keys/dev_ec256_priv.pem\")
    set(mcuboot_CONFIG_BOOT_ENCRYPTION_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/keys/dev_ec256_priv.pem\")
    endif()

    And in the nrf mouse example that worked fine.

    I then tried moving everything to my main project with all the real code, and its not working.

    Here is my entire CmakeList from the main project:

    cmake_minimum_required(VERSION 3.20.0)
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(none)
    
    #check for key file
    if (EXISTS "K/release_key/key.pem")
    set(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE \"K/release_key/key.pem\")
    set(mcuboot_CONFIG_BOOT_ENCRYPTION_KEY_FILE \"K/release_key/key.pem\")
    else()
    add_compile_definitions(USING_DEV_KEY)
    set(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/keys/dev_ec256_priv.pem\")
    set(mcuboot_CONFIG_BOOT_ENCRYPTION_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/keys/dev_ec256_priv.pem\")
    endif()
    
    ADD_CUSTOM_COMMAND(TARGET app
       PRE_BUILD
       COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/version_control_hook.py
    )
    
    FILE(GLOB app_sources src/*.c*)
    
    target_sources(app PRIVATE ${app_sources})

    Instead, it reverts to the keys in the NRF folder.

    Do you have any suggestions for what im doing wrong?

  • i_4556 said:
    And in the nrf mouse example that worked fine.

    Good. Seems the CmakeList works as expected. 

    i_4556 said:
    Instead, it reverts to the keys in the NRF folder.

    That means it cannot find the key as the path in the CmakeList. 

    Please check if the key file exists or if the key path is correct. 

  • And just like that its working! Thanks for all your help!

Related