Secure Boot

Introduction

Secure boot aims at firmware protection, which prevents attackers from modifying or replacing firmware maliciously. When the chip is powered on, the secure boot ROM executes to check the validation of the image signature.

If the signature is valid, authentication will be successful, which means that the firmware is safe and the subsequent operations can be continued. Otherwise, the SoC clears the stack and goes into an endless loop.

This chapter illustrates the usage of Linux verified boot.

ROM Boot Mechanism

Linux secure boot should be guided to start from ROM code, which verifies the bootloader using Root of Trusted Key (RoT) saved in the OTP. Bootloader shall verify the KM0/KM4 images and cert.bin in firmware. Except for RoT, all the keys are saved in cert.bin (Key Cert).

../../_images/secure_boot_flow.svg

Secure boot flow

Chain Verification

Linux secure boot is based on ROM/KM0/KM4 secure boot. The secure boot flow of Linux part is illustrated below.

../../_images/verified_boot_sw_arch.svg

Note

Normally, the kernel cmdline will be Kernel command line: console=ttyS0,1500000 earlycon psci=enable ubi.mtd=8 ubi.block=0,0 ubi.mtd=9 dm-mod.create="system,,0,ro, 0 55928 verity 1 /dev/ubiblock0_0 /dev/ubiblock0_0 4096 4096 6991 6991 sha512 <salt> <hash> 2 ignore_corruption ignore_zero_blocks" root=/dev/dm-0 rootfstype=squashfs.

The cmdline is shown when kernel initializing and the content is given by <sdk>/sources/boot/uboot/cmd/realtek_avb.c.

Function realtek_organize_cmdline() will abstract the key information and organize a new cmdline for secure boot.

  • The ubi.mtd=8 means the index of rootfs block in mtd, which is used to make mtd8 as character-device ubi0.

  • The ubi.block=0,0 means make character-device ubi0 as block-device ubiblock0, because the dm verity can only be done for block-devices.

  • The dm-mod.create parameters are defined by dm-verity driver. Including the block-device to verify, the size of hash block, the numbers of hash block, the start address of rootfs hash tree, the salt and digest of verification and so on. The digest is the root hash of rootfs which has been verified by VBmeta in uboot.

  • The ubi.block0_0 is attached to dm-0. root=/dev/dm-0 mounts dm-0 to root-filesystem which also means make informations in mtd8 area as rootfs. The dm-verity will do a dynamic hash calculation for any block and its related blocks when user accesses to some blocks in rootfs.

For more details on dm-verity, refer to dm verify.

This section describes the Construction Parameters, Theory of operation, Hash Tree, On-disk format and some examples. The kernel command line is the only start-point for the hash-tree verification of rootfs, and the digest of root-hash for hash-tree will be inserted to VBmeta whose validity is confirmed by the former flow.

Codes of the above framework can be divided into three parts: Flash area, U-Boot area and kernel area. Only the core code directories of each part are listed below.

Area

Directory

Introduction

Flash

<sdk>/sources/yocto/meta-realtek/tools/verified_boot

The script of making secure related images.

U-Boot

<uboot>/cmd/mtd.c

The operations of reading NAND Flash.

<uboot>/cmd/realtek-avb.c

The verification of vbmeta/public key/kernel/dtb.

Kernel

