Signing, Building and Flashing an Image for Secure Boot on the Qualcomm® QCA4020/4024 Platform

What is secure boot?

The boot path is a preferred attack vector. It is difficult to guard against attacks there because anti-malware can be disabled by malicious code that prevents it from loading entirely.

Secure boot is designed to protect the system against malicious code being loaded and executed early in the boot process, before firmware is loaded. In secure boot, OS boot images and code are authenticated against the hardware before they are used in the boot process. The hardware is set up beforehand in a way that it authenticates only the code generated using security credentials you trust. Secure boot ensures that the boot image and firmware are as the manufacturer intended and have not being altered by malware or bad actors.


The difference between a normal boot process and secure boot

Signing the image

On the QCA402x board, secure boot will recognize only those images with a matching pk_hash key, a type of secure credential. Building the application with pk_hash is called signing the image. The QCA4020 Development Board Application with a pk_hash key is said to be running a signed image.

The required keys and certificates for building a signed image are created while building the secure boot environment.

Prerequisites

The toolchain for Qualcomm cdb20, which supports both Windows and Linux, can be downloaded from the ARM website at https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads. The QCA402x board supports version 6.2 of the toolchain.

Once you have downloaded the toolchain, add the path of toolchain binaries to the ‘PATH’ environment variable.

  • Linux: export PATH=$PATH:/path/to/bin
  • Windows: set %PATH%=%PATH%:\path\to\bin

Secure boot on the QCA402x board

In secure boot, keys are generated from your SSL certificate, hashed and burned into the CPU in a One Time Programmable (OTP) process. Once a key has been burned into the processor, it cannot be changed.

Building and flashing OTP programmer

Three device profiles are available in building OTP:

  • Development profile
  • Production test profile
  • Production profile

In the code snippet below, we use the development profile:

  1. Edit the configuration file, \target\quartz\mfg\OTP\tools\otp_config.xml, with model_id, pk_hash, and otp_profile as shown.

          <otp_descriptor>
          <firmware_region_write_disable>0</firmware_region_write_disable>
          <model_id>0x0</model_id>
          <pk_hash>de5480d49ed1cbe0813755f06324fce56e3eb391a9a40ffba8df9fd16c717744</pk_hash>
          <otp_profile>development</otp_profile>
          </otp_descriptor>
        
  2. Build the QCA4020 Development Board Application.

          #build.bat t 4020 cdb in \target\quartz\mfg\OTP\build\gcc
        

Building the signed image

Edit the build script at \target\quartz\demo\QCLI_demo\build\gcc\build.bat as follows:

  1. Modify SECBOOT to true.

          SET SECBOOT=true
        
  2. To sign the FIREHOSE image prog_spinor_firehose_qca4020_lite_m4_threadx.mbn, add the following code below the cfg_model_id=0x0000 -o . -s line in build.bat along with the modifications suggested.

          python %SectoolsQdnDir%\sectools.py iot -p 4020 -g m4 -i
          %OUTDIR%\%PROJECT%.elf -k %SectoolsCertsDir%\qpsa_rootca.key -c
          %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff --
          cfg_model_id=0x0000 -o . -s
          
          python %SectoolsQdnDir%\sectools.py iot -p 4020 -g m0 -i %RootDir%\bin\cortex-m0\threadx\ioe_ram_m0_threadx_ipt.mbn -k %SectoolsCertsDir%\qpsa_rootca.key -c %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff --cfg_model_id=0x0000 -o . -s
          
          python %SectoolsQdnDir%\sectools.py iot -p 4020 -g kf -i %RootDir%\bin\wlan\wlan_fw_img.bin -k %SectoolsCertsDir\qpsa_rootca.key -c %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff  --cfg_model_id=0x0000 -o . -s
          
          python %SectoolsQdnDir%\sectools.py iot -p 4020 -g m4 -i %RootDir%\build\tools\flash\prog_spinor_firehose_qca4020_lite_m4_threadx.mbn -k %SectoolsCertsDir%\qpsa_rootca.key -c %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff --cfg_model_id=0x0000 -o . -s
        

    After you have modified build.bat, it should look like the following:

          if /I "%SECBOOT%" == "true" (
          if /I "%BOARD_VARIANT%" == "CDB" (
              python %SectoolsQdnDir%\sectools.py iot -p 4020 -g m4 -i
          %OUTDIR%\%PROJECT%.elf -k %SectoolsCertsDir%\qpsa_rootca.key -c
          %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff --
          cfg_model_id=0x0000 -o . -s
          
          python %SectoolsQdnDir%\sectools.py iot -p 4020 -g m0 -i %RootDir%\bin\cortex-m0\threadx\ioe_ram_m0_threadx_ipt.mbn -k %SectoolsCertsDir%\qpsa_rootca.key -c %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff --cfg_model_id=0x0000 -o . -s
          
          python %SectoolsQdnDir%\sectools.py iot -p 4020 -g kf -i %RootDir%\bin\wlan\wlan_fw_img.bin -k %SectoolsCertsDir\qpsa_rootca.key -c %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff  --cfg_model_id=0x0000 -o . -s
          
          python %SectoolsQdnDir%\sectools.py iot -p 4020 -g m4 -i %RootDir%\build\tools\flash\prog_spinor_firehose_qca4020_lite_m4_threadx.mbn -k %SectoolsCertsDir%\qpsa_rootca.key -c %SectoolsCertsDir%\qpsa_rootca.cer --cfg_oem_id=0xffff --cfg_model_id=0x0000 -o . -s
          )
        
  3. Build the QCA4020 Development Board Application.

          #build.bat t 4020 cdb in \target\quartz\mfg\OTP\build\gcc
        
  4. In target/build/tools/flash/prog_spinor_firehose_qca4020_lite_m4_threadx.mbn, replace the prog_spinor_firehose_qca4020_lite_m4_threadx.mbn with the one in QCLI_demo/build/gcc/4020/m4/prog_spinor_firehose_qca4020_lite_m4_threadx.mbn.

Flashing the signed image

  1. Generate the partition table using the following command in QCLI_demo/build/gcc/ .

          #python ..\..\..\..\..\build\tools\flash\gen_part_table.py --output=output\generated_partition_table.xml --begin=76KB --partition --file=.\4020\m4\Quartz.elf --partition --file=.\4020\m0\ioe_ram_m0_threadx_ipt.mbn --partition --file=.\4020\kf\wlan_fw_img.bin --partition --id=FS1 --start=12KB --size=64KB --partition --id=UNUSED --size=8KB --start=4KB
        
  2. Flash the image using the following command in QCLI_demo/build/gcc/ .

          #python ..\..\..\..\..\build\tools\flash\qflash.py --comm xx –nogen
        

    Status messages confirm whether you have flashed the secure image successfully.

          qflash.py Info: Download device programmer...
          qflash.py Info: Device Programmer loaded successfully
          qflash.py Info: Skipping to program image
          qflash.py Info: Program flash. Please wait...
          qflash.py Info: Flash programming complete!
        

    If so, the QCA402x board is running a secure image.