CYW20829 platform description

Prerequisites

Cysecuretools

The CYW20829 chip has a set of security features. A special tool called cysecuretools is required to use most of them.

Cysecuretools is a Python3 package, which can be installed using the conventional python pip packet manager:

python -m pip install cysecuretools

Cysecuretools is used for reprovisioning of the chip, revocation of keys, security counter updates, image encryption, and more. For more details on functionality, go to https://pypi.org/project/cysecuretools or https://github.com/Infineon/cysecuretools#provision-device

Invocation of cysecuretools is build-in post-build jobs for MCUBootApp and BlinkyApp, so the user gets ready to use images after build.

MCUBootApp specifics

The PSoC CYW20829 can work in two modes - Non-Secure and Secure. In the Non-Secure (NORMAL_NO_SECURE) mode the CYW20829 works as a 'usual' Infineon chip. In the SECURE mode the following functionality becomes available:

  • signing of images;
  • rollback protection (hardware secure counter).

The work with the CYW20829 chip begins from the initialization of the project with the following device provisioning in the desired lifecycle - Non-Secure on Secure.

Device and environment initialization

For the cysecuretools environment setup, the MCUboot boot/cypress folder is used.

To create a common CYW20829 configuration, use:

cysecuretools -t cyw20829 init

To configure an OpenOCD package patch (via ModusToolbox™ by default):

cysecuretools set-ocd --name openocd --path C:/Users/%USERNAME%/ModusToolbox/tools_2.4/openocd

This is enough for a NORMAL_NO_SECURE lifecycle. But for SECURE LCS, a few more steps are necessary.

You will need to generate an RSA key pair (or copy it to the keys folder, if it was generated previously), to provision a chip in Secure mode:

cysecuretools -t cyw20829 -p policy/policy_secure.json create-key -k N

where N is the key number, zero or one.

To get access to the chip after provisioning, a debug certificate is required:

cysecuretools -t cyw20829 -p policy/policy_secure.json debug-certificate -t packets/debug_cert.json -o packets/debug_cert.bin -k N

where N is the key number, zero or one.

CYW20829 provisioning and reprovisioning

For the first provision of the CYW20829 chip, use:

cysecuretools -t cyw20829 -p policy/policy_%LCS%.json provision-device

or

cysecuretools -t cyw20829 -p policy/policy_reprovisioning_%LCS%.json reprovision-device [--key-id N]

for the following reprovision procedure.

More details about provisioning and reprovisioning processes you can find in README_CYW20829.md

Default memory map

The repository provides a set of predefined memory maps in JSON files. They are located in platforms/memory/CYW20829/flashmap. One can use the predefined flash map or define your own using the predefined file as a template.

Encrypted image support

CYW20829 does not have internal flash memory, so both primary and secondary images are located in external memory.

To protect the firmware from reading, place it in external memory in the encrypted form.

CYW20829 can execute encrypted firmware directly using the onboard hardware interface (SMIF) with special mode XIP (eXecute-In-Place). In this mode, all code is decrypted transparently by the AES algorithm.

MCUboot has its own Encrypted image mode to encrypt the firmware and transfer it with the AES session key included in the HKDF data block.

MCUboot image validation flow

  • Decrypt the AES key / initial vector (IV) from HKDF
  • Set up AES IV + CTR nonce (Image addr = base_addr + header_size)
  • Read slot data by MMIO
  • Decrypt the image in the slot using MCUboot internal functionality
  • Calculate and verify hash from decrypted data
  • Validate the slot image by hash and sign it

MCUboot image upgrade flow

  • Read slot 1 sector data using MMIO
  • Skip data decryption
  • Write data to the primary slot using MMIO

MCUboot Application Run

  • Set up SMIF registers
  • Set the AES key
  • Set AES IV
  • Set SMIF mode to XIP
  • Go to the application entry point

MCUBootApp and BlinkyApp can be built with an encrypted image plus encrypted XIP support using special build flags ENC_IMG=1. That flag will automatically enable XIP mode.

Example build command for MCUBootApp:

