wiki:newport/trusted-boot

Securing your Newport board

A quick summary of what you will need to do if you wish to secure your Newport board from any tampering:

  • Create a Root Of Trust (ROT) Private Key or use the one auto-generated by the bdk build.
    • The private key is stored in bdk/trust-keys/hw-rot-private.pem
    • An openssl command to generate the key is:
      openssl ecparam -name prime256v1 -genkey -noout -out bdk/trust-keys/hw-rot-private.pem
      
  • Create a BDK private key or use the one generated by the bdk build:
    • The key is stored in bdk/trust-keys/bdk-sign-private.pem
    • An openssl command to generate a BDK key:
      openssl ecparam -name prime256v1 -genkey -noout -out bdk/trust-keys/bdk-sign-private.pem
      
  • build the BDK firmware image with FUSES=1 and ALLOW_DIAGNOSTICS=1 (ie make -s -j8 firmware-image FUSES=1 ALLOW_DIAGNOSTICS=1)
    • The FUSES=1 displays the FUSE values you will need to hard blow into the One-Time-Programmable (OTP) fuses using the bdk diagnostics app.
    • The ALLOW_DIAGNOSTICS=1 configures the BDK to allow the diagnostics app and instructs the Makefile to inject the diagnostics app in the embedded FAT12 filesystem.
  • boot this firmware and use the diagnostics app to blow the fuses:
    1. Use 'B' when prompted with Press 'B' within 2 seconds for boot menu.
    2. Next use 'D' to enter diagnostics app at the 'Boot Options' menu.
    3. Next select '20' to select the 'Trusted Boot options' menu item.
    4. Next use the various menu options to hard blow fuses:
      • ROTPK hard fuses per the display caused by TRUST=1
      • FUSF_CTL[ROT_LCK]=1 to lock the ROTPK from being changed
      • FUSF_CTL[TZ_FORCE2]=1 to enable trusted boot
    5. Optionally blow additional fuses per your needs:
      • blow the FUSF_CTL[FJ_DIS], FUSF_CTL[FJ_TIMEOUT], FUSF_CTL[FJ_CORE0], FUSF_CTL[FJ_DIS_HUK] if you wish to disable fallback jump necessary for recovery
      • blow the SSK and/or HUK for encrypted data and blow the FUSF_CTL[SSK_LCK] and FUSF_CTL[HUK_LCK] to lock them

These steps are detailed below

Trusted Boot

Trusted Mode Boot is Cavium's hardware and firmware implementation of secure boot based on the ARM Trusted Board Boot Requirements (TBBR) specification described in the ARM Trusted Firmware. It utilizes the ARM TrustZone architecture and the ARM Trusted Firmware (ATF).

This trusted-mode boot solution ensures that all firmware is exactly as the OEM intends and that no FLASH tampering has occurred.

At power-up the on-chip secure BOOT ROM code runs in ARM secure EL3. This code is responsible for reading the boot firmware from flash and validating it against fused Root of Trust Public Key (ROTPK) before running it. This establishes the ROTPK as the initial chain of trust and each following boot step must be validated in step using their own public keys and certificates. The U-Boot bootloader runs in ARM non-secure EL2 and loads and runs the OS which runs in ARM non-secure EL1.

During product development you can use temporary security settings then switch to hardware fuse based security settings during production.

Gateworks is the board manufacturer (what Cavium refers to as the Original Design Manufacturer or ODM). The Gateworks customer is the OEM that is ultimately responsible for software development and typically provides the secure boot firmware.

There are several signing keys used throughout the boot process and there are provisions for different parties being in charge if different keys. The Cavium BDK (used by the Boot Firmware Gateworks provides) build process creates a Board Development Kit (BDK) public key.

Additionally the CN80XX/CN81XX supports fused non-volatile counters that can be used to revoke compromised keys and keep obsolete firmware from being authenticated (rollback protection). These counters are set to an initial value in production and then incremented over the life of the product if the firmware is updated or public keys need to be revoked. Certificates which contain firmware hash values or keys also contain a field specifying the counter (the certificate version number). There are two fused non-volatile counters: one for trusted firmware, and one for non-trusted firmware.

The options provided by the CN80XX allow the OEM to select different degrees of security from 'extremely secure' (if image is corrupted no repair is possible) all the way to completely insecure (which is useful during development).

You can choose things such as:

  • Optionally require SoC to always use trusted-mode boot and never non-trusted
  • Optionally allow a corrupted boot image to be repaired (via non-trusted recovery image)
  • Optionally set different levels of firmware encryption (anti-snooping)

Important Note: Once boards have been configured for trusted-mode boot by hard blowing fuses they can not be re-tested by Gateworks and as a result returns (RMA) will not be accepted. It is recommended that OEM's test board functionality before permanently setting trusted-mode boot fuses.

References:

Cavium CN80XX/CN81XX BDK Trusted Boot Overview

