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!

  • Hello, thank you for your reply.

    I look forward to the IOS issues being fixed, as it would be nice to be able to update the firmware from my phone (and to return my coworker's phone to him).

    In the meantime, I am still having issues with the DFU when I try to implement keys. In the app on android it seems to rapidly flash through the connecting/uploading/validating (too fast to actually see them), and on the firmware side I get the following message in the terminal "I: Image index: 0, Swap type: none" and then nothing has actually happened.

    Could the problem be as simple as the key being somehow wrong?

    Here is my prj.config file:

    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    CONFIG_BT=y
    CONFIG_BT_DEBUG_LOG=y
    CONFIG_BT_MAX_CONN=2
    CONFIG_BT_MAX_PAIRED=2
    CONFIG_BT_L2CAP_TX_BUF_COUNT=5
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DEVICE_NAME="HIDS_mouse"
    CONFIG_BT_DEVICE_APPEARANCE=962
    
    CONFIG_BT_BAS=y
    CONFIG_BT_HIDS=y
    CONFIG_BT_HIDS_MAX_CLIENT_COUNT=2
    CONFIG_BT_GATT_UUID16_POOL_SIZE=40
    CONFIG_BT_GATT_CHRC_POOL_SIZE=20
    
    CONFIG_BT_CONN_CTX=y
    
    CONFIG_BT_DIS=y
    CONFIG_BT_DIS_PNP=y
    CONFIG_BT_DIS_MANUF="NordicSemiconductor"
    CONFIG_BT_DIS_PNP_VID_SRC=2
    CONFIG_BT_DIS_PNP_VID=0x1915
    CONFIG_BT_DIS_PNP_PID=0xEEEE
    CONFIG_BT_DIS_PNP_VER=0x0100
    
    CONFIG_MAIN_STACK_SIZE=1536
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    
    CONFIG_DK_LIBRARY=y
    
    #DFU settings
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_MCUMGR=y
    #changed for BT instead of UART
    CONFIG_MCUMGR_TRANSPORT_BT=y
    #changed, dont want to require a passcode to send dfu image
    CONFIG_MCUMGR_TRANSPORT_BT_AUTHEN=n
    
    CONFIG_MCUMGR_GRP_IMG=y
    CONFIG_BASE64=y
    CONFIG_FLASH=y
    CONFIG_IMG_MANAGER=y
    CONFIG_STREAM_FLASH=y
    CONFIG_NET_BUF=y
    CONFIG_ZCBOR=y
    CONFIG_FLASH_MAP=y
    

    And my CMakeLists

    #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    cmake_minimum_required(VERSION 3.20.0)
    
    set(mcuboot_CONFIG_BOOT_SIGNATURE_KEY_FILE \"${CMAKE_CURRENT_SOURCE_DIR}/custom_key_dir/custom_priv.pem\")
    
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(peripheral_hids_mouse)
    
    FILE(GLOB app_sources src/*.c)
    # NORDIC SDK APP START
    target_sources(app PRIVATE ${app_sources})
    # NORDIC SDK APP END
    
    zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth)
    

    And finally in my child_image folder I have an mcuboot file with CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y

    I followed the instructions exactly like here for the keyfile:

    ${NCS_PATH}/bootloader/mcuboot/scripts/imgtool.py keygen -k custom_priv.pem -t ecdsa-p256

    Do you have any suggestions for what could be wrong, why I cant seem to use DFU in signed mode? Do I still upload the app_update.bin file like with the insecure mode?

    Thank you!

    EDIT: Tested the base case with no signature on my other coworker's iphone 13 and that works fine. Not sure if its all Iphone12 or just mine it doesnt work on...

    EDIT2: Tested with my old android phone running Android 7.0 and once again app crashes when trying to perform DFU. It doesnt crash on my Android 9.0 but also doesnt work, just flashes through the screens like above.

  • Hi,



    Here is my example peripheral_hids_mouse.7z. After uploading with the update_image/nRF53_HID_app_update.bin, it would show "build time: Jan 29 2024 09:51:56"

    Beware that this code/configuration is not fully tested or qualified and should be considered provided “as-is”. Please test it with your application and let me know if you find any issues.

    i_4556 said:
    EDIT: Tested the base case with no signature on my other coworker's iphone 13 and that works fine. Not sure if its all Iphone12 or just mine it doesnt work on...

    Could you try to use the nRF Connect Device Manager App https://apps.apple.com/us/app/nrf-connect-device-manager/id1519423539? Please make sure it's the latest version v1.5.3. 

    The minimum required iOS version is 9.0, originally released in Fall of 2015.

    i_4556 said:
    EDIT2: Tested with my old android phone running Android 7.0 and once again app crashes when trying to perform DFU. It doesnt crash on my Android 9.0 but also doesnt work, just flashes through the screens like above.

    Please try to use the nRF Connect Device Manager app https://play.google.com/store/apps/details?id=no.nordicsemi.android.nrfconnectdevicemanager&hl=en_US 

    The minimum required Android version is 5.0 (Android Lollipop) due to a requirement for high MTU.

    -Amanda H.

  • Hello,

    Thank you for your continued assistance. Per your suggestion, I tried starting with the base case (no security) with the NRF Connect Device Manager app, and that has worked with my iPhone, and every other phone I have tried.

    I am having a problem with the encryption however, in that it wont build. It fails during the signing/encrypting phase, with the following error:

    PermissionError: [Errno 13] Permission denied: 'C:/Users/Isaac/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/child_image/mcuboot/'

    The code embed tool has suddenly stopped working, but here is the relevant terminal message

    [3/12] Generating ../../zephyr/app_update.bin
    FAILED: zephyr/app_update.bin
    cmd.exe /C "cd /D C:\Users\Isaac\Downloads\peripheral_hids_mouse\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/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/build/zephyr/mcuboot_primary_app.hex C:/Users/Isaac/Downloads/peripheral_hids_mouse/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:/Users/Isaac/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/child_image/mcuboot/enc-ec256-priv.pem --header-size 0x200 --align 4 --version 0.0.0+0 --pad-header --encrypt C:/Users/Isaac/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/child_image/mcuboot/ --slot-size 0x74000 C:/Users/Isaac/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/build/zephyr/app_to_sign.bin C:/Users/Isaac/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/build/zephyr/app_update.bin"
    Traceback (most recent call last):

      File "C:/ncs/v2.5.0/bootloader/mcuboot/scripts/imgtool.py", line 22, in <module>

        main.imgtool()

      File "C:\ncs\toolchains\c57af46cb7\opt\bin\Lib\site-packages\click\core.py", line 1128, in __call__

        return self.main(*args, **kwargs)

      File "C:\ncs\toolchains\c57af46cb7\opt\bin\Lib\site-packages\click\core.py", line 1053, in main

        rv = self.invoke(ctx)

      File "C:\ncs\toolchains\c57af46cb7\opt\bin\Lib\site-packages\click\core.py", line 1659, in invoke

        return _process_result(sub_ctx.command.invoke(sub_ctx))

      File "C:\ncs\toolchains\c57af46cb7\opt\bin\Lib\site-packages\click\core.py", line 1395, in invoke

        return ctx.invoke(self.callback, **ctx.params)

      File "C:\ncs\toolchains\c57af46cb7\opt\bin\Lib\site-packages\click\core.py", line 754, in invoke

        return __callback(*args, **kwargs)

      File "C:\ncs\v2.5.0\bootloader\mcuboot\scripts\imgtool\main.py", line 425, in sign

        enckey = load_key(encrypt) if encrypt else None

      File "C:\ncs\v2.5.0\bootloader\mcuboot\scripts\imgtool\main.py", line 91, in load_key

        key = keys.load(keyfile)

      File "C:\ncs\v2.5.0\bootloader\mcuboot\scripts\imgtool\keys\__init__.py", line 49, in load

        with open(path, 'rb') as f:

    PermissionError: [Errno 13] Permission denied: 'C:/Users/Isaac/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/child_image/mcuboot/'

    The error seems related to a path issue, where instead of pointing to the key file it only points to the directory with the key file. I have the same problem with my code, where I have basically copied your work related to SDFU.

    I am using 2.5.0 if that matters in some way.

    Thanks again for all your help!

    EDIT: I tried invoking the tool in standalone mode, using the exact same command as the visual studio build, and the problem becomes evident:

    C:/ncs/v2.5.0/bootloader/mcuboot/scripts/imgtool.py sign --key C:/Users/Isaac/Documents/peripheral_hids_mouse/child_image/mcuboot/enc-ec256-priv.pem --header-size 0x200 --align 4 --version 0.0.0+0 --pad-header --encrypt C:/Users/Isaac/Documents/peripheral_hids_mouse/child_image/mcuboot/ --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"

    Notice that after the --encrypt it points to a directory and not a file.

    I dont know how to fix this in the Visual Studio configs, but I tried fixing it in the terminal, and that led to another interesting error:

    TypeError: ECPrivateKey.sign() got an unexpected keyword argument 'signature_algorithm'

    A quick google search shows this is a known issue from basically last week that has already been patched, so im going to apply the patch and report back. github.com/.../10237

  • Hi, 

    Try to shorter the path, for example:  C:/Users/Isaac/Downloads/peripheral_hids_mouse/peripheral_hids_mouse/

    Windows has character limitations with the executed path, so too many characters in the path would cause unexpected errors. 

    -Amanda H.

  • Hello,

    Thank you for your reply. I dont think the issue is path length.

    I tried invoking the imgtool.py tool in the windows terminal, using the exact same command as the visual studio build, and the problem becomes evident:

    C:/ncs/v2.5.0/bootloader/mcuboot/scripts/imgtool.py sign --key C:/Users/Isaac/Documents/peripheral_hids_mouse/child_image/mcuboot/enc-ec256-priv.pem --header-size 0x200 --align 4 --version 0.0.0+0 --pad-header --encrypt C:/Users/Isaac/Documents/peripheral_hids_mouse/child_image/mcuboot/ --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"

    Notice that after the --encrypt it points to a directory and not a file.

    I dont know how to fix this in the Visual Studio configs, but I tried fixing it in the terminal by simply adding the location of the key file, making the command

    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"

    And now it seems to be working. How do I make that change in the config files for the project?

Related