make clean app APP_NAME=MCUBootApp PLATFORM=CYW20829 BUILDCFG=Debug FLASH_MAP=platforms/memory/CYW20829/flashmap/cyw20829_xip_swap_single.json ENC_IMG=1

Example build command for BlinkyApp:

make clean app APP_NAME=BlinkyApp PLATFORM=CYW20829 BUILDCFG=Debug FLASH_MAP=platforms/memory/CYW20829/flashmap/cyw20829_xip_swap_single.json ENC_IMG=1

Rollback protection Support

As mentioned above, to use the rollback protection feature the device must be transferred to the SECURE lifecycle. The CYW20829 platform has a hardware-supported feature - a non-volatile counter (NV-counter). This feature is used by the MCUboot library to implement the rollback protection counter (security counter). NV-counter on CYW20829 is implemented as an Efuse-type region that can only be incremented. This means, that each time a new counter value is updated - a corresponding number of Efuse is burned.

The initial value of the rollback counter is programmed into the chip at the provisioning stage. The provisioning policy for Secure mode contains a corresponding field (file policy/policy_secure.json):

    "reprovisioning":
    {
        "nv_counter": {
            "description": "Anti-rollback counter. Each item of the 'value' array defines counter for each next application. Each 'bits_per_cnt' item defines number of bits for the next application counter (total bits number 32). IMPORTANT: 'bits_per_cnt' in the provisioning and reprovisioning policy files MUST BE the same",
            "value": [0],
            "bits_per_cnt": [32]
        },

or

    "reprovisioning":
    {
        "nv_counter": {
            "description": "Anti-rollback counter. Each item of the 'value' array defines counter for each next application. Each 'bits_per_cnt' item defines number of bits for the next application counter (total bits number 32). IMPORTANT: 'bits_per_cnt' in the provisioning and reprovisioning policy files MUST BE the same",
            "value": [0, 0],
            "bits_per_cnt": [24, 8]
        },

for multi-image case (2 images).

If the nv_counter value is left untouched, any image with counters higher than 0 and less than value defined by bits_per_cnt (or equal to) can be programmed into the chip.

bits_per_cnt also defines a distribution of eFuse among images in system. For example, in first case MCUBootApp is considered to be single image configuration with all 32 available eFuses dedicated to this one image.

In second case MCUBootApp is considered to be multi-image configuration with 2 images. 24 bits of 32 available eFuses are dedicated to image id 1, and 8 bits to image id 2.

This distribution can be changed by user at initial provisioning stage and SHOULD NOT be changed at later reprovisioning stages.

"value": [2, 3] filed sets corresponding value for image ids. Here 4 would be assigned to image id 1 and 5 to image id 2.

If the nv_counter value is encreased in policy/policy_secure.json at the provisioning stage, the nv_counter value in policy/policy_reprovisioning_secure.json must start from the value not less than the value in policy/policy_secure.json file.
More details about provisioning and reprovisioning processes you can find in README_CYW20829.md

When preparing an image for MCUBootApp with the rollback counter support, the cysecuretools signs it with policy/policy_secure.json in the post-build stage of make. The nv_counter value remains the same as one in the chip or sets higher. When cysecuretools signs an image, it places the nv-counter value and the reprovisioning packet in TLVs with tags 0x50 (bit mask representation of the counter) and 0x51 (reprovisioning packet). MCUBootApp then parses these tags and compares the value supplied with the image against the one stored in the Efuse counter.

If image counter value is set to higher then defined for this image by bits_per_cnt filed in policy, for example, image id 1 is provisioned to have 16 bits for its counter, but image programmed has nv counter value of 20 embedded in TLVs - MCUBootApp would discard it as invalid.

Building MCUBootApp and BlinkyApp with rollback protection

Examples of the build command with the rollback counter support for a single image and OVERWRITE mode:
for MCUBootApp:

make clean app APP_NAME=MCUBootApp PLATFORM=CYW20829 APP_DEFAULT_POLICY=./policy/policy_secure.json BUILDCFG=Debug FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_overwrite_single.json LCS=SECURE

for BlinkyApp with TLVs containing rollback counter data:

  • BOOT slot:

     make clean_boot app APP_NAME=BlinkyApp PLATFORM=CYW20829 IMG_TYPE=BOOT APP_DEFAULT_POLICY=./policy/policy_reprovisioning_secure.json FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_overwrite_single.json  
    
  • UPGRADE slot:

     make clean_upgrade app APP_NAME=BlinkyApp PLATFORM=CYW20829 IMG_TYPE=UPGRADE APP_DEFAULT_POLICY=./policy/policy_reprovisioning_secure.json FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_overwrite_single.json  
    

NV-counter update

To update NV-counter for an appropriate image you have to increase NV-counter in the reprovisioning policy /policy/policy_reprovisioning_secure.json, after that re-build the BlinkyApp and re-program your device.

The CYW20829 chip is designed so that the first stage bootloader called BootROM has most of the rights to modify the system - it is executed in the privileged protection context. Only BootROM can modify the content of Efuse where the NV counter is stored. BootROM supports the special type of service applications used when the user needs to modify the system. These apps are also provided with cysecuretools under targets/cyw20829/packets/apps. The reprovisioning application is used for NV-counter updates.

To enable the rollback counter feaure, one have to use a JSON flash map with the "service_app" section. Sample flash maps are located in boot/cypress/platforms/memory/CYW20829/flashmap/hw_rollback_prot.

The service application is supplied as a precompiled binary executed from RAM by BootROM. User should program either cyapp_reprovisioning_signed.hex (located at ./MCUBootApp/out/CYW20829/Debug/cyapp_reprovisioning_signed.hex) or similar binary ./packets/apps/reprovisioning/cyapp_reprovisioning_signed.bin (with the "address" specified in the "service_app" section of JSON flash map). Some other data is required for BootROM to execute the service app - this data is prepared by MCUBootApp.

When MCUBootApp detects that the rollback counter must be updated on CYW20829, it executes the function, which prepares input data and service application descriptor data and places it in flash at addresses "params_address" and "desc_address", respectively (see the "service_app" section in JSON flash map). Then, it sets the special flag in the service register, which signalizes BootROM to launch the service application and calls a system reset. BootROM then detects the service app with its data, copies it to the corresponding addresses in RAM, and executes it. Reprovisioning app then updates the nv-counter value in Efuse. An automatic reset can (and for convenience should) be initiated after that. To allow this value, sys_reset_req is set to true (false by default).

        "sys_reset_req": {
            "description": "Resets a device after RAM application finishes execution.",
            "value": true
        }

For more details on BootROM service applications, refer to the CYW20829 documentation.

Rollback counter behavior

Case 1

An image is singed using the policy_reprovisioning_secure.json policy with the nv-counter field value set to 1; the current value of NV-counter in the chip is 0 and programmed to the primary slot of MCUBootApp.

MCUBootApp validates the image in the primary slot and initiates a rollback counter update. The image in the primary slot is started after that.

Case 2

An image is signed using the policy_reprovisioning_secure.json policy with nv-counter, the field value is set to 2; the current value of NV-counter in the chip is 1 and programmed into the secondary slot of MCUBootApp. The upgrade type is 'swap'.

MCUBootApp validates the image in the secondary slot and initiates a firmware upgrade. After swapping the primary and secondary images, the firmware from the primary slot is executed immediately after the upgrade.

  • If the upgraded firmware operates correctly - starts its execution and sets the confirmation flag (read more in the design.md file), then, after the next reset, MCUBootApp updates the rollback counter value as in Case 1.

  • If the upgraded firmware operates incorrectly - does not start or does not set the confirmation flag, the watchdog initiates a system reset and MCUBootApp performs the revert operation - copies back the previous firmware from the secondary to the primary slot, marks the image in the secondary slot as invalid and executes the original firmware from the primary slot. The rollback counter is not updated in this case.

Case 3

An image is signed with the policy_reprovisioning_secure.json policy with nv-counter, the field value is set to 3; the current value of NV-counter in the chip is 4 and programmed to the secondary or primary slot of MCUBootApp. The upgrade type is 'swap'.

MCUBootApp tries to validate the image, detects that the value of the rollback counter stored in the chip is greater than the one provided with the image, and rejects such an image. The firmware in the primary slot will not start and an upgrade will not be initiated.

When the reprovisioning packet TLV is absent in the primary or secondary image TLVs, MCUBootApp marks such an image as invalid.

Multi-image case

See Rollback protection Support section for description.

Examples of the build command with the rollback counter support for the multi-image case, SWAP upgrade mode:

for MCUBootApp:

make clean app APP_NAME=MCUBootApp PLATFORM=CYW20829 APP_DEFAULT_POLICY=./policy/policy_secure.json FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_swap_multi2.json LCS=SECURE USE_HW_ROLLBACK_PROT=1

for BlinkyApp with TLVs containing rollback counter data:

  • BOOT slot, IMG_ID=1:

    make clean_boot app APP_NAME=BlinkyApp PLATFORM=CYW20829 IMG_TYPE=BOOT APP_DEFAULT_POLICY=./policy/policy_reprovisioning_secure.json FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_swap_multi2.json IMG_ID=1

  • UPGRADE slot, IMG_ID=1:

     make clean_upgrade app APP_NAME=BlinkyApp PLATFORM=CYW20829 IMG_TYPE=UPGRADE APP_DEFAULT_POLICY=./policy/policy_reprovisioning_secure.json FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_swap_multi2.json IMG_ID=1
    
  • BOOT slot, IMG_ID=2:

     make clean_boot app APP_NAME=BlinkyApp PLATFORM=CYW20829 IMG_TYPE=BOOT APP_DEFAULT_POLICY=./policy/policy_reprovisioning_secure.json FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_swap_multi2.json IMG_ID=2  
    
  • UPGRADE slot, IMG_ID=2:

     make clean_upgrade app APP_NAME=BlinkyApp PLATFORM=CYW20829 IMG_TYPE=UPGRADE APP_DEFAULT_POLICY=./policy/policy_reprovisioning_secure.json FLASH_MAP=platforms/memory/CYW20829/flashmap/hw_rollback_prot/cyw20829_xip_swap_multi2.json IMG_ID=2
    

Attention! Don't omit clean_boot and clean_upgrade to avoid any issues!

Programming applications

The HEXes for device programming you can find:

for MCUBootApp: MCUBootApp.hex in the directory 'MCUBootApp/out/CYW20829/{BUILDCFG}/

for BlinkyApp:

  • for IMG_ID=1, BOOT slot select BlinkyApp.hex inside of 'BlinkyApp/out/CYW20829/{BUILDCFG}/boot/'
  • for IMG_ID=1, UPGRADE slot select BlinkyApp_upgrade.hex inside of 'BlinkyApp/out/CYW20829/{BUILDCFG}/upgrade/
  • for IMG_ID=2, BOOT slot select BlinkyApp.hex inside of 'BlinkyApp/out.id2/CYW20829/{BUILDCFG}/boot/'
  • for IMG_ID=1, UPGRADE slot select BlinkyApp_upgrade.hex inside of 'BlinkyApp/out.id2/CYW20829/{BUILDCFG}/upgrade/

Default {BUILDCFG} is 'Debug', so all previous commands for the 'multi-image' case will build a 'Debug' configuration.

Using OpenOCD from command line

The following instruction assumes the usage of one of Cypress KitProg3 devices and a development board.

Connect the board to your computer. Switch Kitprog3 to DAP-BULK mode by clicking the SW3 MODE button until LED2 STATUS constantly shines.

Open the terminal application and execute the following command after substitution of the PATH_TO_APPLICATION and OPENOCD variables:

export OPENOCD=/Applications/ModusToolbox/tools_2.4/openocd

$OPENOCD_PATH/bin/openocd -s $OPENOCD_PATH/scripts -c "set ENABLE_ACQUIRE 0" -f $OPENOCD_PATH/scripts/interface/kitprog3.cfg -c "set SMIF_BANKS { 0 {addr 0x60000000 size 0x4000000 psize 0x1000 esize 0x40000} }" -f $OPENOCD_PATH/scripts/target/cyw20829.cfg -c "init; reset init; cmsis_flash init; flash write_image %PATH_TO_APPLICATION%/BlinkyApp.hex; shutdown"

Warning

The application slot is erased by flash erase_address before executing the flash write_image command.