How S32g verify secure boot image

Secure boot refers to a two-stage process of successive authentication of the U-Boot and Linux kernel images. This process requires a "root of trust", which is known to be secure. In this case, the root of trust is HSE itself. Each image is authenticated by the preceding step. Thus, the secure boot flow is the following:

  1. BootROM passes control over to HSE FW;

  2. HSE FW authenticates the U-Boot image;

  3. U-Boot authenticates the Kernel image. U-Boot authentication is currently only supported when booting from an SD card

How uboot gets verified:

To authenticate the U-Boot image, HSE uses Advanced Secure Boot (ASB). The system configuration is saved as a System Image (SYS_IMG), which contains data related to imported keys, Secure Memory Region (SMR) configuration and Core Reset (CR) entry configuration.

  • The SYS_IMG is signed with a device-specific key.

  • The keys used for ASB are stored in a NVM key catalog, which contains multiple slots for multiple key types and authentication schemes.

  • The Secure Memory Region entry is used to define which data needs to be authenticated from the boot media, which key and authentication scheme is required, and where to place the data in memory after authentication.

  • The Core Reset entry is used to define which core should be enabled and what address to jump to after authentication, as well as what action to take in case authentication fails.

The steps to enable secure boot:

1. Read the IVT from the boot media;
2. Configure the HSE NVM and RAM key catalogs if no SYS_IMG;
3. Import the RSA public key into the NVM key catalog;
4. Configure and install the Core Reset entry;
5. Configure and install the Secure Memory Region entry;
6. Generate the signed SYS_IMG and Write the SYS_IMG back onto the boot media;
7. Set the BOOT_SEQ bit and Write the IVT back onto the boot media;
8. reboot board

in uboot, hse_secboot_enable is provided to enable secure boot
do_hse_secboot_enable   (arch/arm/mach-s32/s32-cc/hse_adv_secboot.c)

The boot image signature is located in “tb-fw-cert” entry of the boot image which is read only. the verification RSA public key is copied in boot partition of SD card . Also a certificate can be used to verify the boot image signature. the certificate is signed by the device specific key. In the step 3 of enable secure boot, when the public key is imported to HSM, the device specific key is used to check the authenticate of the certificate.

How S32g uboot authenticate Linux kernel:

Kernel image authentication is provided by U-Boot, using the upstream verified boot method. This method will use an .its file, which defines a dtb/kernel configuration and a signing scheme.

this is a sample its file. the output is an ITB file which should be copied to boot partition of SD card. the signature is embedded in ITB file.

/dts-v1/;

/ {
        description = "kernel+dtb/fdt fit image";
        #address-cells = <1>;
        
        images {
                kernel@1 {
                        description = "kernel image";
                        data = /incbin/("/home/shihaijin/secure-boot1/linux/arch/arm64/boot/Image");
                        type = "kernel";
                        arch = "arm64";
                        os = "linux";
                        compression = "none";
                        load = <0x81000000>;
                        entry = <0x81000000>;
			 kernel-version = <1>;
                        hash@1 {
                                algo = "sha1";
                        };
                };
                fdt@1 {
                        description = "dtb blob";
                        data = /incbin/("/home/shihaijin/secure-boot1/linux/arch/arm64/boot/dts/freescale/s32g274a-rdb2.dtb");
                        type = "flat_dt";
                        arch = "arm64";
                        compression = "none";
                        load = <0x83000000>;
                        entry = <0x83000000>;
                        fdt-version = <1>;
                        hash@1 {
                                algo = "sha1";
                        };
                };
        };

        configurations {
                default = "conf@1";
                conf@1 {
                        kernel = "kernel@1";
                        fdt = "fdt@1";
                        signature@1 {
                               algo = "sha1,rsa2048";
				key-name-hint = "boot_key";
				sign-images = "kernel", "fdt";
                        };
                };
        };
};              

The public key to verify kernel ITB image is attached to the boot loader device tree:

