Hardware-based downgrade protection in nRF5340

Hello.

This ticket was derived from another ticket.

I have a few questions about hardware-based downgrade protection.

  • About the Downgrade Protection of the Network Core
    Even with Downgrade Protection enabled, the Network Core is still downgradeable.
    However, version mismatches between the App Core and the Network Core should be avoided.
    If you have any ideas on how to resolve this, please let me know.
  • About the monotonic counter
    Is there a way to retrieve the current value?
    I am assuming it will be displayed on a PC serial terminal or a smartphone app.
  • About Image Swap
    It seems that when the update count reaches the value of SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS, the Image Swap of the App Core is performed every time the software is rebooted.
    Is this the expected behavior?

The logs during the update and reboot are as follows:

monotonic counter < SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS

Update

[00:00:18.749,969] <err> mcumgr_img_grp: Failed to open flash area ID 1: -2
[00:00:19.052,307] <inf> mcuboot_util: Image index: 0, Swap type: none
[00:00:41.610,382] <inf> mcuboot_util: Image index: 1, Swap type: none
*** Booting MCUboot v2.1.0-dev-12e5ee106034 ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
I: Starting bootloader
I: Image index: 0, Swap type: perm
I: Image index: 1, Swap type: perm
I: Image 0 upgrade secondary slot -> primary slot
I: Erasing the primary slot
I: Image 0 copying the secondary slot to the primary slot: 0x44784 bytes
D: writing magic; fa_id=4 off=0xebff0 (0xf7ff0)
D: erasing secondary header
D: erasing secondary trailer
I: Image 1 upgrade secondary slot -> primary slot
I: Erasing the primary slot
I: Image 1 copying the secondary slot to the primary slot: 0x2a3c0 bytes
D: writing magic; fa_id=1 off=0x3fff0 (0x3fff0)
D: erasing secondary header
D: erasing secondary trailer
I: Bootloader chainload address offset: 0xc000
*** Booting Mesh Light Fixture v2.9.0-d54b9798c66e ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***

Reboot

*** Booting MCUboot v2.1.0-dev-12e5ee106034 ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
I: Starting bootloader
I: Image index: 0, Swap type: none
I: Image index: 1, Swap type: none
I: Bootloader chainload address offset: 0xc000
*** Booting Mesh Light Fixture v2.9.0-d54b9798c66e ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***

monotonic counter = SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS

Update

[00:00:30.237,457] <err> mcumgr_img_grp: Failed to open flash area ID 1: -2
[00:00:30.538,299] <inf> mcuboot_util: Image index: 0, Swap type: none
[00:00:53.067,932] <inf> mcuboot_util: Image index: 1, Swap type: none
*** Booting MCUboot v2.1.0-dev-12e5ee106034 ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
I: Starting bootloader
I: Image index: 0, Swap type: perm
I: Image index: 1, Swap type: perm
I: Image 0 upgrade secondary slot -> primary slot
I: Erasing the primary slot
I: Image 0 copying the secondary slot to the primary slot: 0x44784 bytes
D: writing magic; fa_id=4 off=0xebff0 (0xf7ff0)
E: Security counter update failed after image upgrade.
I: Image 1 upgrade secondary slot -> primary slot
I: Erasing the primary slot
I: Image 1 copying the secondary slot to the primary slot: 0x2a3c0 bytes
D: writing magic; fa_id=1 off=0x3fff0 (0x3fff0)
D: erasing secondary header
D: erasing secondary trailer
I: Bootloader chainload address offset: 0xc000
*** Booting Mesh Light Fixture v2.9.0-d54b9798c66e ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***

Reboot

*** Booting MCUboot v2.1.0-dev-12e5ee106034 ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
I: Starting bootloader
I: Image index: 0, Swap type: perm
I: Image index: 1, Swap type: none
I: Image 0 upgrade secondary slot -> primary slot
I: Erasing the primary slot
I: Image 0 copying the secondary slot to the primary slot: 0x44784 bytes
D: writing magic; fa_id=4 off=0xebff0 (0xf7ff0)
E: Security counter update failed after image upgrade.
I: Bootloader chainload address offset: 0xc000
*** Booting Mesh Light Fixture v2.9.0-d54b9798c66e ***
*** Using nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***

Thanks for reading.