<linux>/drivers/md/*

This directory is provided by GPI Linux kernel named dm-verity, used to verify the hash tree of rootfs.

More for android verified boot, refer to android avb.

Usage

The following steps illustrate how to use secure boot.

  1. Enable uboot secure boot configs

  2. Prepare secure boot keys

  3. Make secure images

  4. Enable verified boot

Enable UBoot Secure Boot Config

To enable Linux secure boot, make sure uboot related secure boot configs are enabled, the uboot config listed at <sdk>/sources/boot/uboot/configs and secure boot related configs are listed below

CONFIG_VERIFIED_BOOT=y
CONFIG_OTP_RTK_AMEBA=y

Currently we have enabled the configs by default.

Prepare Secure Boot Key

To use Linux verified boot, secure keys should be prepared.

The default manifest/key files are located at <sdk>/sources/yocto/meta-realtek/tools/verified_boot/security_keys/test. The default key can be used directly during the development phase. However, a custom secure key must be generated for mass production.

Linux SDK provides tool make_key in path <sdk>/sources/yocto/meta-realtek/tools/verified_boot for users to generate their own secure keys under specific key path. Use the following command to generate secure keys, which will be generated under the path <key path> :

make_key <key path>

Secure keys are listed below:

File

Description

manifest.json5

Used to store all secure boot key information

vbmeta.priv.key

Private key information for the Linux vbmeta secure firmware

vbmeta.pub.key

Public key information for the Linux vbmeta secure firmware

soc_info.json

SOC information

Make Secure Image

Before making secure images, all the raw images need to be generated first.

Yocto SDK uses mksecure.sh to compile secure images. The script is lacated at <sdk>/sources/yocto/meta-realtek/tools/verified_boot .

The usage of this script is described as below:

mksecure.sh
--key_dir=<secure key path>
--output_dir=<secure image output path>
--input_dir=<directory of the normal images>
--boot_image=<boot image path>
--dtb_image=<device tree blob image path>
--dtb_part_size=<tree blob image partition size>
--kernel_image=<kernel image path>
--kernel_part_size=<kernel partition size>
--recovery_dtb_image=<recovery device tree blob image path>
--recovery_dtb_part_size=<recovery device tree  blob partition size>
--recovery_kernel_image=<recovery kernel image path>
--recovery_kernel_part_size=<recovery kernel partition size>
--root_image=<rootfs image path>
--root_part_size=<rootfs partition size>
--km4_boot=<firmware boot image path>
--km4_app=<firmware app image path>
--imgtool_flashloader=<imgtool flashloader path>
--use_dtb_size =<enable the auto parse of image size>

The parameters are illustrated below:

Parameter

Mandatory/Optional

Description

key_dir

Mandatory

Indicates where the secure keys locate at.

Ddefault is <sdk>/sources/yocto/meta-realtek/tools/verified_boot/security_keys/test.

output_dir

Mandatory

Indicates the output path of the secure images.

input_dir

Optional

Indicates the directory of the normal images.

  • Images inside this directory will be used as the source of secure images.

  • If input_dir is given, the boot_image, kernel_image, recovery_kernel_image, root_image, km4_boot, km4_app and imgtool_flashloader can be omitted. The mksecure.sh will use boot.img, uImage, <va7, va8>.rootfs.squashfs, km4_boot_all.bin, km0_km4_app.bin, imgtool_flashloader.bin, and uImage-initramfs-rtl8730elh-recovery.bin by default inside the given input_dir.

  • If some of the images are specified by other input parameter, mksecure.sh will use the specified path preferentially.

  • If input_dir is not given, all the image path shall be given each and every.

dtb_image

Mandatory

Indicates the path of non-secure device tree blob images.

recovery_dtb_image

Mandatory if recovery is enabled

Indicates the path of recovery device tree blob image, and this parameter is not mandatory if non-secure recovery images
need to be flashed.

boot_image

Optional if input_dir is given

Indicates the path of non-secure boot images.

kernel_image

Optional if input_dir is given

Indicates the path of non-secure kernal images.

recovery_kernel_image

Optional if input_dir is given

Indicates the path of non-secure recovery kernal images, and this parameter is not mandatory if non-secure recovery images
need to be flashed.

root_image

Optional if input_dir is given

Indicates the path of non-secure rootfs squashfs image, and only squashfs image is needed.

km4_boot

Optional if input_dir is given

Indicates the path of non-secure firmware boot image.

km4_app

Optional if input_dir is given

Indicates the path of non-secure firmware APP image.

imgtool_flashloader

Optional if input_dir is given

Indicates the path of imgtool_flashloader.bin.

use_dtb_size

Optional, also named as -s

Set to 1 to enable automatically dtb parse.

  • The mksecure.mk will parse the size information according to the selected dtb_image.

  • If -s is enabled, the size information of dtb_part_size, kernel_part_size, recovery_dtb_part_size, recovery_kernel_part_size, and root_part_size can be omitted.

  • However, make sure that the description for layout in dts includes the key names of Device Tree Blob, Kernel Image, and Rootfs Image (the capitalization of letters is not important).

dtb_part_size

Only useful when -s is not set

Indicates the partition size of device tree blob partition, which is described in
<dts_dir>/rtl8730e-spi-nand-256m.dtsi (rtl8730e-spi-nand-128m.dtsi).

kernel_part_size

Only useful when -s is not set

Indicates the partition size of kernel partition described in rtl8730e-spi-nand-256m.dtsi (rtl8730e-spi-nand-128m.dtsi).

recovery_dtb_part_size

Only useful when -s is not set

Indicates the partition size of recovery device tree blob described in rtl8730e-spi-nand-256m.dtsi (rtl8730e-spi-nand-128m.dtsi),
and this parameter is not mandatory if non-secure recovery images need to be flashed.

recovery_kernel_part_size

Only useful when -s is not set

Indicates the partition size of recovery kernel described in rtl8730e-spi-nand-256m.dtsi (rtl8730e-spi-nand-128m.dtsi),
and this parameter is not mandatory if non-secure recovery images need to be flashed.

root_part_size

Indicates the partition size of rootfs described in rtl8730e-spi-nand-256m.dtsi (rtl8730e-spi-nand-128m.dtsi).

Where <dts_dir> means the directory of dts files, which is <sdk>/kernel/linux-5.4/arch/arm/boot/dts for kernel 5.4.x, and <sdk>/kernel/linux-6.6/arch/arm/boot/dts/realtek/ameba for kernel 6.6.x.

Enable Verified Boot

After flashing the secure images and system boots up, enable secure boot via programming OTP bit.

The specific key information in the example is the default key included with the Linux SDK.

  1. Ensure that the key information described in Prepare Secure Boot Key is correctly used to compile the secure image, and that the key information in that path will be written to the OTP.

  2. Program secure boot root public key hash in OTP.

    The root public key hash value is from the file manifest.json5 described in Prepare Secure Boot Key . Find the field sboot_public_key_hash in image1.

    image1: {
      img_id: 0,
      img_ver_major: 1,
      img_ver_minor: 1,
      huk_epoch: 1,
      rsip_iv: "0102030405060708",
      sboot_private_key: "A3508C1155602F2C7B5DAC524868A4667B63D2097482786838EFD1046E31404E",
      sboot_public_key: "63C64A234E15B11E7C4A9227F151C640637AEF0699774DCAA7D38BB565172896",
      sboot_public_key_hash: "B7A307DCE8C5967983D55A9E3EB0E0617C48775383753A6D26EA6E13B1187BD3",
    },
    

    Use the following command to program OTP PK1:

    efuse wraw 320 32 B7A307DCE8C5967983D55A9E3EB0E0617C48775383753A6D26EA6E13B1187BD3
    
  3. Enable secure boot in OTP.

    1. Use efuse rmap first to check value in 0x2 and 0x3:

      $efuse rmap 0 16
      
      ../../_images/check_bit.png

      For example, we can see that the values at addresses 0x2 and 0x3 are 0x10 and 0xa0, respectively.

    2. Set 0x3[2] to 1 to enable the secure boot enable bit. Taking 0x10 0xa0 as an example, we would need to write 0x10 0xa4 to addresses 0x2 and 0x3.

      $efuse wmap 2 2 10a4
      

      Use efuse rmap again to check if the secure boot bit has been successfully set.

      ../../_images/enable_bit.png
  4. Reset the board.

    When secure boot is successful, you can see the following logs:

    • IMG1 SBOOT EN: secure boot is enabled

    • IMG1(OTA1) VALID, ret: 0: bootloader authentication pass

    • IMG2 VERIFY PASS: IMAGE2 authentication pass

    • AP BL1&FIP VERIFY PASS: AP uboot authentication pass

    • Public Key Hash Verified Success

    • Rollback Index: Version PASS!: rollback authentication pass

    • VbMeta Signature Verified Success!: vbmeta authentication pass

    • Kernel Image verified success!: linux kernel authentication pass

    • DTB/FDT Image verified success!: Linux DTB authentication pass

    • linux verified boot: success!