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

Replace existing Private Key in Bootloader with new one using DFU

Hello!

I have some devices with a custom built PCB on my desk, all of which have my own custom firmware on it.

Sadly the devices don't have access to the debug pins so I can only update via bluetooth.

When I first flashed these devices I flashed a full firmware package (bootloader, softdevice and application) which was based on a different firmware (let's call it OLD) I wrote some time ago.

This firmware package also includes the Secure BLE DFU Service so my plan was to update the devices later with the new firmware I am developing right now.

All good so far, I've done this before, no troubles yet.

Now I have finished to prepare my new firmware (let's call it NEW) and it's almost ready for production.

I realized that the bootloader I flashed before includes the private key of the OLD firmware.

I wanted to replace the private key in the NEW firmware to prevent the user from being able to flash the wrong firmware onto the wrong device, potentially killing it.

But now I have run into the problem that I am actually trying to avoid.

I have to update the existing firmware via bluetooth but I am unable to do so because my NEW firmware uses a new private key.

I have tried to create a temporary DFU distribution package containing the NEW bootloader (which has been compiled with the NEW private key) but signed with the OLD key.

Sadly that does not work. When trying this on an open PCB I have access to the RTT log I can see the following error output

00> :INFO:Image verified 
00> :INFO:Prevalidate FAILED!
00> :INFO:Sending Response: [0x4, 0x4]

So I guess replacing the bootloader with a different one is not possible?

Or am I missing something?

Would be a really really big shame if the devices I have flashed before are now at a dead end :( 

Any help is appreciated!

Also, big shout out to the Nordic staff and support team! The SDK and documentation you provide is great, as is the support you offer!

  • Hi 

    Just one clarification: the bootloader contains the public key, which is derived from the private key and the private key is used to sign the firmware packages. 

     

    When I first flashed these devices I flashed a full firmware package (bootloader, softdevice and application) which was based on a different firmware (let's call it OLD) I wrote some time ago.

     Ok, so this bootloader contains the old public key. If you want to update the firmware on this device you need to sign the firmware package with the old private key that the old public key was derived from. 

    I have tried to create a temporary DFU distribution package containing the NEW bootloader (which has been compiled with the NEW private key) but signed with the OLD key.

    Sadly that does not work. When trying this on an open PCB I have access to the RTT log I can see the following error output

    00> :INFO:Image verified
    00> :INFO:Prevalidate FAILED!
    00> :INFO:Sending Response: [0x4, 0x4]

    So I guess replacing the bootloader with a different one is not possible?

    Or am I missing something?

     If the  firmware package that contains the new bootloader that uses the new public key is signed with old private key that the old public key in the old bootloader was derived from, then this should work fine. 

    Note that the prevalidation step might fail due to the version numbers used when generating the firmware package using nrfutil, i.e. sd-req,  application-version, bootloader-version etc, see Validation and Acceptance rules for versions

    Can you post the nrfutil command you used to generate the fimware package with the new bootloader? Also please state which SoftDevice version  that is present on the nRF device and which Softdevice version that is used by the new bootloader. 

    Best regards

    Bjørn

  • This command was used to generate the .hex-file for the OLD we flashed onto the device using nrfjprog initially

    .\nrfutil4.exe settings generate --family NRF52 --application logger_app.hex --application-version 3 --bootloader-version 2 --bl-settings-version 1 settings.hex --no-backup
    .\mergehex.exe -m sd3.hex logger_app.hex boot_fixed_rtt.hex -o output_tmp.hex
    .\mergehex.exe -m output_tmp.hex settings.hex -o output.hex
    sd3.hex = s132_nrf52_3.0.0_softdevice.hex

    And we used the following command to create the .zip-DFU-package to successfully update the application-part of the OLD firmware via bluetooth

    .\nrfutil4.exe pkg generate --application ..\Firmware\_build\logger_app.hex --key-file ..\Firmware\priv.pem DFU_package.zip --hw-version 52 --sd-req 0x8C --application-version 3

    priv.pem = the OLD private key

    And then I tried to create the NEW DFU package in different ways.

    DFU package to replace the app-part only (works, basically the same as above). This caused the devices to crash on startup because the new app is no longer compatible with the old bootloader / softdevice

    res\nrfutil4.exe pkg generate --application build/NEW_App.out.hex --key-file REDACTED\Firmware\priv.pem DFU_App_w_oldkey.zip --hw-version 52 --sd-req 0x8C --application-version 3

    Next I tried to create a DFU package containing the NEW bootloader and NEW softdevice using the following command (again using the old key)

    .\res\nrfutil4.exe pkg generate --bootloader res/bootloader.hex --bootloader-version 3 --softdevice sdk/components/softdevice/s132/hex/s132_nrf52_6.1.1_softdevice.hex --sd-id 0xB7 --key-file REDACTED\Firmware\priv.pem DFU_BL_SD_w_oldkey.zip --hw-version 52 --sd-req 0x8C

    And that's the package I am unable to send and update with

  • So if you can update the application using a package generate with the following nrfutil command

    .\nrfutil4.exe pkg generate --application ..\Firmware\_build\logger_app.hex --key-file ..\Firmware\priv.pem DFU_package.zip --hw-version 52 --sd-req 0x8C --application-version 3

    but not a SoftDevice+Bootloader update with a firmware package generated using the following nrfutil command. 

    .\res\nrfutil4.exe pkg generate --bootloader res/bootloader.hex --bootloader-version 3 --softdevice sdk/components/softdevice/s132/hex/s132_nrf52_6.1.1_softdevice.hex --sd-id 0xB7 --key-file REDACTED\Firmware\priv.pem DFU_BL_SD_w_oldkey.zip --hw-version 52 --sd-req 0x8C

    Then that suggests that bootloader version is to low as the first package confirms that the private key and the --sd-req is correct. The sd-id is only used in SD+BL+APP images, so its not checked for a SD+BL image. 

    Are you able to debug the old booloader? The prevalidation of the init packet is done in dfu_handle_prevalidate() in dfu_req_handling.c. and you should be able see where the prevalidation fails by placing breakpoints. 

  • I was suspecting the bootloader versions too, but in my very first command I was setting said version to 2

    .\nrfutil4.exe settings generate --family NRF52 --application logger_app.hex --application-version 3 --bootloader-version 2 --bl-settings-version 1 settings.hex --no-backup
    

    So when creating the DFU-package with --bootloader-version 3 I thought that should to the trick?

    I'm not sure if I can debug the bootloader. It was compiled (and modified too, if I remember correctly. But only something related to the RTT output of the bootloader) by a former colleague who sadly left the company and was not really well practiced at documenting what he was working on... Not sure if I can even find the source code of his modified bootloader. I'll look into it.

    In theory I should be able to just create a new bootloader with the old SDK, old signing key and debug this one to see what's going wrong, right?

    Is there any chance that the bootloader he compiled just doesn't allow to update itself or the softdevice? Certainly he could have broken something, but could it be that some setting he overlooked prevented this from being possible?

  • Ah, missed that. Yes, then it shouldnt be the bootloader version. The remaining checks are then the bootloader size check, if the new bootloader is larger than the old one, then the prevalidation will fail. 

    #elif defined ( NRF52 )
        if (p_init->bl_size > NRF_MBR_PARAMS_PAGE_ADDRESS - BOOTLOADER_START_ADDR)
    #endif
        {
            return NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES;
        }

    and the available flash space check. 

    // Find the location to place the DFU updates
    err_code = nrf_dfu_find_cache(m_firmware_size_req, false, &m_firmware_start_addr);
    if (err_code != NRF_SUCCESS)
    {
        return NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES;
    }

    The S132 v3.x.x requires 124kB ( 0x1F000 bytes). 

    The S132 v6.1.1 requires 152 kB (0x26000 bytes)( 148kB without the MBR) . 

    The Secure Bootloader should not exceed 24kB, but If its the debug bootloader the size is 0xB000 and the start address is 0x73000. 

    So there should be 0x1F000 - 0x73000( debug bootloader start address) = 0x54000 ( 336kB available) so more than enough space for a BL and the S132 v6.1.1

     

    mikoay said:
    In theory I should be able to just create a new bootloader with the old SDK, old signing key and debug this one to see what's going wrong, right?

     Yes, that should be possible.  

    mikoay said:
    Is there any chance that the bootloader he compiled just doesn't allow to update itself or the softdevice? Certainly he could have broken something, but could it be that some setting he overlooked prevented this from being possible?

    Your former colleague may have heavily modified the old bootloader, but in general most customers modify the bootloader as little as possible. 

Related