signature {
		key-boot_key {
			rsa,r-squared = <0x4a1545d9 0x29fa8582 0x2091da6a 0x55fc4189 0x74d35293 0xd90435e5 0xbb6b1e28 0xa32f5a1f 0x661028e8 0x7195b57f 0xb1fed832 0xc979ed61 0xc6b1545a 0x75454906 0x735e217a 0x960860c0 0x5f3e4862 0x75979377 0x3944db15 0x9e4c5236 0xbcc3da84 0xcf3d3355 0x713ecfc2 0xc4f33e77 0xc7e69537 0xcfe9d7a4 0x3b5cc949 0x256ce9f1 0x92cc1c96 0xe10b89c8 0x9dabdddb 0x3acf256f 0xe3dccf97 0x1b2ce495 0xbfebeb47 0xc9a30c95 0xbb6de685 0x753f14be 0xb081bb34 0x230adab3 0xc02cd506 0xace12335 0xbc16a4c2 0x9d81a391 0x541fe9d1 0xc287d566 0xf889643f 0xd114cb21 0x1089004 0x4050fd98 0xb1da22e3 0x2f978065 0xcc8e25f1 0x643be4cd 0x11fc9fcc 0x453d0297 0x3c9326c3 0x16f83eaa 0x73ca8a6d 0xa975b417 0x96bcf8a7 0xbc3cf8dc 0x8c45d2 0xc72e3bc3>;
			rsa,modulus = <0xdd1384ff 0xde9f083c 0x526d06ed 0x5d6e5d06 0x96a2488d 0xb2ba6461 0x1d068621 0x4caa414d 0xf52e809 0xaa92f3a8 0x783de6f9 0x4f5302e8 0xe97d07e6 0xfc5b7023 0x8bae0329 0xb5651340 0xf411f9bb 0x43efff91 0xda1777b4 0xa701f58c 0xec5b9087 0xd3d43320 0x3b0e5aea 0x7f9e4155 0x8a474975 0xdf92281 0xb164d60b 0x71d03ba8 0x2f9aeec 0x8e19c931 0xaabdff05 0xdddb4afb 0xbdd1d2a8 0xf47ac289 0x3c269c72 0x1ad3ecc8 0x72e8a68d 0xad1e547f 0x2054ce53 0x2da1e792 0x5a1e108d 0xf922b5e2 0x10255a18 0x7c39e49a 0x26131d6b 0xa4397e0 0x55c518b0 0xad5b9f0d 0xb91d12e8 0x24d0248e 0xe6f8cc14 0x5a80155 0x5dea4d52 0x3968eff6 0x6dc6b04e 0xae16a6ee 0xe322291e 0x3f927c51 0x944432e7 0x52ac4af0 0xa369e0a1 0x573b96b5 0x8d55db35 0xe6877ddd>;
			rsa,exponent = <0x00 0x10001>;
			rsa,n0-inverse = <0x5ca53d8b>;
			rsa,num-bits = <0x800>;
			required = "conf";
			algo = "sha1,rsa2048";
			key-name-hint = "boot_key";
		};
	};

linux kernel authentication steps:

# command to start LINUX from uboot
# load itb file
fatload mmc 0:1 0x80000000 itb_file
# call bootm
bootm 0x80000000

# the call stack of bootm
bootm  (cmd/bootm.c)
do_bootm  (cmd/bootm.c)
do_bootm_states (common/bootm.c)
bootm_find_os (common/bootm.c)
boot_get_kernel (common/bootm.c)
fit_image_load (common/image-fit.c)
fit_config_verify (common/image-sig.c)
fit_config_verify_required_sigs (common/image-sig.c)
fit_config_verify_sig (common/image-sig.c)
fit_config_check_sig (common/image-sig.c)

in fit_config_check_sig
// call fit_image_setup_verify to get crypto/has settting
// call crypto->verify to verify the signature

currently uboot provides the RSA verification alog.

struct checksum_algo checksum_algos[] = {
	{
		.name = "sha1",
		.checksum_len = SHA1_SUM_LEN,
		.der_len = SHA1_DER_LEN,
		.der_prefix = sha1_der_prefix,
		.calculate = hash_calculate,
	}
};

struct crypto_algo crypto_algos[] = {
	{
		.name = "rsa2048",
		.key_len = RSA2048_BYTES,
		.sign = rsa_sign,
		.add_verify_data = rsa_add_verify_data,
		.verify = rsa_verify,
	}
}
struct padding_algo padding_algos[] = {
	{
		.name = "pkcs-1.5",
		.verify = padding_pkcs_15_verify,
	}
};
they are defined in common/lib/rsa/rsa_verify.c, rsa_sign.c

RSA verify retrieves the public key from bootloader device tree blob 
and call rsa_verify to verify the signture. 

This RSA verification is pure software. we can take advantage of HSE on S32g, either use prev-loaded public key or import the public key from device tree and call HSM service to verify the signature.

最后更新于