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

Parents Reply Children
  • 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

  • Hi Andreas,

    Does this still resonate with your understanding?

    Sorry, I’m a bit confused. Meaning, which two numbers should I make the same?

    This is configurations and result I tried.
    I made the values of SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE and CONFIG_FW_INFO_FIRMWARE_VERSION the same.
    After upgrading to '2' via the nRF Device Manager App, I tried to downgrade to '1'.
    Net Core's Downgrade Protection has failed.

    Result:

    [00:00:37.332,916] <inf> mcuboot_util: Image index: 0, Swap type: none
    [00:00:59.952,514] <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
    E: Image in the secondary slot is not valid!
    I: Image index: 1, Swap type: perm
    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 ***

    ./sysbuild.conf

    # STEP 2.1 Enable MCUboot
    SB_CONFIG_BOOTLOADER_MCUBOOT=y
    
    # STEP 6.3 - Configure project to use external flash for DFU
    SB_CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y
    
     # STEP 7.2 - Add b0n image
    SB_CONFIG_SECURE_BOOT_NETCORE=y
    
    # STEP 7.3 - Set up multiple partitions
    SB_CONFIG_MCUBOOT_UPDATEABLE_IMAGES=2
    
    # STEP 7.4 - Add support to netcore for DFU
    SB_CONFIG_NETCORE_APP_UPDATE=y
    
    # STEP 7.5 - Add support to mcuboot for updating
    # two cores simultaneously
    SB_CONFIG_MCUBOOT_NRF53_MULTI_IMAGE_UPDATE=y
    
    # STEP 7.6 - Simultaneous FOTA does not support rollback
    SB_CONFIG_MCUBOOT_MODE_OVERWRITE_ONLY=y
    
    # Enable Hardware-based downgrade protection using MCUboot
    SB_CONFIG_MCUBOOT_HARDWARE_DOWNGRADE_PREVENTION=y
    SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_SLOTS=4
    SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE=2

    ./prj.conf

    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    # Deferred logging helps improve LPN power consumption
    # when friendship is established.
    CONFIG_LOG_MODE_DEFERRED=y
    
    # General configuration
    CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="Mesh Light Fixture"
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    CONFIG_FLASH=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_NVS_LOOKUP_CACHE=y
    CONFIG_SETTINGS=y
    CONFIG_SETTINGS_NVS_NAME_CACHE=y
    CONFIG_HWINFO=y
    CONFIG_DK_LIBRARY=y
    CONFIG_PWM=y
    CONFIG_PM_SINGLE_IMAGE=y
    CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000
    CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE=y
    
    # Bluetooth configuration
    CONFIG_BT=y
    CONFIG_BT_DEVICE_NAME="Mesh Light Fixture"
    CONFIG_BT_L2CAP_TX_BUF_COUNT=8
    CONFIG_BT_OBSERVER=y
    CONFIG_BT_PERIPHERAL=y
    
    # Disable unused Bluetooth features
    CONFIG_BT_CTLR_LE_ENC=n
    CONFIG_BT_PHY_UPDATE=n
    CONFIG_BT_CTLR_CHAN_SEL_2=n
    CONFIG_BT_CTLR_MIN_USED_CHAN=n
    CONFIG_BT_CTLR_PRIVACY=n
    
    # Bluetooth Mesh configuration
    CONFIG_BT_MESH=y
    CONFIG_BT_MESH_RELAY=y
    CONFIG_BT_MESH_FRIEND=y
    CONFIG_BT_MESH_TX_SEG_MAX=10
    CONFIG_BT_MESH_PB_GATT=y
    CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME=y
    CONFIG_BT_MESH_GATT_PROXY=y
    CONFIG_BT_MESH_ADV_EXT_GATT_SEPARATE=y
    CONFIG_BT_MESH_DK_PROV=y
    CONFIG_BT_MESH_NLC_PERF_CONF=y
    CONFIG_BT_MESH_NLC_PERF_LIGHTNESS_CTRL=y
    CONFIG_BT_MESH_MODEL_EXTENSIONS=y
    CONFIG_BT_MESH_MODEL_EXTENSION_LIST_SIZE=18
    # Enabling BT_MESH_NLC_PERF_CONF enables support for 3 application keys by
    # default. Therefore, allow up to 3 application key bindings per model instance.
    CONFIG_BT_MESH_MODEL_KEY_COUNT=3
    
    # Bluetooth Mesh models
    CONFIG_BT_MESH_LIGHT_CTRL_SRV=y
    CONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_ON=3
    CONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_PROLONG=3
    CONFIG_BT_MESH_LIGHT_CTRL_SRV_RESUME_DELAY=30
    CONFIG_BT_MESH_SCENE_SRV=y
    CONFIG_BT_MESH_SENSOR_SRV=y
    
    # STEP 2.2 - Enable FOTA over Bluetooth LE
    CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y
    
    # Enable updates for the network core
    CONFIG_NRF53_UPGRADE_NETWORK_CORE=y

    ./sysbuild/mcuboot.conf

    # STEP 6.2 - MCUboot should use external flash
    CONFIG_NORDIC_QSPI_NOR=y
    CONFIG_BOOT_MAX_IMG_SECTORS=256
    
    # Enable PCD command to read network core application version
    CONFIG_FW_INFO=y
    CONFIG_PCD_READ_NETCORE_APP_VERSION=y
    
    # Enable Debug Log
    CONFIG_MCUBOOT_LOG_LEVEL_DBG=y

    ./sysbuild/b0n.conf

    # Enable PCD command to read network core application version
    CONFIG_PCD_READ_NETCORE_APP_VERSION=y

    ./sysbuild/ipc_radio/prj.conf

    CONFIG_HEAP_MEM_POOL_SIZE=8192
    CONFIG_MAIN_STACK_SIZE=2048
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    
    CONFIG_MBOX=y
    CONFIG_IPC_SERVICE=y
    
    CONFIG_BT=y
    CONFIG_BT_HCI_RAW=y
    CONFIG_BT_MAX_CONN=16
    
    # Copy controller configuration from prj.conf
    CONFIG_BT_CTLR_LE_ENC=n
    CONFIG_BT_CTLR_CHAN_SEL_2=n
    CONFIG_BT_CTLR_MIN_USED_CHAN=n
    CONFIG_BT_CTLR_PRIVACY=n
    
    # Enables the extended advertising API support and the necessary amount of advertising sets
    # in the Bluetooth controller on the network core required by the Bluetooth Mesh.
    CONFIG_BT_EXT_ADV=y
    CONFIG_BT_EXT_ADV_MAX_ADV_SET=5
    
    CONFIG_IPC_RADIO_BT=y
    CONFIG_IPC_RADIO_BT_HCI_IPC=y
    
    # Step 9.2 - Enable logs in netcore so we can verify the update
    CONFIG_SERIAL=y
    CONFIG_UART_CONSOLE=y
    CONFIG_LOG=y
    
    # Enable version number of the firmware
    CONFIG_FW_INFO_FIRMWARE_VERSION=2
    
    # Enable logs in netcore
    CONFIG_IPC_RADIO_LOG_LEVEL_WRN=y

    Kind regards,

    a.da

Related