Maintaining a chain of trust from the chip secure ROM into the final operating system requires that each file in the boot path be authenticated. Cavium processors use a combination of the BDK and ARM Trusted Firmware (ATF) code to maintain the chain of trust up through the bootloader. The bootloader (UEFI, Uboot, etc) is then responsible for authenticating the final operation system.

Terminology:

  • TBL1FW: Trusted Boot Level 1 Firmware. The first code loaded from flash by the BOOT ROOM, located at offset 0x50000 of the boot device.
  • CSIB: Cavium ROM Code Signature Information-Block Structure. Located at 0x10300, contains the SHA256 hash of TBL1FW, and the root of trust (ROT) public key.
  • CLIB: Cavium ROM Code Load Information-Block Structure. Located at 0x10200, contains the CSIB signature.
  • CoT: Chain of Trust.
  • ROT: Root of Trust.
  • ROTPK: Root of Trust Public Key (derived from ROT private key).
  • BOOT ROM: The firmware in the CN80XX/CN81XX SoC that fetches and authenticates the TBL1FW (first stage of firmware also know as the 'boot stub').

Newport CN80XX/CN81XX Chain of Trust (CoT)

Trusted boot requires authenticating each boot stage before using the data and/or executing the code. This authentication is done using a series of public keys, signatures, and an authentication algorithm. This authentication is anchored in the Root of Trust Public Key (ROTPK) which is fused in the CN80XX/CN81XX by the OEM. Each subsequent public key is contained in an authenticated image and this process is referred to as the 'Chain of Trust (CoT)'.

From the hardware perspective the boot process starts with the secure on-chip BOOT ROM code, then either the TBL1FW (trusted mode) or the NBL1FW (non-trusted). The firmware designer chooses the path of execution from this point. The Cavium BDK firmware solution that Gateworks provides for Boot Firmware follows the typical ARM path: the boot-level 1 (BL1) firmware (TBL1FW/NBL1FW) runs then sequentially BDK BL1 code, ATF BL1 code, ATF boot-level 2 (BL2) code, boot-level 3 (BL31, BL33), U-Boot, and operating system.

The following table shows these items, and what execution level (EL) they run at:

item Execution Level (EL) Authenticated Trusted
Secure BOOT ROM EL3 (secure) Yes Yes
BDK code EL3 (secure) Yes Yes
ATF BL1 EL3 (secure) Yes Yes
ATF FIP BL2 S-EL1 1 (secure) Yes Yes
ATF FIP BL31, BL33 EL3 (secure) Yes Yes
U-Boot EL2 (not secure) Yes No
OS / rootfs EL1 (not secure) 2 No
Applications EL0 (not secure) 2 No
  1. ATF's BL2 image is executed at S-EL1 level. In the future BL2 may be run in EL2
  2. The OS and rootfs authentication will be done by the authenticated bootloader. This is done in U-Boot using the Flattened Image Tree (FIT) which validates hashes

Secure vs Trusted:

  • Secure:
    • EL3 is always a secure execution level
    • EL2 is always a non-secure execution level
    • EL0 and EL1 can be either secure or non-secure:
      • Secure: S-EL0 and S-EL1 denote secure levels
      • Non-Secure: EL0 and EL1 denote non-secure levels
  • Trusted: must bmeet two conditions:
    1. the code was authenticated but not necessary 'secure'
    2. the code is executing in one of the following processor modes:
      • S-EL0 (Secure Exception Level 0)
      • S-EL1 (Secure Exception Level 1)
      • EL3 (Exeception Level 3)

The bootloader (U-Boot is used by Gateworks) is authenticated by ATF BL2 but they are not 'trusted' code because it is easy to compromise. For example, U-Boot provides a menu that allows the user to read/modify memory from the command line. This means the U-Boot code that validates the OS image can be overwritten which would be a security hole. U-Boot needs services from the secure world to properly verify an OS image it loads which is why U-boot runs in non-secure EL2. U-Boot runs at EL2 so it can start a hypervisor. The Linux kernel starts at LE2 then jumps to EL1 so it can install a hypervisor.

The OS authentication must be be done by the authenticated bootloader and the implementation of this is up to the OEM.

If the chain of trust is broken at the TBL1FW level, then the boot process options are controlled by FUSE_CTL options which can allow or dis-allow jumping to non-trusted boot. If the chain of trust is borken software must write a 1 to RST_BOOT[DIS_HUK] register to hide the fused secrets from non-trusted software.

Hardware Flash Layout

The CN80xx secure BOOT ROM dictates the following hardware flash layout:

Region Address Description
0x0000 0000 - 0x0000 FFFF Available for software use (but reserved for BDK use)
0x0001 0000 - 0x0001 00FF 256 bytes: non-trusted (NB1FW) CLIB
0x0001 0100 - 0x0001 01FF 256 bytes: non-trusted (NB1FW) CSIB
0x0001 0200 - 0x0001 02FF 256 bytes: trusted (TB1FW) CLIB
0x0001 0300 - 0x0001 03FF 256 bytes: trusted (TB1FW) CSIB
0x0001 0400 - 0x0001 FFFF Reserved - not available for software use
0x0002 0000 - 0x0004 FFFF 192Kbytes: NBL1FW code (unencrypted). Bytes 0-255 are ignored
0x0005 0000 - 0x0007 FFFF 192Kbytes: TBL1FW code (optionally encrypted). Bytes 0-255 are ignored. Signed by the fused ROTPK
0x0008 0000 - up Available for software use; typically contains later stage boot images

