Changes between Version 5 and Version 6 of newport/secure_boot


Ignore:
Timestamp:
09/04/2024 11:08:23 PM (2 weeks ago)
Author:
Tim Harvey
Comment:

refactored the FIT section and OTP section

Legend:

Unmodified
Added
Removed
Modified
  • newport/secure_boot

    v5 v6  
    3737openssl ecparam -name prime256v1 -genkey -noout -out bdk/trust-keys/bdk-sign-private.pem
    3838}}}
     39
     40**
     41The hw-rot-private.pem and bdk-sign-private.pem files must be stored in a secure database preferably indexed by board serial number in case you even need to change them.
     42**
    3943
    4044To build a version of boot firmware in the Newport BSP directory using keys that you create and manage in the ~/keys directory:
     
    6266}}}
    6367
    64 **
    65 The hw-rot-private.pem and bdk-sign-private.pem files must be stored in a secure database preferably indexed by board serial number in case you even need to change them.
    66 **
    67 
    68 [=#dtb]
    69 == Adding signature node to DTB for booting signed FIT images
    70 To add the kernel, fdt, and ramdisk to the chain of trust you can use a signed fit image (see [wiki:secure_boot#fit]). This requires that the FDT controlling U-Boot have a signature node containing the key data used to verify the FIT image.
    71 
    72 To accomplish this you must alter your board dtb in the boot firmware FATFS using the method discussed in [wiki:secure_boot#fit].
    73 
    74 You can do this using the fatfs-tool which is built by the Newport BSP. For example, if your board is a GW6304 thus uses the gw6304-linux.dtb, your Newport BSP is in /usr/src/newport/bsp, and your FIT key is ~/keys/fit.key
    75 {{{#!bash
    76 # define vars used in commands below
    77 BSP_DIR=/usr/src/newport/bsp
    78 DTB=gw6304-linux.dtb
    79 KEY_DIR=~/keys
     68
     69[=#otp]
     70== Blowing Fuses to lock a device to use trusted boot
     71
     72**Important Note: Once boards have been configured for trusted-mode boot by hard blowing fuses the JTAG chain is disabled and boards 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.**
     73
     74In order to enable trusted boot you must:
     75 * program the ROTPK 256bit hash into OTP
     76 * enable the tz-force bit
     77 * enable the fj-dis bit if you want to disable a fallback to insecure boot firmware if secure boot fails
     78
     79The 256bit ROTPK that needs to be used for trusted boot can be found using the following in the Newport BSP directory:
     80{{{#!bash
     81./newport/getkey.py bdk/trust-keys/hw-rot-private.pem
     82}}}
     83
     84Before doing this permanently there is a way to 'soft' blow the fuses where you can perform a warm reset to verify everything boots as expected.
     85
     86Gateworks provides an [https://dev.gateworks.com/buildroot/newport/minimal/octeontxotp.c octeontxotp] application on its pre-built buildroot based minimal kernel+ramdisk that can be used for provisioning boards.
     87
     88To boot this on a Newport board download the kernel [https://dev.gateworks.com/buildroot/newport/minimal/Image Image] (which contains a ramdisk rootfs) and boot via something like:
     89{{{#!bash
     90tftpboot $kernel_addr_r 192.168.1.146:newport/Image.rescue && booti $kernel_addr_r - $fdtcontroladdr
     91}}}
     92
     93This program can be used to blow the fuses necessary to enable trusted boot:
     94 * soft blow (for testing)
     95{{{#!bash
     96octeontxotp --rotpk $ROTPK
     97octeontxotp --tz_force
     98octeontxotp --fj_dis
     99i2cset -f -y 0 0x20 0 0 # disable power-cycle on reset
     100octeontxotp --reset
     101}}}
     102  - replace $ROTPK above with the value output from './newport/getkey.py bdk/trust-keys/hw-rot-private.pem' in your BSP build directory
     103  - the i2cset command above disables a board power-cycle on CPU reset so that the soft fuses are used
     104
     105After the {{{octeontxotp --reset}}} you should see the following which indicates a clean and successful trusted boot:
     106{{{#!bash
     107WARNING:
     108WARNING: ********************************************************
     109WARNING: * Configured for soft blow of secure NV counter. This
     110WARNING: * build is not suitable for production trusted boot.
     111WARNING: ********************************************************
     112WARNING:
     113
     114
     115
     116Gateworks Newport SPL (12.7.0-7647df8 Wed Sep 4 20:36:41 UTC 2024)
     117
     118GSC     : v61 0xfa4b RST:VIN Thermal Protection Enabled at board temp of 96C
     119Temp    : Board:29C/96C CPU:56C/95C
     120Model   : GW6905-SP435-A2
     121MFGDate : 07-11-2024
     122Serial  : 448336
     123RTC     : 51
     124SoC     : CN8030-1500BG676-AUS-P12-G 1024KB 1500/550MHz 0xa2 Pass 1.2
     125MMC1    : not detected
     126MMC0    : eMMC   
     127Boot    : eMMC trusted, Secure Boot
     128DTB     : gw6404.dtb
     129DRAM    : 4096 MB, 2133 MT/s, DDR4 UDIMM
     130J9      : PCI
     131J10     : PCI (hwconfig options:PCI,SATA,USB2)
     132J11     : PCI
     133QLM0    : PCIE_X1@8000MHz J9
     134QLM1    : QSGMII@5000MHz
     135QLM2    : PCIE_X1@8000MHz J11
     136QLM3    : PCIE_X1@8000MHz J10
     137Serial  : 2x RS232 without flow control
     138MDIO0   : DP83867 (RGMII)
     139MDIO1   : VSC8574 (QSGMII)
     140temp    : 29.4C 
     141vdd_bat : 0.000V
     142fan_tach: 0 RPM 
     143vdd_vin : 17.070V
     144vdd_5p0 : 5.062V
     145vdd_3p3 : 3.348V
     146vdd_2p5 : 2.506V
     147vdd_core: 0.891V
     148vdd_0p9 : 0.902V
     149vdd_1p0 : 0.999V
     150vdd_1p2 : 1.193V
     151vdd_1p5 : 1.483V
     152vdd_an1 : 1.394V
     153vdd_gsc : 3.162V
     154NOTICE:  Booting Trusted Firmware
     155NOTICE:  BL1: v1.5(release):e1ffc601 (Marvell-12.1.0)
     156NOTICE:  BL1: Built : 20:36:52, Sep  4 2024
     157NOTICE:  CHIP UniqueID not set
     158NOTICE:  BL1: Booting BL2
     159NOTICE:  BL2: v1.5(release):e1ffc601 (Marvell-12.1.0)
     160NOTICE:  BL2: Built : 20:37:09, Sep  4 2024
     161NOTICE:  BL1: Booting BL31
     162NOTICE:  BL31: v1.5(release):e1ffc601 (Marvell-12.1.0)
     163NOTICE:  BL31: Built : 20:37:17, Sep  4 2024
     164
     165
     166U-Boot 2021.01-g4ba8e461cc (Sep 04 2024 - 20:37:51 +0000)
     167
     168Model: Gateworks Newport CN80XX GW6404
     169Board: GW6905-SP435-A2
     170DRAM:  4 GiB
     171WDT:   Started with servicing (60s timeout)
     172MMC:   octeontx-mmc0: 0
     173Loading Environment from MMC... OK
     174In:    serial@87e028000000
     175Out:   serial@87e028000000
     176Err:   serial@87e028000000
     177BGX0 QLM1 LMAC2 mode: QSGMII
     178BGX0 LMACs: 4
     179XCV_DLL_CTL: TX_BYP=0 RX_BYP=1
     180BGX2 LMAC0 mode: RGMII
     181BGX2 LMACs: 1
     182Net:   eth0: vnic0, eth1: vnic1, eth2: vnic2, eth3: vnic3, eth4: vnic4
     183Thermal protection:enabled at 96C
     184Hit any key to stop autoboot:  0
     185}}}
     186
     187If you use a $ROTPK value that differs from that which was used to build your image you will see no output from the UART as the board does not boot.
     188
     189After testing via soft blow above you can now hard blow the fuses (**this is permanent and you will no longer be able to JTAG program or RMA your board**). Repeat the boot to the rescue image and blow the fuses with:
     190{{{#!bash
     191octeontxotp --hard --force --rotpk $ROTPK
     192octeontxotp --hard --force --lock rotpk
     193octeontxotp --hard --force --tz_force
     194octeontxotp --hard --force --fj_dis
     195}}}
     196  - replace $ROTPK above with the value output from './newport/getkey.py bdk/trust-keys/hw-rot-private.pem' in your BSP build directory
     197
     198At this point you have trusted boot all the way to the bootloader and can follow-up with a signed FIT image.
     199
     200
     201[=#fit]
     202== Signed FIT Image (kernel and optional ramdisk)
     203To add the kernel and an optional ramdisk to the chain of trust you can use a signed FIT image (see [wiki:/secure_boot#fit]). This requires that the FDT controlling U-Boot have a signature node containing the key data used to verify the FIT image.
     204
     205For this you need the following:
     206 * A key for your FIT image
     207 * Add a signature node with the key details in the linux dtb used by U-Boot which resides in the FATFS
     208 * Create a FIT image with a kernel, optional ramdisk and optional configuration
     209
     210Example Procedure:
     211 1. Define some env variables used in commands below (altered for your needs):
     212{{{#!bash
     213DTB=gw6404-linux.dtb
     214KEY_DIR=$PWD/bdk/trust-keys/
    80215KEY_NAME=fit
    81 
    82 # get latest boot firmware
    83 wget http://dev.gateworks.com/newport/boot_firmware/firmware-newport.img
    84 
    85 # extract your DTB to current directory
    86 $BSP_DIR/bin/fatfs-tool -i firmware-newport.img extract /$DTB .
    87 
    88 # use mkimage to apply the key signature node
    89 cat << EOF > dummy.its
     216}}}
     217  - DTB should match the board linux DTB you are using
     218  - KEY_NAME - what you named your key (fit) above
     219  - KEY_DIR is where your key is
     220 1. Create the KEY:
     221{{{#!bash
     222# create key
     223openssl genpkey -algorithm RSA -out $KEY_DIR/$KEY_NAME.key -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537
     224# create cert for key
     225openssl req -batch -new -x509 -key $KEY_DIR/$KEY_NAME.key -out $KEY_DIR/$KEY_NAME.crt
     226}}}
     227  - you will want to save this away on a trusted source along with the keys used for secure boot above; note that a make clean will wipe any keys in bdk/trust-keys
     228 1. Alter the linux dtb (which U-Boot uses) in the boot firmware to add the signature node. This is done using the U-Boot mkimage tool then using the fatfs-tool tool to copy it into the embedded FATFS in the firmware image. Create an ITS template where each image is defined to have a has and each configuration is signed:
     229{{{#!bash
     230cat << EOF > fit.its
    90231/dts-v1/;
    91232
    92233/ {
    93         description = "Dummy file for signing board .dtb files";
     234        description = "Image for Linux Kernel";
    94235        #address-cells = <1>;
    95236
    96         /* dummy image just to keep mkimage tool happy */
    97237        images {
    98                 kernel@1 {
    99                         description = "dummy kernel image";
    100                         data = /incbin/("dummy.bin");
     238                kernel {
     239                        description = "Linux Kernel";
     240                        data = /incbin/("./linux/arch/arm64/boot/Image.gz");
    101241                        type = "kernel";
    102242                        arch = "arm64";
    103243                        os = "linux";
    104                         compression = "none";
    105                         load = <0x0>;
    106                         entry = <0x0>;
    107                         hash@1 {
     244                        compression = "gzip";
     245                        load =<0x48200000> ;
     246                        entry = <0x48200000>;
     247                        hash-1 {
    108248                                algo = "sha256";
    109249                        };
     
    111251        };
    112252        configurations {
    113                 default = "config@1";
    114                 config@1 {
     253                default = "config-1";
     254                config-1 {
    115255                        description = "Linux configuration";
    116                         kernel = "kernel@1";
    117                         signature@1 {
    118                                 algo = "sha256,rsa2048";
    119                                 key-name-hint = "dummy";
     256                        kernel = "kernel";
     257                        signature-1 {
     258                                algo = "sha1,rsa2048";
     259                                key-name-hint = "$KEY_NAME";
     260                                sign-images = "kernel";
    120261                        };
    121262                };
     
    123264};
    124265EOF
    125 touch dummy.bin
    126 # replace dummy placeholders for key-name
    127 sed -i "s;key-name-hint = \"dummy\";key-name-hint = \"$KEY_NAME\";g" dummy.its
    128 # create cert for key
    129 openssl req -batch -new -x509 -key $KEY_DIR/$KEY_NAME.key -out $KEY_DIR/$KEY_NAME.crt
    130 # add signature node to myboard.dtb
    131 $BSP_DIR/bin/mkimage -r -k $KEY_DIR -K $DTB -f dummy.its dummy.itb
     266
     267# add signature node to your dtb using mkimage
     268cp dts/$DTB .
     269mkimage -r -k $KEY_DIR -K $DTB -f fit.its fit.itb
    132270
    133271# pad and sign the dtb
    134 BDK_ROOT=$BSP_DIR/bdk $BSP_DIR/bdk/bin/bdk-aes-pad $DTB
    135 BDK_ROOT=$BSP_DIR/bdk $BSP_DIR/bdk/bin/bdk-sign bdk-sign-private $DTB.sign $DTB
     272./bdk/bin/bdk-aes-pad $DTB
     273BDK_ROOT=$PWD/bdk ./bdk/bin/bdk-sign bdk-sign-private ./$DTB.sign ./$DTB
    136274
    137275# copy the new dtb and its signature into the FATFS
    138 $BSP_DIR/bin/fatfs-tool -i firmware-newport.img cp $DTB $DTB.sign /
    139 }}}
    140 
    141 
    142 [=#otp]
    143 == Blowing Fuses to lock a device to use trusted boot
    144 
    145 **Important Note: Once boards have been configured for trusted-mode boot by hard blowing fuses the JTAG chain is disabled and boards 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.**
    146 
    147 In order to enable trusted boot you must:
    148  * program the ROTPK 256bit hash into OTP
    149  * enable the tz-force bit
    150  * enable the fj-dis bit if you want to disable a fallback to insecure boot firmware if secure boot fails
    151 
    152 The 256bit ROTPK that needs to be used for trusted boot can be found using the following in the Newport BSP directory:
    153 {{{#!bash
    154 ./newport/getkey.py bdk/trust-keys/hw-rot-private.pem
    155 }}}
    156 
    157 Before doing this permanently there is a way to 'soft' blow the fuses where you can perform a warm reset to verify everything boots as expected.
    158 
    159 Gateworks provides an octeontxotp application on its pre-built buildroot based minimal kernel+ramdisk that can be used for provisioning boards. This program can be used to blow the fuses necessary to enable trusted boot:
    160  * soft blow (for testing)
    161 {{{#!bash
    162 octeontxotp --rotpk $ROTPK
    163 octeontxotp --tz_force
    164 octeontxotp --fj_dis
    165 i2cset -f -y 0 0x20 0 0 # disable power-cycle on reset
    166 octeontxotp --reset
    167 }}}
    168  * hard blow (after testing via soft blow) **this is permanent and you will no longer be able to JTAG program or RMA your board**)
    169 {{{#!bash
    170 octeontxotp --hard --force --rotpk $ROTPK
    171 octeontxotp --hard --force --lock rotpk
    172 octeontxotp --hard --force --tz_force
    173 octeontxotp --hard --force --fj_dis
    174 }}}
     276fatfs-tool -i firmware-newport.img cp ./$DTB ./$DTB.sign /
     277
     278# copy the FIT image into the FATFS
     279fatfs-tool -i firmware-newport.img cp fit.itb /
     280
     281# create a JTAG binary image
     282./mkimage_jtag --soc cn803x --emmc -s --partconf=user firmware-newport.img@user:erase_part:0-32768 > firmware-newport.bin
     283}}}
     284  - Note placing the FIT image containing the kernel in the FATFS is just one option. You may want to put it someplace dedicated in FLASH due to size or other prefrences.
     285
     286Now you can JTAG program the updated firmware-newport.bin and boot it via:
     287 1. verify the signature node is in the controlling dtb
     288{{{#!bash
     289GW6905-SP435-A2> fdt addr $fdtcontroladdr && fdt print /signature
     290signature {
     291    key-fit {
     292        required = "conf";
     293        algo = "sha256,rsa2048";
     294        rsa,r-squared = <0xaf3ca3f0 0x73f28178 0x88f0aee0 0xaa2d9d2d 0xb1f4a926 0xfb94185f 0xf006b370 0xfe24b6f3 0x0f93dc67 0x49638257 0x33d2b04e 0xcf70c6b4 0x3abfda78 0xdbe6a1d7 0xd2a119fa 0x6e2efea8 0x359492a2 0x634dd1bf 0x5e3f1248 0x135cc54a 0x8b92f034 0xdf4b3525 0x99668d2b 0xd1b5c5cf 0xeb5a84a6 0x958edc0f 0x37bca5ee 0xb64b4b56 0x28c7b114 0x2771edde 0xd87b1b68 0x1b2c22d9 0xd44242d9 0xa3f5749d 0xa3ca7b86 0xe31923d7 0x6cf1d2c9 0x685a79f5 0x27576cea 0xa33a4be0 0x3ce85721 0xb8a1b9a1 0xe54acf5b 0x098d2201 0x0b768b19 0x9be17c61 0xb5540e51 0xe9f89f54 0xc6d69841 0x7a4a79f2 0xf9e10893 0x992f120d 0xeb874b8e 0xa1017e7c 0x5f60874a 0xf78d9b6a 0xc6b8b64f 0x4fcad653 0xdaa9f618 0x1ff8e9fc 0x5ee19772 0x5c3c66f0 0x5a006dec 0xddc182ff>;
     295a6d 0x5a4e6f90 0xe31b9d42 0xcefa7d1f 0x6b757a25 0xcafe13b5 0x3b0eb7ff 0xfc281541 0xd8765ac3 0x5f19110a 0x381aac24 0xaa69c335 0x3aaddfe1 0x48bc4576 0x7c725b55 0x3a006181 0x4439a5d6 0x6a6523f2 0xeff42f8f 0x9f927be6 0xbc88d703 0xd264bc4c 0x1be6fad9 0x24e157e8 0x365f4765 0x7c63c31d 0xac83d338 0x0da0eedb 0xa2102d3a 0xf826be86 0xcd6d5e02 0x6bacb3f3 0xb82f7982 0x8fedc29e 0x81764654 0x6c4a8ce0 0x5d8bfdda 0xcb2b3973 0x8247809e 0x9abdbdd1 0x98155cc1 0x1ac51a84 0xcd6e87b2 0xf1a656e4 0x68b3cc9f 0x655ba517 0x9f6841dd 0x48de6550 0x5869179a 0x84e68b6d 0xeabd5b4c 0x146448ec 0x37d11af4 0x8e715f05>;
     296        rsa,exponent = <0x00000000 0x00010001>;
     297        rsa,n0-inverse = <0xde6a6a33>;
     298        rsa,num-bits = <0x00000800>;
     299        key-name-hint = "fit";
     300    };
     301};
     302}}}
     303 1. Boot the FIT image
     304{{{#!bash
     305# boot FIT image
     306setenv bootargs "root=/dev/mmcblk0p2 rootwait rw"
     307load mmc 0:1 $loadaddr fit.itb && bootm $loadaddr - $fdtcontroladdr
     308}}}
     309
     310Note that Newport's U-Boot already has the things defined necessary for signed FIT images (CONFIG_FIT_SIGNATURE, CONFIG_RSA, CONFIG_LEGACY_IMAGE_FORMAT)
     311
     312You can continue the process of securing your firmware image by locking down U-Boot's environment and using a ramdisk to mount an encrypted filesystem. For detailed examples of that see [wiki:/venice/secure_boot venice/secure_boot]