a.da

  • Hi a.da

    I've picked up your case and will be looking into it early next week. As a starter I was hoping you could have a look at  CONFIG_MCUBOOT_HARDWARE_DOWNGRADE_PREVENTION in NRF5340 multi update and see if the solution in this case and/or the case this one refers to is of any help in resolve the issues you're observing with the netcore downgrade protection not being enabled?

    Kind regards,
    Andreas 

  • Hi Andreas, thanks for your reply.

    I've picked up your case and will be looking into it early next week.

    I appreciate your assistance.

    As a starter I was hoping you could have a look at  CONFIG_MCUBOOT_HARDWARE_DOWNGRADE_PREVENTION in NRF5340 multi update and see if the solution in this case and/or the case this one refers to is of any help in resolve the issues you're observing with the netcore downgrade protection not being enabled?

    I have already referred to that page.
    The need to change 'CONFIG_FW_INFO_FIRMWARE_VERSION' means that Net Core has Software-based downgrade protection enabled, right?
    By simply changing 'SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE', can we enable Hardware-based downgrade protection on both App Core and Net Core?
    I believe that the combination of App Core and Net Core versions must always match.
    Therefore, if we want to implement downgrade protection, I think it needs to be enabled on both App Core and Net Core.
    Also, it is preferable to have a single piece of information that manages the combination.

    Kind regards,

    a.da

  • Hi,

    a.da said:
    I have already referred to that page.

    Great!

    a.da said:
    The need to change 'CONFIG_FW_INFO_FIRMWARE_VERSION' means that Net Core has Software-based downgrade protection enabled, right?

    It implies it but it does not necessarily enable it as you can have firmware versions without enabling downgrade protection.

    For software-based downgrade protection you need CONFIG_MCUBOOT_DOWNGRADE_PREVENTION enabled for the mcuboot image (i.e within sysbuild/mcuboot.conf or sysbuild/mcuboot/mcuboot.conf) and SB_CONFIG_MCUBOOT_MODE_OVERWRITE_ONLY=y enabled in sysbuild.conf for "CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY (see Sysbuild forced options)

    "MCUboot has been configured to just overwrite primary slot

    MCUboot will take contents of secondary slot of an image and will overwrite primary slot with it. In this mode it is not possible to revert back to previous version as it is not stored in the secondary slot. This mode supports MCUBOOT_BOOTLOADER_NO_DOWNGRADE which means that the overwrite will not happen unless the version of secondary slot is higher than the version in primary slot."

    a.da said:
    By simply changing 'SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE', can we enable Hardware-based downgrade protection on both App Core and Net Core?

    CONFIG_MCUBOOT_HARDWARE_DOWNGRADE_PREVENTION enables Downgrade prevention using hardware security counters meaning you can use the counter values from 

    To my understanding, this means you can have different counters for the different slots, and if you intend to only upgrade the app core you need to increment the counter for the image corresponding to the app core, and respectively the same for the counter for the netcore when you upgrade the firmware in the netcore.

    Furthermore in https://github.com/nrfconnect/sdk-mcuboot/blob/148712e7b4618aadbedd04e8d3ce5c3847d3be4f/boot/bootutil/src/loader.c#L1063 you can see pcd_version_cmp_net() which checks the netcore version in MCUboot, i.e MCUBoot checks the versioning for you and it checks it different than the application version number, i.e through boot_version_cmp (L1066 and L:1068).

    a.da said:
    I believe that the combination of App Core and Net Core versions must always match.

    I've not seen anything indicating that you need to do this, since you can have separate counters for both. I know that you can have different firmware versioning for appcore and netcore based on https://github.com/nrfconnect/sdk-mcuboot/blob/148712e7b4618aadbedd04e8d3ce5c3847d3be4f/boot/bootutil/src/loader.c#L1063 

    Kind regards,
    Andreas

  • Hi Andreas,

    Thank you for your detailed explanation. I also apologize for my inadequate explanation.

    It implies it but it does not necessarily enable it as you can have firmware versions without enabling downgrade protection.

    Yes, I understand how to enable Software-based downgrade protection.

    To my understanding, this means you can have different counters for the different slots, and if you intend to only upgrade the app core you need to increment the counter for the image corresponding to the app core, and respectively the same for the counter for the netcore when you upgrade the firmware in the netcore.

    Do you mean to set it up as follows?

    App Core ( ./sysbuild.conf )

    • SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS
    • SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE

    Net Core ( ./sysbuild/<netcore_name>/prj.conf )

    • CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS
    • CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE
    I've not seen anything indicating that you need to do this, since you can have separate counters for both.

    The term 'version' was not appropriate.
    I understand that we need to prevent inconsistencies in the configuration (Project / Source Code) in which the software was built.

    Kind regards,

    a.da

  • a.da said:
    Thank you for your detailed explanation. I also apologize for my inadequate explanation.
    a.da said:
    Yes, I understand how to enable Software-based downgrade protection.

    No worries, happy to discuss it further

    a.da said:

    Do you mean to set it up as follows?

    App Core ( ./sysbuild.conf )

    • SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS
    • SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE

    Net Core ( ./sysbuild/<netcore_name>/prj.conf )

    • CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS
    • CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE

    I did a revisit to my investigation yesterday, and I think my conclusion has changed somewhat. I was under the impression that we supported individual app and netcore versioning and downgrade protection, but it looks to be as you said initially, i.e this:

    a.da said:
    By simply changing 'SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE', can we enable Hardware-based downgrade protection on both App Core and Net Core?
    I believe that the combination of App Core and Net Core versions must always match.


     https://github.com/nrfconnect/sdk-mcuboot/blob/148712e7b4618aadbedd04e8d3ce5c3847d3be4f/boot/bootutil/src/loader.c#L1063 shows that downgrade protection for netcore is only valid in a multi image update for the nrf5340, i.e a simultaneous update.

    Conclusion:

    These configurations works for both cores and must be maintained similarly. App and netcore versions must match to enable downgrade protection on both cores since it requires simultaneous multi-image update to work.

    • SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS
    • SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE

    Does this still resonate with your understanding?

    Kind regards,
    Andreas

Related