Fuses

The CN80XX/CN81XX has a set of one-time-programmable (OTP) fuses many of which control trusted boot.

  • FUSF_ROTPK(0..3): 256bit SHA256 hash of the ROT public key
  • FUSF_SSKX(0..1): 128bit AES128 key for Secret Symmetric Key Encryption (for product line based anti-snooping encryption)
  • FUSF_HUKX(0..1): 128bit AES128 key for Binding Secret Symmetric Key Encryption (for device-specific anti-snooping encryption)
  • FUSF_EKX(0..3): 256bit ECC Private Endorsement Key (unused by the BDK)
  • FUSF_SWX(0..7): 512bit Software defined fuses (unused by the BDK)
  • FUSF_CTL: Trusted boot configuration options
    • TZ_FORCE2 - if set override GPIO_STRAP[TRUSTZONE] and require trusted-mode boot (should be last thing blown)
    • FJ_DIS - if set disable flash jump. If set TZ_FORCE2 must also be set. Setting this is for high security and dis-allows any recovery option
    • FJ_TIMEOUT - 2 bits: THe flash jump chip kill timer value (0 means chip kill is disabled)
    • FJ_CORE0 - if set only core 0 is available
    • FJ_DIS_HUK - if set the secret fuses (FUSF_CTL[SSK, HUK, EK, SW]) are hidden from non-trusted code at boot time. This is typically set after the secret fuses are set at production time
    • CRYPT_NO_DIS - if set the CSIB crypt field is not allowed to be 'no encryption'
    • CRYPT_SSK_DIS - if set the CSIB crypt field is not allowed to be 'SSK'
    • ROM_T_CNT - 32bits: ROM trusted counter typically set tot he firmware version number and incremented when the firmware is updated. Initial value is 0. First firmware version sets the value to 1. The value is the population count: 31 legal values. All ones is an overflow condition
    • FUSF_LCK - locks all fuses (do not do this if you want to use ROM_T_CNT counters)
    • ROT_LCK - locks the Root Of Trust Public Key (ROTPK), Hardware Unique Key (HUK), and ECC Private Endorsement Key (EK) from further modification.
    • SSK_LCK - locks the Secret Symmetric Key (SSK)
    • SW_LCK - locaks the software secure space

All fuses default to 0 and once blown to 1 can not be changed back to a 0. Note that FUSF_CTL[TZ_FORCE2] must be set if FUSF_CTL[FJ_DIS]=1, FUSF_CTL[FJ_CORE0]=1, or FUSEF_CTL[FJ_TIMEOUT]!=0. Also note that if flash jump to non-trusted firmware is allowed care must be taken to ensure that non-trusted firmware execution fits with the security model for the device.

All fuses also have the ability to be 'soft blown' where their values are retained until a hard reset which is used to test fuse settings before blowing them permanently (hard blow). However if a fuse is locked, soft blow can not change the fuse value in local memory.

Hard fuse blowing requires board power supplies enable 1.5V (the fuse blowing foltage) on EFUSE_PROG and hold EFUSE_ENABLE_L low. Please contact sales@… to make sure your board revision has this capability.

The HUK, SSL, EK, and SW fuses may contain information that is private therefore for security the visibility of these fuses to software can be managed via:

  • FUSF_CTL[FJ_DIS_HUK] fuse - set this to hid HUK, SSK, EK, and SW whenever trusted mode boot is not used or fails
  • RST_BOOT[DIS_HUK] register - software can set this bit if the chain of trust becomes broken to hide HUK, SSK, EK, and SW bits
  • CSIB[EXPOSE] field - this can be set in firmware image to hide HUK, SSK, EK, and SW bits

Most field fuses are set when the OEM finalizes the product however two sets of fuses are typically updated during the product lifetime:

  • FUSF_CTL[ROM_T_CNT] fuses: The boot logic checks if the current trusted firmware version number is >= ROM_T_CNT. This uses the NVCNT field in the CSIB data structure and is there to allow prevention of a rollback attack where you do not want older software to be able to be installed.
  • FUSE_SW(0..7) fuses: These fuses can be used by software.

