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.
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:
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.
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.
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
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.
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
MCUboot image upgrade flow
MCUboot Application Run
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
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.
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
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.
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!
The HEXes for device programming you can find:
for MCUBootApp: MCUBootApp.hex
in the directory 'MCUBootApp/out/CYW20829/{BUILDCFG}/
for BlinkyApp:
BlinkyApp.hex
inside of 'BlinkyApp/out/CYW20829/{BUILDCFG}/boot/'BlinkyApp_upgrade.hex
inside of 'BlinkyApp/out/CYW20829/{BUILDCFG}/upgrade/BlinkyApp.hex
inside of 'BlinkyApp/out.id2/CYW20829/{BUILDCFG}/boot/'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.
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.