Changes between Version 19 and Version 20 of venice/secure_boot


Ignore:
Timestamp:
04/01/2024 07:59:27 PM (8 months ago)
Author:
Samuel Lee
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • venice/secure_boot

    v19 v20  
    7777  b. Unpack the CST :
    7878{{{#!bash
    79 tar xvf cst-3.3.2.tgz
    80 cd cst-3.3.2/keys
     79tar xvf cst-3.4.0.tgz
     80cd cst-3.4.0/keys
    8181}}}
    8282  c. Create a text file named "serial", which contains 8 digits. OpenSSL uses the contents of this file for the 'certificate serial numbers'.
     
    227227 - https://elixir.bootlin.com/u-boot/latest/source/doc/imx/habv4/introduction_habv4.txt
    228228 - https://elixir.bootlin.com/u-boot/latest/source/doc/imx/habv4/guides/mx8m_spl_secure_boot.txt
     229
     230== HABv4 encrypted boot architecture
     231The IMX HABv4 also provides an extra optional security operation by using cryptography (AES-CCM) to obscure the boot image so it can not be seen or used by unauthorized users.
     232
     233Encrypted boot adds an extra layer of security to the boot sequence using cryptographic techniques to obscure the bootloader data (which can be extended to the entire firmware image)so that it can not be seen or used by unauthorized users. This mechanism protects and conceals the bootloader code residing in flash.
     234
     235The Data Encryption Key (DEK) is an AES key used to encrypt the boot image (via the Code Signing Tool) and decrypt the boot image (using the DEK blob appended to the image). The DEK blob is used as a security layer to wrap and store the DEK off-chip which is unique to the chip that generated the blob.
     236
     237Generation of the DEK blob that gets appended to your image must be done on the IMX via the U-Boot dek_blob command which is enabled with CONFIG_CMD_DEKBLOB=y.
     238
     239References:
     240 - https://elixir.bootlin.com/u-boot/latest/source/doc/imx/habv4/introduction_habv4.txt
     241 - https://elixir.bootlin.com/u-boot/v2021.07/source/doc/imx/habv4/guides/encrypted_boot.txt
     242 - NXP AN12056 - Encrypted Boot on HABv4 and CAAM Enabled devices
    229243
    230244
     
    444458
    445459The init script we will use can be created like this:
     460* '''''You need to set SERVERIP variable to your tftp IP address'''''
    446461{{{#!bash
    447462cat <<\EOF> init
     
    456471
    457472# Some basic vars
    458 DEV=/dev/mmcblk2 # storage device to be used for the encrypted file system
     473DEVICE=mmcblk2 # storage device to be used for the encrypted file system
     474DEV=/dev/$DEVICE
    459475P1_OFFSETMB=64
    460476PART=p1
     
    463479NIC=eth0
    464480INIT=/sbin/init # init of final OS
     481SERVERIP=<YOUR_SERVER_IP> # serverip for tftp server
     482# Boot firmware support
     483BOOT_FIRMWARE=http://$SERVERIP/tftpboot/venice/flash.bin
     484FIT_IMAGE=http://$SERVERIP/tftpboot/venice/fit.itb
     485# TPM support
     486KEY_HANDLE=0x81234567 #TPM2 Owner Persistent Handle Range: 0x81000000 - 0x81800000
    465487
    466488# Mount things needed by this script
     
    470492mount -n -t tmpfs tmpfs /run
    471493
     494# Check if "tpm" is present in bootargs
     495for arg in $(cat /proc/cmdline); do
     496        [ "$arg" == "tpm" ] && {
     497                insmod /virt-dma.ko
     498                insmod /imx-sdma.ko
     499                insmod /spi-imx.ko
     500                insmod /tpm_tis_spi.ko
     501                [ -c /dev/tpm0 ] && {
     502                        TPM=/dev/tpm0
     503                        echo "Using TPM: $TPM"
     504                }
     505        }
     506done
     507
    472508error() {
    473         printf "\n\nErro: $@"
    474         while [ 1 ]; do sleep 1; done
     509        printf "\n\nErro: $@"
     510        while [ 1 ]; do sleep 1; done
    475511}
    476512
    477513user_data() {
    478         echo "Applying user changes..."
    479 
    480         # in any board specific changes to rootfs
    481         case "$(cat /proc/device-tree/board)" in
    482                 GW74*)
    483                         mkdir -p /mnt/etc/udev/rules.d
    484                         echo 'SUBSYSTEM=="net", ACTION=="add", DEVPATH=="/devices/platform/soc@0/30800000.bus/30bf0000.ethernet/net/eth*", NAME="en0"' > /mnt/etc/udev/rules.d/70-persistent-net.rules
    485                         echo 'SUBSYSTEM=="net", ACTION=="add", DEVPATH=="/devices/platform/soc@0/30800000.bus/30be0000.ethernet/net/eth*", NAME="en1"' >> /mnt/etc/udev/rules.d/70-persistent-net.rules
    486                         sed -i 's/eth0/en0/' /mnt/etc/network/interfaces
    487                         ;;
    488         esac
     514        echo "Applying user changes..."
     515
     516        # in any board specific changes to rootfs
     517        case "$(cat /proc/device-tree/board)" in
     518                GW74*)
     519                        mkdir -p /mnt/etc/udev/rules.d
     520                        echo 'SUBSYSTEM=="net", ACTION=="add", DEVPATH=="/devices/platform/soc@0/30800000.bus/30bf0000.ethernet/net/eth*", NAME="en0"' > /mnt/etc/udev/rules.d/70-persistent-net.rules
     521                        echo 'SUBSYSTEM=="net", ACTION=="add", DEVPATH=="/devices/platform/soc@0/30800000.bus/30be0000.ethernet/net/eth*", NAME="en1"' >> /mnt/etc/udev/rules.d/70-persistent-net.rules
     522                        sed -i 's/eth0/en0/' /mnt/etc/network/interfaces
     523                        ;;
     524        esac
    489525}
    490526
     
    492528#  - gateworks ubuntu tarbarll and linux kernel tarball
    493529ROOTFS_TARS="\
    494         https://dev.gateworks.com/ubuntu/jammy/jammy-venice.tar.xz \
    495         https://dev.gateworks.com/venice/kernel/linux-venice-6.6.8.tar.xz \
     530        https://dev.gateworks.com/ubuntu/jammy/jammy-venice.tar.xz \
     531        https://dev.gateworks.com/venice/kernel/linux-venice-6.6.8.tar.xz \
    496532"
    497533rootfs1() {
    498         # Create an ext4 file system on the opened LUKS device
    499         echo "Creating filesystem..."
    500         mkfs.ext4 -q -F -L rootfs /dev/mapper/$NAME || error "mkfs.ext4 failed"
    501 
    502         # Mount the LUKS device to /mnt
    503         mount /dev/mapper/$NAME /mnt || error "mount failed"
    504 
    505         for url in $ROOTFS_TARS; do
    506                 echo "Downloading $url..."
    507                 wget -q --show-progress --no-check-certificate -O data $url || error "wget failed"
    508                 echo "Extracting..."
    509                 pv data | tar -C /mnt -mxJ --keep-directory-symlink || error "tar extract failed"
    510         done
    511 
    512         user_data
    513 
    514         # Unmount the LUKS device
    515         echo "Unmounting LUKS device..."
    516         umount /dev/mapper/$NAME || error "umount failed"
     534        # Create an ext4 file system on the opened LUKS device
     535        echo "Creating filesystem..."
     536        mkfs.ext4 -q -F -L rootfs /dev/mapper/$NAME || error "mkfs.ext4 failed"
     537
     538        # Mount the LUKS device to /mnt
     539        mount /dev/mapper/$NAME /mnt || error "mount failed"
     540
     541        for url in $ROOTFS_TARS; do
     542                echo "Downloading $url..."
     543                wget -q --show-progress --no-check-certificate -O data $url || error "wget failed"
     544                echo "Extracting..."
     545                pv data | tar -C /mnt -mxJ --keep-directory-symlink || error "tar extract failed"
     546        done
     547
     548        user_data
     549
     550        # Unmount the LUKS device
     551        echo "Unmounting LUKS device..."
     552        umount /dev/mapper/$NAME || error "umount failed"
    517553}
    518554
    519555# example2: rootfs via compressed disk image
    520556rootfs2() {
    521         FILESYSTEM=https://dev.gateworks.com/venice/images/jammy-venice.img.gz
    522         # a compressed disk image contains a partition table as well as
    523         # partitions. Here we assume an MBR partition with the OS on P1.
    524         # we will extract the MBR, determine the start/end of P1 and copy
    525         # it to the LUKS device.
    526         echo "Downloading $FILESYSTEM..."
    527         wget -q --show-progress --no-check-certificate -O data $FILESYSTEM || exit 1
    528         # Extract the MBR
    529         zcat data | dd of=mbr count=1
    530         start=$(sfdisk -l mbr | tail -1 | tr -s ' ' | cut -d ' ' -f3)
    531         end=$(sfdisk -l mbr | tail -1 | tr -s ' ' | cut -d ' ' -f4)
    532         # copy the filesystem in P1 to the LUKS device
    533         echo "Copying..."
    534         pv data | zcat | dd of=/dev/mapper/$NAME skip=$start count=$((end-start))
    535 
    536         # apply user data
    537         mount /dev/mapper/$NAME /mnt || error "mount failed"
    538         user_data
    539         umount /dev/mapper/$NAME || error "umount failed"
     557        FILESYSTEM=https://dev.gateworks.com/venice/images/jammy-venice.img.gz
     558        # a compressed disk image contains a partition table as well as
     559        # partitions. Here we assume an MBR partition with the OS on P1.
     560        # we will extract the MBR, determine the start/end of P1 and copy
     561        # it to the LUKS device.
     562        echo "Downloading $FILESYSTEM..."
     563        wget -q --show-progress --no-check-certificate -O data $FILESYSTEM || exit 1
     564        # Extract the MBR
     565        zcat data | dd of=mbr count=1
     566        start=$(sfdisk -l mbr | tail -1 | tr -s ' ' | cut -d ' ' -f3)
     567        end=$(sfdisk -l mbr | tail -1 | tr -s ' ' | cut -d ' ' -f4)
     568        # copy the filesystem in P1 to the LUKS device
     569        echo "Copying..."
     570        pv data | zcat | dd of=/dev/mapper/$NAME skip=$start count=$((end-start))
     571
     572        # apply user data
     573        mount /dev/mapper/$NAME /mnt || error "mount failed"
     574        user_data
     575        umount /dev/mapper/$NAME || error "umount failed"
    540576}
    541577
    542578# example3: rootfs via existing filesystem
    543579rootfs3() {
    544         FILESYSTEM=https://dev.gateworks.com/buildroot/venice/minimal/rootfs.ext2.xz
    545         echo "Downloading $FILESYSTEM..."
    546         wget -q --show-progress --no-check-certificate -O data $FILESYSTEM || exit 1
    547         # copy the filesystem in P1 to the LUKS device
    548         echo "Copying..."
    549         pv data | xzcat | dd of=/dev/mapper/$NAME bs=16M
    550 
    551         # apply user data
    552         mount /dev/mapper/$NAME /mnt || error "mount failed"
    553         user_data
    554         umount /dev/mapper/$NAME || error "umount failed"
     580        FILESYSTEM=https://dev.gateworks.com/buildroot/venice/minimal/rootfs.ext2.xz
     581        echo "Downloading $FILESYSTEM..."
     582        wget -q --show-progress --no-check-certificate -O data $FILESYSTEM || exit 1
     583        # copy the filesystem in P1 to the LUKS device
     584        echo "Copying..."
     585        pv data | xzcat | dd of=/dev/mapper/$NAME bs=16M
     586
     587        # apply user data
     588        mount /dev/mapper/$NAME /mnt || error "mount failed"
     589        user_data
     590        umount /dev/mapper/$NAME || error "umount failed"
    555591}
    556592
     
    558594        rootfs=${1:-rootfs1}
    559595
    560         echo "Provision $DEV via $rootfs..."
    561 
    562         # board specific customizations
    563         case "$(cat /proc/device-tree/board)" in
    564                 GW74*) NIC=eth1;;
    565         esac
    566 
    567         # Mount the /tmp directory as a tmpfs with 75% of the available memory
    568         mount -t tmpfs /tmp -o size=75%
    569 
    570         # Change the current working directory to /tmp
    571         cd /tmp
    572 
    573         # bring up network
    574         echo "Bringing up network $NIC..."
    575         udhcpc -i $NIC
    576 
    577         echo "Creating partition table..."
    578         # partition disk:
    579         #   - you could use MBR or GPT based on your needs
    580         #   - ensure that you do not start your partition data until after your boot firmware
    581         # Create MBR with a single partition taking up the entire device
    582         printf "$((P1_OFFSETMB*1024*1024/512)),,L,*" | sfdisk -u S $DEV || exit 1
    583         DEV=${DEV}${PART}
    584 
    585         # Format the partition as a LUKS encrypted file system using the encryption key
    586         echo "Formating LUKS device..."
    587         echo "YES" | cryptsetup luksFormat $DEV $KEY - || exit 1
    588 
    589         # Open the LUKS encrypted partition and map it to the specified name ($NAME)
    590         echo "Opening LUKS device..."
    591         cryptsetup luksOpen $DEV $NAME --key-file=$KEY || exit 1
    592 
    593         # call rootfs option
    594         $rootfs
    595 
    596         # Close the LUKS device and remove the mapping
    597         echo "Closing LUKS device..."
    598         cryptsetup luksClose $NAME || exit 1
    599 
    600         echo "Provisioning complete"
    601 
    602         # Wait forever
    603         #while [ 1 ]; do sleep 1; done
    604 
    605         # power cycle
    606         echo 2 > /sys/bus/i2c/devices/0-0020/powerdown
     596        echo "Provision $DEV via $rootfs..."
     597
     598        # board specific customizations
     599        case "$(cat /proc/device-tree/board)" in
     600                GW74*) NIC=eth1;;
     601        esac
     602
     603        # Mount the /tmp directory as a tmpfs with 75% of the available memory
     604        mount -t tmpfs /tmp -o size=75%
     605
     606        # Change the current working directory to /tmp
     607        cd /tmp
     608
     609        # bring up network
     610        echo "Bringing up network $NIC..."
     611        udhcpc -i $NIC
     612
     613        [ "$BOOT_FIRMWARE" ] && {
     614                echo "Writing locked down U-Boot to memory..."
     615                wget -q --show-progress --no-check-certificate -O data $BOOT_FIRMWARE || exit 1
     616                # create 4MB boot0 image and flash it
     617                truncate -s 4M boot-firmware
     618                dd if=data of=boot-firmware bs=1K seek=33 conv=notrunc # note this seek=0 for imx8mm/imx8mp for boot0/boot1
     619                # BOOT partitions by default are read-only as they are typically used for sensitive boot firmware. To write to them you must disable force_ro in sysfs
     620                echo 0 > /sys/class/block/${DEVICE}boot0/force_ro
     621                # write the flash.bin with proper offset to unlocked BOOTpart
     622                dd if=boot-firmware of=/dev/${DEVICE}boot0
     623        }
     624
     625        [ "$FIT_IMAGE" ] && {
     626                echo "Flashing FIT Image to memory..."
     627                wget -q --show-progress --no-check-certificate -O data $FIT_IMAGE || exit 1
     628                # sanity check its not too big for P1_OFFSETMB
     629                #  - we don't want to automatically choose P1_OFFSETMB as you may want to support
     630                #    firmware updates and you should allow it to grow and thus choose your slack space
     631                FIT_SIZEMB=$(($(stat -c '%s' data) / 1024 / 1024))
     632                [ $FIT_SIZEMB -lt $(($P1_OFFSETMB + 1)) ] || {
     633                        echo "Error: $FIT_IMAGE is too large; adjust P1_OFFSETMB"
     634                        exit 1
     635                }
     636                # Write fit Image to memory
     637                dd if=data of=$DEV bs=1M seek=1
     638        }
     639
     640        echo "Creating partition table..."
     641        # partition disk:
     642        #   - you could use MBR or GPT based on your needs
     643        #   - ensure that you do not start your partition data until after your boot firmware
     644        # Create MBR with a single partition taking up the entire device
     645        printf "$((P1_OFFSETMB*1024*1024/512)),,L,*" | sfdisk -u S $DEV || exit 1
     646       
     647        [ "$TPM" ] && {
     648                # Get inital PCR measurment values
     649                echo "Retrieving initial PCR measurement values..."
     650                # PCR0: boot-firmware
     651                tpm2 pcrextend 0:sha1=$(sha1sum boot-firmware | cut -d" " -f1)
     652                # PCR8: partition table and FIT image (kernel, dtb, ramdisk)
     653                dd if=$DEV of=data bs=1M count=$P1_OFFSETMB
     654                tpm2 pcrextend 8:sha1=$(sha1sum data | cut -d" " -f1)
     655
     656                echo "Creating Key from TPM2.0..."
     657                tpm2_evictcontrol -C o -c $KEY_HANDLE # delete any existing key
     658                echo "Your Keyphrase (up to 256BYTE)" > $KEY
     659                tpm2_createpolicy --policy-pcr -l sha1:0,8 -L policy.digest #only sha1 works for our current TPM's PCRs
     660                tpm2_createprimary -g sha256 -G rsa -c primary.context
     661                tpm2_create -g sha256 -u obj.pub -r obj.priv -C primary.context -L policy.digest -a "noda|adminwithpolicy|fixedparent|fixedtpm" -i $KEY
     662                tpm2_load -C primary.context -u obj.pub -r obj.priv -c load.context
     663                tpm2_evictcontrol -C o -c load.context $KEY_HANDLE # save key to TPM handle
     664                rm -rf policy.digest primary.context obj.pub obj.priv load.context
     665        }
     666
     667        # Format the partition as a LUKS encrypted file system using the encryption key
     668        echo "Formating LUKS device..."
     669        echo "YES" | cryptsetup luksFormat ${DEV}${PART} $KEY - || exit 1
     670
     671        # Open the LUKS encrypted partition and map it to the specified name ($NAME)
     672        echo "Opening LUKS device..."
     673        cryptsetup luksOpen ${DEV}${PART} $NAME --key-file=$KEY || exit 1
     674
     675        # call rootfs option
     676        $rootfs
     677
     678        # Close the LUKS device and remove the mapping
     679        echo "Closing LUKS device..."
     680        cryptsetup luksClose $NAME || exit 1
     681
     682        echo "Provisioning complete"
     683
     684        # Wait forever
     685        #while [ 1 ]; do sleep 1; done
     686
     687        # power cycle
     688        echo 2 > /sys/bus/i2c/devices/0-0020/powerdown
    607689}
    608690
    609691for x in $(cat /proc/cmdline); do
    610         case "$x" in
    611                 bypass)
     692        case "$x" in
     693                bypass)
    612694echo "Booting straight to ramdisk..."
    613695umount /proc
     
    620702fi
    621703exec /sbin/init "$@"
    622                         ;;
    623                 provision=*) provision ${x//provision=};;
    624         esac
     704                        ;;
     705                provision=*) provision ${x//provision=};;
     706        esac
    625707done
    626708
     
    630712echo "Waiting for $DEV..."
    631713while [ ! -b "$DEV" ]; do
    632         sleep 1
    633         echo -n .
     714        sleep 1
     715        echo -n .
    634716done
    635717
    636718# Open the LUKS encrypted partition and map it to the specified name ($NAME)
     719[ "$TPM" ] && {
     720        echo "Fetching Key from TPM..."   
     721        tpm2_unseal -c $KEY_HANDLE -p pcr:sha1:0,8 -o fs.keyphrase_decrypted
     722        KEY=fs.keyphrase_decrypted
     723}
     724
    637725DEV=${DEV}${PART}
    638726echo "Opening $DEV..."
    639727cryptsetup luksOpen $DEV $NAME --key-file=$KEY || exit 1
     728
     729[ "$TPM" ] && {
     730        # reseal the key by extending the PCR's
     731        rm -rf fs.keyphrase_decrypted
     732        tpm2_pcrextend 0:sha1=0000000000000000000000000000000000000000
     733        tpm2_pcrextend 8:sha1=0000000000000000000000000000000000000000
     734}
    640735
    641736# Mount the LUKS device to /mnt
     
    663758
    664759==== Option1: Downloading a prebuilt ramdisk
    665 To download the prebuilt root file system and incorporate your script manually, follow these steps:
    666 {{{#!bash
    667 # download the ramdisk
     760To download the prebuilt root file system and incorporate the needed overlay files manually, follow these steps:
     761
     762Note: For Gateworks's standard BSP 6.6 Kernel to work seamlessly with the initialization scripts and enable TPM functionality, it's imperative to include the following kernel modules:
     763
     764- spi-imx.ko
     765- tpm_tis_spi.ko
     766- virt-dma.ko
     767- imx-sdma.ko
     768Additionally, ensure that the firmware file sdma-imx7d.bin is located in the directory lib/firmware/imx/sdma/. These modules are crucial for proper TPM integration and operation within our secure setup.
     769{{{#!bash
     770#download the ramdisk
    668771wget https://dev.gateworks.com/buildroot/venice/minimal/rootfs.cpio.xz
    669772# extract files from an existing gzipped cpio:
    670773mkdir initrd
    671774(cd initrd; xz -cd ../rootfs.cpio.xz | fakeroot -s ../initrd.fakeroot cpio -idmv)
    672 # copy key and init to it
    673 cp fs.key init initrd/
     775
     776#get all the custom files needed in one spot
     777mkdir overlay
     778cp fs.key init overlay/
     779
     780#utilize a bsp to copy in required kernel modules to be used for tpm in the init script
     781mkdir -p overlay/lib/firmware/imx/sdma/
     782export VENICE_BSP=/path/to/venice_bsp
     783for i in virt-dma imx-sdma spi-imx tpm_tis_spi; do file=$(find $VENICE_BSP/linux/ -name $i.ko); [ -r "$file" ] && cp $file overlay && echo $file; done
     784wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/imx/sdma/sdma-imx7d.bin -O overlay/lib/firmware/imx/sdma/sdma-imx7d.bin
     785
     786# copy needed files to initrd
     787cp -r overlay/* initrd/
     788
    674789# re-create initrd
    675790(cd initrd; find | fakeroot -i ../initrd.fakeroot cpio -o -H newc | xz --check=crc32 -c > ../rootfs.cpio.xz)
    676791}}}
    677 
    678 This will produce the desired rootfs.cpio.xz artifact which we will copy to our blobs directory for safe keeping:
    679 {{{#!bash
    680 cp rootfs.cpio.xz blobs/
     792This will produce the desired rootfs.cpio.xz artifact.
     793{{{#!bash
     794#copy it over to your tftp server (under the venice sub-dir)
     795cp rootfs.cpio.xz /tftpserver/venice
    681796}}}
    682797
     
    780895In comparing Option 1 and Option 2, both provide robust firmware security through code signing and verification. However, Option 2 goes a step further by integrating the verification into the hardware root-of-trust using platform security features like HABv4.
    781896
    782 Option 1 provides more versatility in terms of being able to construct different FIT image payloads signed by the same key that U-Boot can universally verify and boot from. This modularity can be advantageous, especially for deployment scenarios that need frequent kernel/filesystem updates without modifying the secure bootloader components.
     897Option 1 provides more versatility in terms of being able to construct different FIT image payloads signed by the same key that U-Boot can universally verify and boot from. This modularity can be advantageous, especially for deployment scenarios that need frequent kernel/filesystem updates without modifying the secure bootloader components. This is also appears to be the standard when implementing a secure boot process. We strongly recommend using this option.
    783898
    784899
     
    11101225[=#embedded-fit]
    11111226==== Option 2 - Embed the kernel/dtb/ramdisk in the U-Boot ITB
     1227'''''We Strongly recommend using option 1, we keep this option documented here in the off chance someone would want to implement this edge case for whatever reason'''''
    11121228For IMX you can utilize the fact that the SPL is using HABv4 and the SRK keys to verify the entire U-Boot FIT image (u-boot.itb) which already contains the ARM Trusted Firmware, U-Boot propper, and the U-Boot control DTB's.
    11131229 
     
    13361452 - change CONFIG_BOOTCOMMAND to what you need to directly boot (depending on the options above)
    13371453
    1338 
    1339 
    1340 == HABv4 encrypted boot architecture
    1341 The IMX HABv4 also provides an extra optional security operation by using cryptography (AES-CCM) to obscure the boot image so it can not be seen or used by unauthorized users.
    1342 
    1343 Encrypted boot adds an extra layer of security to the boot sequence using cryptographic techniques to obscure the bootloader data (which can be extended to the entire firmware image)so that it can not be seen or used by unauthorized users. This mechanism protects and conceals the bootloader code residing in flash.
    1344 
    1345 The Data Encryption Key (DEK) is an AES key used to encrypt the boot image (via the Code Signing Tool) and decrypt the boot image (using the DEK blob appended to the image). The DEK blob is used as a security layer to wrap and store the DEK off-chip which is unique to the chip that generated the blob.
    1346 
    1347 Generation of the DEK blob that gets appended to your image must be done on the IMX via the U-Boot dek_blob command which is enabled with CONFIG_CMD_DEKBLOB=y.
    1348 
    1349 References:
    1350  - https://elixir.bootlin.com/u-boot/latest/source/doc/imx/habv4/introduction_habv4.txt
    1351  - https://elixir.bootlin.com/u-boot/v2021.07/source/doc/imx/habv4/guides/encrypted_boot.txt
    1352  - NXP AN12056 - Encrypted Boot on HABv4 and CAAM Enabled devices
     1454== TPMv2.0
     1455Now that we've implemented encrypted storage, providing a solid layer of security for data-at-rest protection, we can consider an optional step to further enhance our system's security. This step involves integrating TPM 2.0 technology, which offers features like measured boot and secure key storage. By opting for TPM 2.0 integration, we can extend the chain of trust and manage encryption keys with enhanced security. Next, we'll outline the steps to integrate TPM 2.0 into our secure setup for those who wish to implement this additional security measure. For this example we are building of the base blocks of "Option 1 - using an External FIT Image" above.
     1456
     1457TPMv2.0 (Trusted Platform Module) is a hardware-based security solution designed to provide secure storage and processing of cryptographic keys, digital certificates, and other security-related data on computing platforms. It is an international standard developed by the Trusted Computing Group (TCG) and serves as an evolution of the original TPM specification (TPMv1.2). Platform Configuration Registers (PCRs) are specialized registers within the TPM that store cryptographic hashes, also known as digests or integrity measurements, of the software components running on the system. These digests are generated using secure hashing algorithms, such as SHA-256, and represent the measured state of the code running on your computer at various stages of the boot process.
     1458
     1459The process of extending a PCR involves updating its current value by combining it with a new digest using a one-way operation. The integrity measurement is hashed together with the existing PCR value, and the result is stored back in the PCR. This process ensures that any change to the system's software state, including the order in which components are loaded, will alter the final PCR values, enabling detection of unauthorized modifications or tampering.
     1460
     1461The TPM contains a small amount of Non-Volatile RAM (NV RAM) that can be used to store persistent data and configurations. The NV RAM is divided into several areas, each with its own access policies and permissions.
     1462
     1463One of the main features of the TPM is the ability to perform a "measured boot" process. During boot, it is intended that the system firmware (BIOS/UEFI) measures and records the hash of each component involved in the boot process, such as the bootloader, kernel, drivers, and just about any other software blob running on your system that can be hashed. These measurements are stored in the TPM's PCRs.
     1464
     1465By comparing the PCR values against known good values, the system can detect if any unauthorized modifications have been made to the boot components. This allows for a secure boot process and provides a chain of trust for the entire system.
     1466
     1467In our example, the PCRs and NV RAM are leveraged together to implement measured boot and secure storage of data. Sensitive data can be "sealed" to specific PCR values, meaning it is encrypted by the TPM and can only be decrypted if the PCR values match the expected values (i.e., the system is in a known good state).
     1468
     1469You can read more about the TPMv2.0 spec here: https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagementDomainFirmwareProfile_v1p00_11aug2020.pdf
     1470
     1471Although we intend to adhere to the Trusted Computing Group's guidelines for utilizing TPMv2.0 as outlined in the specification, the support for TPMv2.0 in U-Boot is still somewhat limited due to its relatively newer adoption. Consequently, we will primarily rely on our IMX High Assurance Boot (IMX.HAB) feature, which is part of the on-chip BOOT ROM, to serve as our Code Root of Trust for Measurement (CRTM). Once the boot process reaches U-Boot, we will extend the PCRs with SHA-1 digests of our firmware components and of our FIT Image Blob.
     1472
     1473In this example we are using PCR 0 to measure the entire boot firmware including the SPL, ATF, U-Boot DTB's and the u-boot environment. Additionally, we are dedicating PCR 8 specifically for measuring the contents of the fit.itb, which includes the device tree blob (.dtb), kernel Image, and ramdisk as those are part of the OS. Technically you can consider things like bootargs and ramdisk as OS configuration (PCR9) but we don't care to make that distinction here.
     1474
     1475According to the TCG specification's Table 1 PCR Usage, PCR 0 is designated for the SRTM (Static Root of Trust for Measurement) and Boot Loader, which aligns with our decision to use it for measuring the entire boot firmware. PCR 8, on the other hand, is defined for use by the Management Domain OS, making it a suitable choice for measuring the contents of our fit.itb, which will be essential for the operating system's boot process.
     1476
     1477This mechanism is used in the provided script to protect the encryption key for the root filesystem. The key is sealed to specific PCR values representing the boot firmware and FIT Image (kernel & device tree blob & initrd) measurements. During the boot process, the script unseals the key from the TPM using the current PCR values, allowing the encrypted root filesystem to be unlocked and mounted.
     1478
     1479We'll securely store the key necessary for unlocking our encrypted storage device and filesystem within the TPM. Access to this key will be restricted to the ramdisk only if the PCRs have been extended with precise data from our firmware components and FIT Image Blob. Once this key is utilized to unlock the encrypted disk device, we'll update the PCRs again. Any subsequent attempts to access the key post-separation event will be unsuccessful since the PCRs will no longer align with the sealing policy.
     1480
     1481In order to successfully integrate the TPM into our secure setup, these components and configurations are necessary:
     14821. A Gateworks board that has a tpm (from the following list) with a regular Gateworks u-boot enviroment:
     1483 - GW71x1-E
     1484 - GW72x1-F+
     1485 - GW73x1-F+
     1486 - GW74x1-B+
     1487 - GW830x
     1488 - GW890x
     14892. A TFTP server with the following files:
     1490 - The final FIT Image Tree Blob (fit.itb) you want to use for flashing
     1491 - The final flash.bin from U-Boot with appropriate tpm, lockdown, and boot command configurations you want to use for flashing
     1492
     1493We are choosing the following PCR conventions:
     1494 * PCR0 - SRTM & Boot Loader:
     1495  - boot firmware (emmc boot0 hardware partition)
     1496 * PCR8 - Management Domain OS
     1497  - OS (partition table, FIT image) (not root filesystem as we assume that is read/write and encrypted in this example)
     1498
     1499We are choosing to store our fs key in the TPM NVRAM (0x81000000 - 0x81800000) in a somewhat random location:
     1500 * 0x81234567
     1501
     1502=== Using the TPM with the init script
     1503If you want to utilize the discrete TPM on your Gateworks board, simply add the 'tpm' argument at the end of the bootargs in U-Boot.
     1504{{{#!bash
     1505#How to use the tpm with provisioning
     1506setenv bootargs provision=rootfs1 tpm
     1507#How to use the TPM for unlocking
     1508setenv bootargs tpm
     1509}}}
     1510
     1511=== Final u-boot flash.bin and FIT Image
     1512
     1513This section serves as a summary step for this wiki article.
     1514
     1515Similarly to the meticulous steps outlined throughout this wiki article, it is essential to confirm the inclusion of the final desired blobs in the FIT Image, while also configuring our end u-boot environment with the specific settings we desire:
     1516
     1517For the FIT Image, you must use this rootfs.cpio.xz that we just created above, a standard (built from our BSP) or custom device tree blob specific to the board you are using, and you can use our Gateworks Kernel (built from our BSP) or other custom kernel:
     1518{{{#!bash
     1519mkdir blobs
     1520cp $VENICE_BSP/linux/arch/arm64/boot/Image blobs/
     1521cp $VENICE_BSP/linux/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x.dtb blobs/
     1522cp rootfs.cpio.xz blobs/
     1523# gzip the kernel
     1524gzip -fk blobs/Image
     1525}}}
     1526
     1527Once you created a fit.itb comprised of these individual blobs by following the steps outlined in the "Generation of Signed FIT Image" section you just need to copy that FIT image to the tftp server you intend to use (same server ip that you define inside the init script).
     1528
     1529Now we need to modify U-Boot to enable which security features you wish to leverage and change the boot command:
     1530* '''''i.MX HAB CONFIG OPTIONS'''''
     1531 - CONFIG_IMX_HAB=y #'hab_auto_img', 'hab_status' and 'hab_version' commands
     1532 - CONFIG_SPL_LOAD_FIT_ADDRESS=0x44000000
     1533* '''''SIGNED FIT IMAGE CONFIG OPTIONS'''''
     1534 - CONFIG_FIT_SIGNATURE=y #enable signature verification of FIT uImages using a hash signed and verified using RSA.
     1535 - RSA=y # enable RSA library
     1536 - CONFIG_LEGACY_IMAGE_FORMAT=n #undefined - otherwise this allows booting unsigned images or any image if you lack a signature node
     1537    - Include signature Node in u-boot build (See "Getting FIT key into U-Boot proper and verifying signed images" section)
     1538* '''''LOCKED DOWN U-BOOT CONFIG OPTIONS'''''
     1539 - CONFIG_BOOTDELAY=-1 #disables use of u-boot prompt
     1540 - CONFIG_ENV_IS_NOWHERE=y #disable env load/save
     1541 - CONFIG_ENV_IS_IN_MMC=n
     1542* '''''Choose BOOTCOMMAND CONFIG OPTION depending on if you want to use a TPM or not'''''
     1543 - CONFIG_BOOTCOMMAND="tpm2 init && tpm2 startup TPM2_SU_CLEAR && tpm2 self_test full && tpm2 self_test continue && mmc dev 2 1 && mmc read $loadaddr 0 0x2000 && hash sha1 $loadaddr 0x400000 *0x40200000 && md.b 0x40200000 0x20 && tpm2 pcr_extend 0 0x40200000 sha1 && tpm2 pcr_read 0 0x40200000 sha1 && mmc dev 2 0 && mmc read $loadaddr 0x0 0x20000 && hash sha1 $loadaddr 0x4000000 *0x40200000 && md.b 0x40200000 0x20 && tpm2 pcr_extend 8 0x40200000 sha1 && tpm2 pcr_read 8 0x40200000 sha1 && setenv bootargs tpm && mmc dev 2 0 && mmc read 0x40200000 0x800 0x1f800 && bootm 0x40200000" #If you are using a TPM
     1544 - CONFIG_BOOTCOMMAND="setenv bootargs; mmc dev 2 0 && mmc read 0x40200000 0x800 0x1f800 && bootm 0x40200000" # If you are not using the TPM
     1545
     1546Procedure:
     1547 1. Checkout U-Boot (or use your existing U-Boot that you have been working with):
     1548{{{#!bash
     1549git clone https://github.com/Gateworks/uboot-venice.git
     1550cd uboot-venice
     1551# copy necessary artifacts from bsp
     1552cp $VENICE_BSP/u-boot/lpddr4*.bin . # DDR firmware
     1553cp $VENICE_BSP/atf/build/imx8mm/release/bl31.bin . # ATF
     1554}}}
     1555 1. Make sure your environment is configured for cross-compiling:
     1556{{{#!bash
     1557(cd $VENICE_BSP; . ./setup-environment)
     1558make imx8mm_venice_defconfig
     1559}}}
     1560 1. Use 'make menuconfig' to make the changes above
     1561{{{#!bash
     1562make menuconfig # enable CONFIG options described above
     1563make savedefconfig && cp defconfig configs/imx8mm_venice_defconfig
     1564}}}
     1565 1. Make the flash.bin and sign it and tftp it over
     1566{{{#!bash
     1567make flash.bin
     1568# sign flash.bin; see "i.MX secure boot" section
     1569/bin/sh doc/imx/habv4/csf_examples/mx8m/csf.sh
     1570}}}
     1571 1. Its a good idea for troubleshooting to enable DEBUG in common/spl/spl_fit.c by adding '#define DEBUG' to the top of that file
     1572
     1573When complete your differences should look like this:
     1574{{{#!bash
     1575$ git diff
     1576diff --git a/configs/imx8mm_venice_defconfig b/configs/imx8mm_venice_defconfig
     1577index dc391e47da..556052a7ce 100644
     1578--- a/configs/imx8mm_venice_defconfig
     1579+++ b/configs/imx8mm_venice_defconfig
     1580@@ -6,7 +6,6 @@ CONFIG_SPL_GPIO=y
     1581 CONFIG_SPL_LIBCOMMON_SUPPORT=y
     1582 CONFIG_SPL_LIBGENERIC_SUPPORT=y
     1583 CONFIG_ENV_SIZE=0x8000
     1584-CONFIG_ENV_OFFSET=0x3f0000
     1585 CONFIG_DM_GPIO=y
     1586 CONFIG_DEFAULT_DEVICE_TREE="imx8mm-venice"
     1587 CONFIG_SPL_TEXT_BASE=0x7E1000
     1588@@ -17,7 +16,8 @@ CONFIG_SPL_SERIAL=y
     1589 CONFIG_SPL_DRIVERS_MISC=y
     1590 CONFIG_SPL_STACK=0x920000
     1591 CONFIG_SPL=y
     1592-CONFIG_ENV_OFFSET_REDUND=0x3f8000
     1593+CONFIG_IMX_HAB=y
     1594+# CONFIG_CMD_DEKBLOB is not set
     1595 CONFIG_SYS_LOAD_ADDR=0x48200000
     1596 CONFIG_SYS_MEMTEST_START=0x40000000
     1597 CONFIG_SYS_MEMTEST_END=0x80000000
     1598@@ -25,11 +25,14 @@ CONFIG_LTO=y
     1599 CONFIG_SYS_MONITOR_LEN=524288
     1600 CONFIG_FIT=y
     1601 CONFIG_FIT_EXTERNAL_OFFSET=0x3000
     1602+CONFIG_FIT_SIGNATURE=y
     1603 CONFIG_SPL_LOAD_FIT=y
     1604 CONFIG_SPL_LOAD_FIT_ADDRESS=0x44000000
     1605 CONFIG_OF_BOARD_SETUP=y
     1606 CONFIG_OF_SYSTEM_SETUP=y
     1607 CONFIG_DISTRO_DEFAULTS=y
     1608+CONFIG_BOOTDELAY=1
     1609+CONFIG_BOOTCOMMAND="tpm2 init && tpm2 startup TPM2_SU_CLEAR && tpm2 self_test full && tpm2 self_test continue && mmc dev 2 1 && mmc read $loadaddr 0 0x2000 && hash sha1 $loadaddr 0x400000 *0x40200000 && md.b 0x40200000 0x20 && tpm2 pcr_extend 0 0x40200000 sha1 && tpm2 pcr_read 0 0x40200000 sha1 && mmc dev 2 0 && mmc read $loadaddr 0x0 0x20000 && hash sha1 $loadaddr 0x4000000 *0x40200000 && md.b 0x40200000 0x20 && tpm2 pcr_extend 8 0x40200000 sha1 && tpm2 pcr_read 8 0x40200000 sha1 && setenv bootargs tpm && mmc dev 2 0 && mmc read 0x40200000 0x800 0x1f800 && bootm 0x40200000"
     1610 CONFIG_USE_PREBOOT=y
     1611 CONFIG_PREBOOT="gsc wd-disable"
     1612 CONFIG_BOARD_LATE_INIT=y
     1613@@ -77,9 +80,7 @@ CONFIG_CMD_EXT4_WRITE=y
     1614 CONFIG_OF_CONTROL=y
     1615 CONFIG_SPL_OF_CONTROL=y
     1616 CONFIG_OF_LIST="imx8mm-venice imx8mm-venice-gw71xx-0x imx8mm-venice-gw72xx-0x imx8mm-venice-gw73xx-0x imx8mm-venice-gw7901 imx8mm-venice-gw7902 imx8mm-venice-gw7903 imx8mm-venice-gw7904 imx8mm-venice-gw75xx-0x"
     1617-CONFIG_ENV_IS_IN_MMC=y
     1618 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
     1619-CONFIG_SYS_MMC_ENV_DEV=2
     1620 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
     1621 CONFIG_USE_ETHPRIME=y
     1622 CONFIG_ETHPRIME="eth0"
     1623}}}
     1624
     1625
     1626=== Provisioning
     1627Now that we have all the necessary files in our tftp server, instantiating the provisioning of a FDE on a Gateworks board will look something like this:
     1628{{{#!bash
     1629u-boot=> dhcp && setenv serverip <YOUR_SERVER_IP> && setenv bootargs provision=rootfs1 && tftpboot 0x40200000 venice/fit.itb && bootm 0x40200000
     1630}}}
     1631
     1632If you opt to use the TPM for enhanced security it will look like this instead:
     1633{{{#!bash
     1634u-boot=> dhcp && setenv serverip <YOUR_SERVER_IP> && setenv bootargs provision=rootfs1 tpm && tftpboot 0x40200000 venice/fit.itb && bootm 0x40200000
     1635}}}
     1636
     1637
     1638Once the board completes provisioning its storage device, the secure system setup for your Venice board is complete.
     1639
     1640=== further tpm reading/sources
     1641For more info on TPM see:
     1642 - https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagementDomainFirmwareProfile_v1p00_11aug2020.pdf
     1643 - https://community.infineon.com/t5/Blogs/Sealing-and-unsealing-data-in-TPM/ba-p/465547
     1644 - https://community.infineon.com/t5/Blogs/Storing-and-reporting-system-measurements-with-TPM/ba-p/443590
     1645 - https://trustedcomputinggroup.org/resource/tpm-library-specification/
     1646 - https://tpm2-tools.readthedocs.io/en/latest/