Fuses that will typically be configured for secure boot:

  • Blow FUSF_ROTPK
  • Blow FUSF_HUK - save HUK in a database with chip/system ID if it will be used for firmware encyrption
  • Blow FUSF_EK - optional - save public portion of EK in database with chip/system ID
  • Blow FUSF_CTL[ROT-LCK] - this locks down and prevents any further modification to the FUSF_ROTPK, FUS_HUK, and FUSF_EK
  • Blow FUS_CTL[FJ_DIS_HUK] - this hides secure fuse values (SSK, HUK, EK, SW) from non-trusted code in the case of non-trusted boot
  • Blow FUSF_SSK
  • Blow FUSF_CTL[SSK_LCK] - this locks down the SSK and prevents any further modification of the SSK
  • Flash Jump:
    • if only trusted-mode boot is desired blow the FUSF_CTL[FJ_DIS] and FUSF_CTL[TZ_FORCE2] fuses
    • optionally enable flash jump which allows non-trusted firmware to run if TBL1FW boot fails (for flash repair): set FUSF_CTL[FJ_DIS]=0, FUSF_CTL[TZ_FORCE2]=1, FUSF_CTL[FJ_TIMEOUT] to desired value, FUSF_CTL[FJ_CORE0] to desired value
  • Encryption configuration fuses:
    • FUSF_CTL[CRYPT_NO_DIS]: requires encryption of firmware
    • FUSF_CTL[CRYPT_SSK_DIS]: disables SSK based encryption and requires BSSK encryption. Tyipically set with CRYPT_NO_DIS
  • Global lock, SW Lock: The FUSF_CTL[FUSF_LCK] and FUSF_CTL[SW_LCK] fuses should never be set. These fuses need to be unlocked to permit updating the trusted and non-trusted NV counter fuses (ROM_T_CNT and SW, respectively)

When building the BDK for trusted boot, you can easily loose track of the various FUSF settings for ROTPK, SSK, and HUK. You can add FUSES=1 to the bdk target to see this information.

$ make -s -j8 bdk FUSES=1
BDK_ROOT not set, assuming /usr/src/newport/bsp/bdk
Root of Trust Public Key:
    Qx:            23b6f9ebf3e712b1061b43323b321113711e2a1d6a4277328243c8eaa4476584
    Qy:            b729fd87c510daf2225028a6e4d9982c319d6188083ccb1489ae8cf53a471883
    CSIB ROTPK:    846547a4eac843823277426a1d2a1e711311323b32431b06b112e7f3ebf9b6238318473af58cae8914cb3c0888619d312c98d9e4a6285022f2da10c587fd29b7
    FUSF_ROTPK[0]: 0xaba31863b14a9edf
    FUSF_ROTPK[1]: 0x43176c0377a1d485
    FUSF_ROTPK[2]: 0x9b816ad453a0d964
    FUSF_ROTPK[3]: 0xbe91fda1f893a251
Field Fuses:
    0x3ff:0x300 (ROTPK SHA256) be91fda1f893a2519b816ad453a0d96443176c0377a1d485aba31863b14a9edf

Blowing Fuses

