This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Buttonless Secure DFU - Preparing for Production

I am porting an application with buttonless DFU from SDK 14.2 to SDK 15.2 to target nRF52840 and in the process working to prepare the code for production.

After some effort to get the environment set up correctly (I initially missed the compile time pre-processor configuration for enabling NRF_DFU in the SES project, which created some very cyptic macro errors - not sure why the DFU config is not included in sdk_config like everything else!!) it is working and I managed to flash new firmware OTA with our application on SDK 15.2.

However, the skeleton code in the buttonless DFU template is sparsely documented and I would appreciate assistance with the following questions:

  1. What is the purpose of the buttonless_dfu_sdh_state_observer function? What drives the need to enter system off here?
  2. In app_shutdown_handler -> NRF_PWR_MGMT_EVT_PREPARE_DFU there is code (but commented out) that would disable the softdevice and stop the application timers. Is this required and if so why given the system is about to be reset to enter DFU?

I would also appreciate any additional advice on best practice to "productionise" the DFU process beyond the skeleton code in the SDK, for example:

  1. It it usual to change the name advertised by the bootloader to be application specific or leave it as the generic DfuTarg in production?
  2. What is the correct way to handle the situation where a device gets stuck in DFU mode (e.g. due to link loss part way through an update)? How does our central (smartphone application) identify the device and recover it to a working state?
  3. Our application is bonded but at present we are doing open DFU. Is this a common approach and if so are there any security risks when doing secure DFU without bonding?
  4. Is it recommended to use the same private key for signing firmware to all devices or should each device be coded with an individual key? If so how can the key in the bootloader be set without needing to recompile each time?
  5. Any other security/logistics considerations around the DFU process we should be aware of before entering production?

All advice gratefully received!

  • Hi,

     

    What is the purpose of the buttonless_dfu_sdh_state_observer function? What drives the need to enter system off here?

    All our BLE peripherals examples advertise for a certain amount of time and then they go to sleep. The skip CRC thing is because there is a bootloader, so it will make bootup a little faster. So what happens here is that the advertising times out -> the Softdevice is disable -> the buttonless_dfu_sdh_state_observer handler puts the system to sleep.

     

    In app_shutdown_handler -> NRF_PWR_MGMT_EVT_PREPARE_DFU there is code (but commented out) that would disable the softdevice and stop the application timers. Is this required and if so why given the system is about to be reset to enter DFU?

     This part of the code can be used if you have an application that needs to finish a task before it resets into DFU mode.

     

    It it usual to change the name advertised by the bootloader to be application specific or leave it as the generic DfuTarg in production?

     You can change the name if you want or leave it as it is. Just make sure your mobile app know which target the application is going to connect to perform DFU.

     

    What is the correct way to handle the situation where a device gets stuck in DFU mode (e.g. due to link loss part way through an update)? How does our central (smartphone application) identify the device and recover it to a working state?

    This will depend if you are using dual-bank or single-bank updates. In the buttonless_dfu example this is taken care of. The preferred update mode if there is enough space for the application (something that usually is the case using nRF52840) is dual-bank. There is a time-out in the DFU bootloader, and it will either recover to the old application and start advertising again, or it will start advertising in bootloader mode if using single-bank. If there is a disconnect and connect while the DFU update is going on the bootloader will remember where in the update it is and continue from it.

     

    Our application is bonded but at present we are doing open DFU. Is this a common approach and if so are there any security risks when doing secure DFU without bonding?

    I have asked around here and it seems that DFU without bonding is a common approach. Some may see more disadventages than adventages when using bonds. The bootloader will verify the signature of the init packet regardless of it using bonds or not to perform updates.

     

    Is it recommended to use the same private key for signing firmware to all devices or should each device be coded with an individual key? If so how can the key in the bootloader be set without needing to recompile each time?

     Yes, you should use the same private key, as long as it is kept private Slight smile

     

    Any other security/logistics considerations around the DFU process we should be aware of before entering production?

    One I can think of is that is you are using bonds you will need to use dual-bank updates. If the application you are updating the nRF52840 with is not valid and you loose your bonded device while performing the update, you will be stucked if using single-bank. When using dual-bank you can go back to the last verified application.

    Best Regards,

    Marjeris

  • Thanks msromero - we will follow your advice!

    A seperate but related question - I have found that on SDK 15.2 I can no longer re-flash just the application (+ settings page) when the bootloader is present. If I try the device will go to DFU mode on reset, presumably because the bootloader is rejecting the updated application.

    Instead I have to fully erase the chip and write SD + bootloader + application + settings page all at the one time, then it works. If I send a new application over DFU it also works. It is only when attempting to flash a new application directly there is a problem.

    Has something changed in the SDK 15.2 bootloader that means the application cannot be re-flashed after initial programming? Any work around for this? It is a pain for development having to fully erase the device each time the application is updated as bonding information, etc is lost in the process.

  • Hi,

    You should be able to re-flash the application + bootloader settings using --sectorerase. There are no changes in SDK15.2 that modify this. Could you post the commands you are using to update the application?

    Just as a recap, you'll need to

    1. Build the application hex file
    2. Generate a new bootloader settings based on new application hex file
    3. Flash the new application and new bootloader settings

    Best Regards,

    Marjeris

  • These are the commands I'm using that work and bring the application up correctly (application is built prior in SES):

    nrfjprog -e
    nrfjprog --program s140_nrf52_6.1.0_softdevice.hex
    nrfjprog --program bootloader.hex 
    nrfjprog --program application.hex --sectorerase
    nrfutil settings generate --family NRF52840 --application application.hex --application-version 1 --bootloader-version 2 --bl-settings-version 1 settings.hex
    nrfjprog --program settings.hex --sectorerase
    nrfjprog --reset

    If I don't do the erase and just flash the application/bootloader settings the device comes up in DFU mode. I didn't have this issue with SDK 14.2.

  • Hi,

    My mistake, there was a change from SDK 14.2 to SDK15.2. In SDK 15.2 we use MBR parameter storage as a backup of the bootloader settings page. You will need to erase the backup stored in the MBR (and reflash app + settings). Try this:

    nrfjprog --erasepage 0x000FE000
    nrfjprog --program application.hex --sectorerase
    nrfutil settings generate --family NRF52840 --application application.hex --application-version 1 --bootloader-version 2 --bl-settings-version 1 settings.hex
    nrfjprog --program settings.hex --sectorerase
    nrfjprog --reset

    Where 0x000FE000 is the start adress of the MBR parameter storage in nRF52840.

    See the comment on the update under "New features" here:

    - The bootloader settings page is now backed up before being updated. This increases protection from corruption caused by chance events
        (for example, power failure) and malicious apps.

    Regards,

    Marjeris

Related