While custom software can be written to facilitate fuse blowing, the BDK 'diagnostics' application supports both soft blow and hard blow (permanent) fuse blowing. Note that the diagnostics are used only in a production environment and should not be deployed as they are not secure (fuses and CSR's can be modified). Fuses hard blown on a chip must be stored in a database so that the various encryption keys can be used in future firmware updates. Index the database with the device tree chip identifier *CHIP-SERIAL* or *CHIP-UNIQUE-ID*.

Due to the hardening of trust associated with trusted boot, a number of setup options available during a non-trusted boot are hidden when trusted boot is used.

  • Chip Features - Runtime changes to the configuration
  • DRAM Options - Runtime changes to DRAM setup
  • QLM Options - Runtime changes to SERDES setup
  • Power Options - Runtime changes to power setup
  • Save Settings and Exit - Since no changes are possible, saving settings is disabled

After permanently blowing the fuses, Cavium recommends the OEM remove access to the diagnostics menu which will remove access to both the field fuses and the configuration and status registers. Diagnostics are not intended to be secure.

The BDK diagnostics application allows blowing of fuses by writing 64bits at a time and the fuse values for the ROT private key in bdk/trust-keys/hw-rot-private.pem will be shown by making the bdk target with a FUSES=1.

To build in support for diagnostics you must build the newport firmware-image target with ALLOW_DIAGNOSTICS=1.

Example:

  • build with diagnostics and show fuse values during make for SHA256 hash of the ROT public key (ROT private key is in bdk/trust-keys/hw-rot-private.pem and should not be shared)
    $ make -s -j8 firmwareimage FUSES=1 ALLOW_DIAGNOSTICS=1
    BDK_ROOT not set, assuming /usr/src/newport/bsp/bdk
    Root of Trust Public Key:
        Qx:            23b6f9ebf3e712b1061b43323b321113711e2a1d6a4277328243c8eaa4476584
        Qy:            b729fd87c510daf2225028a6e4d9982c319d6188083ccb1489ae8cf53a471883
        CSIB ROTPK:    846547a4eac843823277426a1d2a1e711311323b32431b06b112e7f3ebf9b6238318473af58cae8914cb3c0888619d312c98d9e4a6285022f2da10c587fd29b7
        FUSF_ROTPK[0]: 0xaba31863b14a9edf
        FUSF_ROTPK[1]: 0x43176c0377a1d485
        FUSF_ROTPK[2]: 0x9b816ad453a0d964
        FUSF_ROTPK[3]: 0xbe91fda1f893a251
    Field Fuses:
        0x3ff:0x300 (ROTPK SHA256) be91fda1f893a2519b816ad453a0d96443176c0377a1d485aba31863b14a9edf
    
  • use diagnostics to program ROTPK:
    Gateworks Newport SPL (53bc52b-dirty Tue Apr 3 20:30:17 UTC 2018)
    
    GSC     : v51 0xa7d8 WDT:disabled WDT_RESET board temp:57C
    RTC     : 1859
    Model   : GW6300-B
    MFGDate : 03-23-2018
    Serial  : 757535
    DTB     : gw6300.dtb
    
    Press 'B' within 2 seconds for boot menu
    
    =================================
    Boot Options
    =================================
    N) Boot Normally
    S) Enter Setup
    D) Enter Diagnostics
    W) Burn boot flash using Xmodem
    U) Change baud rate and flow control
    R) Reboot
    
    Choice: D
    
    SoC     : CN8020-850BG676-SCP-P12-G 1024KB 850/350MHz 0xa2 Pass 1.2
    MMC0    : eMMC
    MMC1    : not detected
    Boot    : eMMC non-trusted
    DRAM    : 1024 MB, 1333 MT/s, DDR4 UDIMM
    J9      : DISABLED
    J10     : DISABLED
    J11     : DISABLED
    QLM0    : DISABLED@5000MHz
    QLM1    : SGMII_1X1@1250MHz
    QLM2    : DISABLED@5000MHz
    QLM3    : DISABLED@5000MHz
    Serial  : 2x RS232 without flow control
    MDIO0   : DP83867 (RGMII)
    MDIO1   : DP83867 (SGMII)
    temp    : 50.8C
    vdd_vin : 16.115V
    vdd_bat : 65.535V
    vdd_5p0 : 5.042V
    vdd_3p3 : 3.328V
    vdd_2p5 : 2.484V
    vdd_core: 0.874V
    vdd_0p9 : 0.897V
    vdd_1p0 : 1.007V
    vdd_1p2 : 1.189V
    vdd_1p5 : 1.505V
    vdd_1p8 : 1.811V
    vdd_an1 : 0.787V
    vdd_an2 : 0.601V
    vdd_gsc : 2.954V
    Lua 5.2.0  Copyright (C) 1994-2011 Lua.org, PUC-Rio
    
    Cavium Diagnostics
    Copyright (C) 2010-2017 Cavium Inc.
    BDK Version: 53bc52b-dirty Tue Apr 3 20:30:17 UTC 2018
    
    
    =================================
    Main Menu
    =================================
     1) Display current configuration
     2) SERDES configuration
     3) File options
     4) DDR options
     5) PCIe options
     6) TWSI options
     7) SMI/MDIO options
     8) SPI/MPI options
     9) eMMC/SD options
    10) SATA options
    11) GPIO options
    12) SGPIO options
    13) USB options
    14) Interactive Lua prompt
    15) Traffic Generator
    16) Power Burn options
    17) VSC7224 options
    18) aqr-107 phy support
    19) PBUS options
    20) Trusted Boot options
    21) Reboot
    (INS)Menu choice []: 20
    
    =================================
    Trusted Boot Menu
    =================================
     1) Display SHA256 of the Root-of-Trust Public Key (ROTK)
     2) Display Secret Symmetric Key (SSK)
     3) Display Hardware Unique Key (HUK)
     4) Display ECC Private Endorsement Key (EK)
     5) Display Software Fuses (SW)
     6) Display Control Fuses (CTL)
     7) Soft blow SHA256 of the Root-of-Trust Public Key (ROTK)
     8) Soft blow Secret Symmetric Key (SSK)
     9) Soft blow Hardware Unique Key (HUK)
    10) Soft blow ECC Private Endorsement Key (EK)
    11) Soft blow Software Fuses (SW)
    12) Soft blow Control Fuses (CTL)
    13) Hard blow fuses
    14) Main menu
    (INS)Menu choice []: 13
    
    =================================
    FUSF Fuse Blow Menu
    =================================
     1) Hard blow SHA256 of the Root-of-Trust Public Key (ROTK)
     2) Hard blow Secret Symmetric Key (SSK)
     3) Hard blow Hardware Unique Key (HUK)
     4) Hard blow ECC Private Endorsement Key (EK)
     5) Hard blow Software Fuses (SW)
     6) Hard blow Control Fuses (CTL)
     7) Main menu
    (INS)Menu choice []: 1
    (INS)FUSF_ROTK(0): 0xaba31863b14a9edf
    (INS)FUSF_ROTK(1): 0x43176c0377a1d485
    (INS)FUSF_ROTK(2): 0x9b816ad453a0d964
    (INS)FUSF_ROTK(3): 0xbe91fda1f893a251
    
    =================================
    FUSF Fuse Blow Menu
    =================================
     1) Hard blow SHA256 of the Root-of-Trust Public Key (ROTK)
     2) Hard blow Secret Symmetric Key (SSK)
     3) Hard blow Hardware Unique Key (HUK)
     4) Hard blow ECC Private Endorsement Key (EK)
     5) Hard blow Software Fuses (SW)
     6) Hard blow Control Fuses (CTL)
     7) Main menu
    (INS)Menu choice []:
    

Repairing flash

If the OEM configures the system to allow 'flash jump' it is possible to repair the flash in a deployed system with trusted-mode boot enabled providing there is a bootable mechanism in the untrusted-boot firmware to recover the board.

Start of Trust, the Secure ROM and Fuses

Secure on chip ROM starts executing without any off chip IOs enabled. This creates the base anchor for the chain of trust. The ROM code loads and verifies TBL1FW from flash. TBL1FW must be signed with the public key who's hash is stored in the FUSF_ROTPKX fuses.

Secure ROM authenticates the ROT public key by computing the SHA256 and comparing it with the FUSF_ROTPK fuses. Once the SHA256 matches, the first link of the chain of trust becomes the ROT public key.

BDK Keys

The BDK uses two public/private key pairs for verification of the chain of trust. THe first public/private key pair is the Root Of Trust (ROT) and the second is the BDK signing key. These are stored in bdk/trust-keys/:

  • hw-rot-private.pem - Root of Trust (ROT) key intended to be blown into the fuses. This is controlled by the OEM.
  • bdk-sign-private.pem - BDK signing key used to sign various components used by the BDK. This is in a certificate-like format and its signature is verified using the ROTPK.

The following files are signed by the Root of Trust private key:

  • TBL1FW - trusted boot stub
  • bdk-sign.pub

The following files are signed by the BDK signing private key:

  • Apps such as init.bin, setup.bin, diagnostics.bin etc
  • Device tree files
  • ATF BL1

The following are not signed:

  • NTBL1FW - non trusted boot stub

Encryption

Trusted firmware can optionally be encrypted with an AES128 key. This prevents attackers from extracting the firmware code from flash for analysis. Two options are supported:

  • Secret Symmetric Key (SSK)
  • Binding Secret Symetcric Key (BSSK)

Secret Symmetric Key (SSK) Encryption

SSK is normally programmed the same across an entire product line, making the firmware flash images identical across the product. Encrypt BDK builds with a SSK by setting the make variable *SSK* to the encryption key. The key must be 32 hex digits.

make -s -j8 firmware-image SSK=0123456789abcdef0123456789abcdef

Binding Secret Symmetric Key (BSSK) Encryption

The Hardware Unique Key (HUK) is normally programmed differently for every chip, preventing cloning. Encrypt BDK builds with a BSSK by setting the make variable *HUK* to the encryption key. The key must be 32 hex digits. If both HUK and SSK are specified, the files are encrypted with BSSK and the SSK is unused.

make -s -j8 firmware-image HUK=0123456789abcdef0123456789abcdef

Encryption Performed During Packing

AES128 encryption is done by *fatfs_tool* with the "-e" option. As each file is copied by fatfs_tool, it is encrypted before being written into bdk/target-bin/bdk.bin. The "-e" option is automatically added by the BDK make system when you specify a SSK or HUK.

The encrypted files can be accessed on the build host by using the fatfs_tool extract command. After extracting the file, you can manually decrypt it using OpenSSL.

fatfs-tool -i bdk/target-bin/bdk.bin extract init.bin .
openssl enc -d -aes-128-cbc -in init.bin -out init-decrypt.bin \
        -K $(SSK/BSSK) -iv 00000000000000000000000000000000

DRAM Scrambling

The device tree parameter *DDR-CONFIG-SCRAMBLE* controls DRAM scrambling to prevent snooping. Systems using SSK or BSSK encryption should normally use DRAM scrambling to prevent attackers from extracting secrets from DRAM. The value of DDR-CONFIG-SCRAMBLE can be:

  • 0: No scrambling
  • 1: Always scramble
  • 2: Scramble only when using trusted boot. This is the default

Protection Against Rollback

To prevent rollback of firmware updates, the BDK implements a secure non-volatile counter in FUSF. The fuses FUSF_CTL[ROM_T_CNT] implement 32 possible NV counter values.

Using the Non-volatile Anti-rollback Counter

The BDK normally use a non-volatile counter value of zero. This can be changed through the make variable NV_COUNT.

make -s -j8 firmware-image NV_COUNT=1

For safety, the BDK defaults to soft blow of FUSF_CTL[ROM_T_CNT]. This is fine for development, but not suitable for production. Production builds should change the define BDK_TRUST_HARD_BLOW_NV to 1 inside bdk/libbdk-trust/bdk-trust.c.

/* The define BDK_TRUST_HARD_BLOW_NV controls whether the BDK will
   hard blow the secure NV counter on boot. This is needed for a
   production system, but can be dangerous in a development
   environment. The default value of 0 is to prevent bricking of
   chips due to CSIB[NVCOUNT] mistakes. BDK_TRUST_HARD_BLOW_NV must
   be changed to a 1 for production. The code below will display a
   warning if BDK_TRUST_HARD_BLOW_NV=0 in a trusted boot to remind
   you */
#define BDK_TRUST_HARD_BLOW_NV 1

IMPORTANT: Always set *BDK_TRUST_HARD_BLOW_NV=1* for releases.*

Device Tree Parameters for Trusted Boot

The following device tree items are added to the BDK device tree as part of trusted boot.

  • TRUST-CSIB:: Contains the 256 byte ROM_CSIB_S read from flash signing

the initial TBL1FW boot stage.

  • TRUST-ROT-ADDR:: Physical address of the Root of Trust Public Key in

secure memory. This address is normally an IO address referencing secure key memory.

  • TRUST-BSSK-ADDR:: Physical address of the BSSK in secure memory. This

address is normally an IO address referencing secure key memory.

File Format Details

This section describes exact low level formats of file related to trusted boot.

Root of Trust (ROT) Private Key

The root of trust private key is PEM encoded ASN.1. It contains a Elliptic Curve private key of 256 bits, for curve prime256v1. The key is stored in bdk/trust-keys/hw-rot-private.pem.

cat bdk/trust-keys/hw-rot-private.pem
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMDFxto5wfnfWmT8WuQSNrxy2jew1LTIPdzpYIw/xoDRoAoGCCqGSM49
AwEHoUQDQgAEW9sG+aI4sLebr9+tLkP5LBFJhLLQ5oSOZG3x96bqPcclUCClvwLK
dMmq5Unq5uTc7nrc6v4ok2IMQSWwCM8DcA==
-----END EC PRIVATE KEY-----

The openssl command to generate a key in this format is:

openssl ecparam -name prime256v1 -genkey -noout -out hw-rot-private.pem

The BDK make system will generate a new ROT key if hw-rot-private.pem doesn't exist.

BDK Signing Private Key

The BDK signing private key is PEM encoded ASN.1. It contains a Elliptic Curve private key of 256 bits, for curve prime256v1. The key is stored in bdk/trust-keys/bdk-sign-private.pem.

cat bdk/trust-keys/bdk-sign-private.pem
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILGdcgUnEgMAGOPrt3YaVxIHeS0yhcwaOFyczx6qaW/roAoGCCqGSM49
AwEHoUQDQgAEKKEp5y2dIWo4z87p1WCaIsYy9VfTMv1KKZi8x/dpX3w9mxLgNTHt
ZBrwH93xAr7l/vLmeYnJGyt3rIXWXLS5dQ==
-----END EC PRIVATE KEY-----

The openssl command to generate a key in this format is:

openssl ecparam -name prime256v1 -genkey -noout -out bdk-sign-private.pem

The BDK make system will generate a new BDK signing key if bdk-sign-private.pem doesn't exist.

BDK Signing Public Key

The BDK Signing Public Key is present inside the private key file on the host build system. For use on the target system, the public is repackaged into a certificate like format without the private key. The public key is stored in bdk/trust-keys/bdk-sign.pub. The format of this file is:

  • 56 bytes of random data
  • 8 byte NV counter in little endian format
  • 32 bytes of EC public key pair R in little endian format
  • 32 bytes of EC public key pair S in little endian format

The BDK signing public key is signed by the ROT private key, creating bdk/trust-keys/bdk-sign.pub.sign.

Signature of file signed by BDK Signing Private Key (*.sign files)

The signature of a file is stored in an independent file with the same name, except ".sign" appended. The file is a ASN.1 encoded point on the EC curve padded to a multiple of 16 bytes, the AES key size.

openssl dgst -sha256 -binary -sign bdk-sign-private.pem -out FILE.sign FILE
bdk/bin/bdk-aes-pad FILE.sign

Example Decoded signature

dumpasn1 bdk/trust-keys/bdk-sign.pub.sign
  0  69: SEQUENCE {
  2  32:   INTEGER
       :     28 29 6F F1 60 D2 7A 34 BC 5C A9 06 51 EF 2C F2
       :     AF 68 FB 14 F0 C5 F9 E3 C1 85 34 79 89 1C 3B 6F
 36  33:   INTEGER
       :     00 AF 87 03 25 71 F1 EA C1 58 B5 C1 35 DB B3 1D
       :     33 5D 76 B5 C8 98 13 9E 59 98 1D 53 8E 00 2A 25
       :     1E
       :   }

LZMA Compressed Images

LZMA compressed images (*.bin.lzma) follow the LZMA standard, except for requiring the uncompressed size to be correct in the header.

LZMA header format:

  • 1 byte of Properties
  • 4 bytes encoding Dictionary Size, little endian
  • 8 bytes of uncompressed size, little endian

The BDK takes the LZMA compressed file and pads it to a multiple of 16 bytes, the AES key size.

bdk/bin/lzma lzma e FILE FILE.lzma
bdk/bin/bdk-aes-pad FILE.lzma
openssl dgst -sha256 -binary -sign bdk/trust-keys/bdk-sign-private.pem \
        -out FILE.lzma.sign FILE.lzma
bdk/bin/bdk-aes-pad FILE.lzma.sign

IMPORTANT: ARM Trusted Firmware boot level 1, bl1.bin, is expected to be copied to bdk/target-bin/bl1.bin before the BDK is built. The Newport firmware-image Makefile will compress and sign bl1.bin and include it into the FAT12 filesystem. If bl1.bin is not copied, the file will not be present in the firmware image, causing ATF to fail trusted boot.

Uncompressed Images

Uncompressed image files (*.bin) contain a 256 byte header followed by executable code. The image files are padded multiple of 16 bytes, the AES key size.

bdk/bin/bdk-aes-pad FILE.bin

Device Tree Files

Device tree source files stored in bdk/boards/ are automatically compiled and signed for inclusion into the target binary. The following steps are automatically performed by the BDK make system.

dtc -I dts -O dtb -o FILE.dtb FILE.dts
bdk/bin/bdk-aes-pad FILE.dtb
openssl dgst -sha256 -binary -sign bdk/trust-keys/bdk-sign-private.pem \
        -out FILE.dtb.sign FILE.dtb
bdk/bin/bdk-aes-pad FILE.dtb.sign

Trusted Boot Sequence

Note that once Trusted Boot has been enabled by blowing FUSF_CTL bits, JTAG programability is disabled and boards can no longer be RMA'd to Gateworks (as they can not be re-programmed or tested via JTAG).

Trusted Boot Sequence:

  1. Chip strapping, or FUSF_CTL[tz_force2] enables trusted boot
  2. Chip exits reset, begins executing the secure ROM
  3. Secure ROM load CLIB, CSIB, TBL1FW, and NTBL1FW from flash
  4. Secure ROM calculates the SHA256 of CSIB[rotpk0..rotpk7]
  5. If the SHA256 matches FUSF_ROTPK(0..3) then trusted boot continues
  6. Secure ROM calculates the SHA256 of CSIB
  7. The EC signature in CLIB[csib_sign0..csib_sign7] is checked against the SHA256 of CSIB, verifying the trust of CSIB
  8. If CSIB[crypt] specifies, the TBL1FW is AES decrypted
    • CSIB[crypt]=1, then AES key is SSK = FUSF_SSK(0..1)
    • CSIB[crypt]=2, then AES key is BSSK = AES128(FUSF_HUK(0..1), CSIB[fs0..fs1])
  9. Secure ROM calculates the SHA256 of TBL1FW
  10. If the SHA256 matches CSIB[fs0..fs3] then trusted boot continues
  11. TBL1FW takes control, which is bdk/apps/boot/boot.bin
  12. TBL1FW Loads bdk-sign.pub and bdk-sign.pub.sign from flash
  13. If bdk-sign.pub authenticates against bdk-sign.pub.sign, the current chain for trust key changes from ROT to the BDK signing key.
  14. TBL1FW Loads the manufacturing data from flash. This data is not authenticated
  15. TBL1FW Loads <BOARD>.dtb and <BOARD>.dtb.sign from flash. The exact name of the device tree file loaded is based on the manufacturing data. Details are documented in BDK_Config-X.Y.pdf.
  16. If <BOARD>.dtb authenticates against<BOARD>.dtb.sign, the BDK configuration is updated.
  17. TBL1FW Loads init.bin and init.bin.sign from flash
  18. If init.bin authenticates against init.bin.sign, booting continues. If it fails, the boot menu is shown.
  19. Init.bin takes control, which is bdk/apps/init/init.bin. Current chain of trust key reverts to ROT
  20. Init.bin receives the current BDK config from TBL1FW in a device tree located in cache
  21. Init.bin receives the CSIB, ROT public key address, and BSSK address in a device tree located in cache
  22. Init.bin Loads bdk-sign.pub and bdk-sign.pub.sign from flash
  23. If bdk-sign.pub authenticates against bdk-sign.pub.sign, the current chain for trust key changes from ROT to the BDK signing key.
  24. Init.bin initializes the hardware
  25. If the BDK config specifies DRAM scrambling, init.bin enables scrambling
  26. Init.bin Loads <BOARD>-linux.dtb and <BOARD>-linux.dtb.sign from flash. The exact name of the device tree file loaded is based on the manufacturing data. Details are documented in BDK_Config-X.Y.pdf.
  27. If <BOARD>-linux.dtb authenticates against <BOARD>-linux.dtb.sign, the in memory device tree is updated.
  28. Init.bin Loads bl1.bin and bl1.bin.sign from flash
  29. If bl1.bin authenticates against bl1.bin.sign, booting continues to ATF. If it fails, diagnostics.bin.lzma and diagnostics.bin.lzma.sign are tried.
Last modified 3 months ago Last modified on 04/18/2018 09:41:23 AM