i.MX8 AHAB secure boot porting guide

背景

本文将介绍NXP的AHABHAB机制以及差异,详细说明如何一步步使用CST工具对镜像进行签名以及验签的过程。


NXP AHAB介绍(i.MX8使用)

资料来源u-boot/doc/imx/ahab/introduction_ahab.txt
AHAB认证基于数字签名,其中使用一个或多个private key离线对镜像数据进行签名。然后使用相应的public key在i.MX处理器上验证所得到的签名镜像数据。public key包含在最终二进制文件中,SRK hash在SoC的fuse中(OTP),用于建立信任根(确认SRK是否一致)。
这里面涉及到的private keypublic key都是在CST工具中生成,CST在这里可以认为是一个CA。i.MX8 secure boot流程:

i.MX8 secure boot流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1  - At reset, the SCU ROM and SECO ROM both start execution.
2 - The SCU ROM reads the boot configuration and loads the SECO FW (First
container) from the boot media to the SECO TCM.
3 - A message is sent by the SCU ROM via MU requesting the SECO ROM to
authenticate the SECO FW which is signed using NXP key.
4 - The SCU ROM loads the second container from the boot media, this container
must contain at least the SCFW which is signed using the OEM keys.
5 - The SCU ROM loads the SCFW to the SCU TCM, a message is sent via MU
requesting the SECO FW to authenticate the SCFW and DCD table.
6 - The SCU ROM configures the DDR and loads the M4 and AP images included in
the second container to their respective load addresses.
7 - The SCU ROM request the SECO FW to authenticate the M4 image.
8 - The SCU ROM request the SECO FW to authenticate the AP image. This image
is the initial AP core software, depending in the U-Boot target it can
be the U-Boot and ATF or only SPL.
9 - The SCFW is initialized and starts the ARM Cortex-M and Cortex-A cores.
10 - From this point additional containers can be loaded by Cortex-M and
Cortex-A cores and authenticated by SECO, the AP SW must interface with
SCU by calling the sc_misc_seco_authenticate() API function. In current
U-Boot implementation the additional image can be the Linux Kernel binary
or the U-Boot proper and ATF. Details about current U-Boot implementation
can be found in AHAB guides included in doc/imx/ahab/guides/ directory.

NXP HAB介绍(i.MX7以下的使用)

根据NXP官方文档:Secure Boot on i.MX 50, i.MX 53, i.MX 6 and i.MX 7 Series using HABv4 ,我们可以研究一下HAB是个什么东西。

官方定义

1
2
3
4
5
6
Executing trusted and authentic code on an applications processor starts with securely booting the device.
The i.MX family of applications processors provides this capability
with the High Availability Boot (HAB) component of the on-chip ROM.
The ROM is responsible for loading the initial program image from the boot medium.
HAB enables the ROM to authenticate the program image by using digital signatures.
This initial program image is usually a bootloader.

官方术语

  • CA(Certificate Authority):持有private key并对public key签名生成数字证书
  • CAAM(Cryptographic Acceleration and Assurance Module):用于加密,流密码和散列算法的加速器,使用随机数生成器和运行时完整性检查程序;
  • CSF(Command Sequence File):由HAB解释的二进制数据结构,用于指导身份验证操作;
  • CST(Code Signing Tool):在构建主机上运行的应用程序,用于生成CSF和相关的数字签名,产生NXP所需要的SRK等;
  • HAB(High Assurance Boot):启动时在NXP处理器的内部ROM中执行的软件库,通过CSF验证数字签名来验证外部存储器中的软件;
  • OTP(One-Time Programmable):OTP硬件包括屏蔽ROM和电可编程保险丝(eFuse),只能烧写一次,不可改变;
  • PKI(Public Key Infrastructure):公钥证书的层次结构,其中每个证书(根证书除外)都可以使用其上方的公钥进行验证;
  • SRK(Super Root Key)一个RSA密钥对(SRK公钥和秘钥),它构成了启动时认证链的起点。SRK公钥的散列使用OTP硬件嵌入在处理器中。 SRK私钥由CA持有。

HAB身份验证过程

HAB身份验证基于使用RSA算法加密的public key,验证镜像数据,使用一系列private key对镜像数据在安全的环境中进行脱机签名。然后在i.MX处理器上使用相应的public key(SRK)验证所得到的签名镜像数据。
i.MX HAB验签流程

在上图中:
1、在安全的环境中对SW Image内容hash化生成摘要A,然后使用private key摘要A进行签名(采用RSA算法),得到SW ImageSignature
2、将该SW ImageSignature烧录到flash中后去启动;
3、在启动的时候会将SW Image内容hash化生成摘要B(如果SW Image没有被修改过,摘要A摘要B肯定相等),使用Fuse中的public key进行对Signature进行验签得到摘要C,如果摘要B摘要C相等,表示认证成功,就去启动OS。

注意,这里i.MX处理器中芯片存储的是SRK,而不是hash化后的值,所以该SRK可以直接进行验签。


HAB和AHAB

HAB Libraryboot rom code中的一个子模块,AHAB是某些特定的NXP处理器中的安全子系统。他们负责验证作为产品软件一部分的数字签名,并确保当处理器配置为安全设备时,不允许运行未经身份验证的代码。

使用HAB的启动流程

对于HAB,引导加载程序映像包含引导加载程序本身以及:HAB用于验证映像的命令,数字签名数据和public key数字证书数据,统称为命令序列文件(CSF)数据,使用代码签名工具(CST)离线生成CSF数据。

HAB流程

使用AHAB(SECO)的启动流程

AHAB流程


使用CST工具进行数字签名

可以在IMX_CST_TOOL 下载CST工具,该工具用于对HAB和AHAB进行代码签名。

  • CST输入文件:
    要签名的Image镜像 + CSF文件(CSF文件提供了一系列指令给CST,比如说数据镜像从哪里开始签名,使用哪个key去签名)
  • CST输出文件:
    Image镜像 + 数字签名 + CSF文件(该文件只有HAB有)。

cst工具

CST目录结构

  • ca\:包含OpenSSL配置文件。 使用OpenSSL命令行工具生成签名密钥和证书时,将使用这些配置文件;
  • crts\:包含用于签名的public key证书,最初此目录为空;
  • linux32/linux64/:包含CST工具执行的文件。bin/cst用于CST执行对代码签名;bin/srktool为HAB4和AHAB生成SRK表和e-fuse文件;
  • keys/:包含用于签名的private key,最初时候此目录只包含生成PKI tree的脚本,格式如下:

包含的脚本如下:
habx_pki_tree.sh/.bat脚本,其中x为3或者4,该脚本有Linux和Windows两种,都是用于生成支持HABx所需要的一系列密钥和证书;
ahab_pki_tree.sh/.bat脚本,该脚本有Linux和Windows两种,都是用于生成支持AHAB所需要的一系列密钥和证书;


一步步porting security boot

生成PKI tree

主要生成private keypublic key 数字证书,生成的PKI tree包含4个SRK
csf文件中会指定使用哪个SRK,签名后会往container中相应字段的值写入,这样的话在读取到container head之后就可以根据这个值来判断使用fuse的哪个SRK。
那为什么要用4个呢?通常情况下,可以让不同的批次指定不同的SRK。或者是同一个SRK永久了,可以指定换另外一个SRK。废弃掉的SRK可以在csf文件中使用Revocations来指定废弃哪个。
csf文件用例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[Header]
Target = AHAB
Version = 1.0

[Install SRK]
# SRK table generated by srktool
File = "./release/crts/SRK_1_2_3_4_table.bin"
# Public key certificate in PEM format
Source = "./release/crts/SRK1_sha384_secp384r1_v3_usr_crt.pem"
# Index of the public key certificate within the SRK table (0 .. 3)
Source index = 0
# Type of SRK set (NXP or OEM)
Source set = OEM
# bitmask of the revoked SRKs
Revocations = 0x0

[Authenticate Data]
# Binary to be signed generated by mkimage
File = "flash_os.bin"
# Offsets = Container header Signature block (printed out by mkimage)
Offsets = 0x0 0x90

我对SRK可以理解为private keypublic key certificates,前者用于对镜像进行签名或者是对public key进行加密生成数字证书。使用以下命令生成PKI tree

1
2
3
# tar -zxvf cst-3.1.0.tgz
# cd release/keys
# ./ahab_pki_tree.sh

生成的PKI tree结构如下,不带SGK。运行结果如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This script is a part of the Code signing tools for NXP's
Advanced High Assurance Boot. It generates a basic PKI tree. The
PKI tree consists of one or more Super Root Keys (SRK), with each
SRK having one subordinate keys:
+ a Signing key (SGK)
Additional keys can be added to the PKI tree but a separate
script is available for this. This this script assumes openssl
is installed on your system and is included in your search
path. Finally, the private keys generated are password
protectedwith the password provided by the file key_pass.txt.
The format of the file is the password repeated twice:
my_password
my_password
All private keys in the PKI tree are in PKCS #8 format will be
protected by the same password.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Do you want to use an existing CA key (y/n)?: n
Do you want to use Elliptic Curve Cryptography (y/n)?: y
Enter length for elliptic curve to be used for PKI tree:
Possible values p256, p384, p521: p384
Enter the digest algorithm to use: sha384
Enter PKI tree duration (years): 5
Do you want the SRK certificates to have the CA flag set? (y/n)?: n
A default 'serial' file was created!
A default file 'key_pass.txt' was created with password = test!

+++++++++++++++++++++++++++++++++++++
+ Generating CA key and certificate +
+++++++++++++++++++++++++++++++++++++

Generating a 384 bit EC private key
writing new private key to 'temp_ca.pem'
-----

++++++++++++++++++++++++++++++++++++++++
+ Generating SRK key and certificate 1 +
++++++++++++++++++++++++++++++++++++++++

read EC key
writing EC key
Using configuration from ../ca/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'SRK1_sha384_secp384r1_v3_usr'
Certificate is to be certified until Mar 24 06:47:01 2024 GMT (1825 days)

Write out database with 1 new entries
Data Base Updated

++++++++++++++++++++++++++++++++++++++++
+ Generating SRK key and certificate 2 +
++++++++++++++++++++++++++++++++++++++++

read EC key
writing EC key
Using configuration from ../ca/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'SRK2_sha384_secp384r1_v3_usr'
Certificate is to be certified until Mar 24 06:47:01 2024 GMT (1825 days)

Write out database with 1 new entries
Data Base Updated

++++++++++++++++++++++++++++++++++++++++
+ Generating SRK key and certificate 3 +
++++++++++++++++++++++++++++++++++++++++

read EC key
writing EC key
Using configuration from ../ca/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'SRK3_sha384_secp384r1_v3_usr'
Certificate is to be certified until Mar 24 06:47:01 2024 GMT (1825 days)

Write out database with 1 new entries
Data Base Updated

++++++++++++++++++++++++++++++++++++++++
+ Generating SRK key and certificate 4 +
++++++++++++++++++++++++++++++++++++++++

read EC key
writing EC key
Using configuration from ../ca/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'SRK4_sha384_secp384r1_v3_usr'
Certificate is to be certified until Mar 24 06:47:01 2024 GMT (1825 days)

Write out database with 1 new entries
Data Base Updated

生成SRK tableSRK hash

  • 输入文件是在上一个步骤中创建的public key certificates
  • 输出文件是SRK tableSRK hash

通过CAprivate keypublic key certificates进行解密就可以拿到可以对镜像认证的public key

在AHAB架构中:

  • SRK table就是一系列的public key证书,SRK table会打包到已签名的镜像中;
  • SRK hashSRK table hash化生成的数字摘要,会被烧写到i.MX芯片的SOC SRK_HASH[511:0] OTP中;

在认证过程期间的目标设备上,AHAB代码(SECO)会将镜像中的SRK table hash化然后与SoC SRK_HASH中的SRK hash比较,如果相等,则说明用于验签的public key是正确的,AHAB代码可以用该public key进行后续的镜像认证。对于SRK table中未使用的4个密钥中的任何一个,相应的密钥位将设置为0。后续的镜像认证,就是完全按照HAB的过程来了。

为什么生成SRK table后还要生成SRK hash呢?主要原因是:

  • 由于OTP空间小,将public key hash化之后,可以减小存储空间;
  • 为了防止public keyprivate key被替换。假设有个图谋不轨的人,使用CST生成private key对自己的镜像签名,然后再将public key加入到镜像中,镜像中的public key被hash化后肯定不与fuse中的SRK hash不一致,因此无法验签通过。
1
2
3
4
5
6
7
# cd ../crts/
# ../linux64/bin/srktool -a -s sha384 -t SRK_1_2_3_4_table.bin \
-e SRK_1_2_3_4_fuse.bin -f 1 -c \
SRK1_sha384_secp384r1_v3_usr_crt.pem,\
SRK2_sha384_secp384r1_v3_usr_crt.pem,\
SRK3_sha384_secp384r1_v3_usr_crt.pem,\
SRK4_sha384_secp384r1_v3_usr_crt.pem

各个参数含义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  -a, --ahab_ver:
AHAB Version - set for AHAB SRK table generation

-s, --sign_digest <digestalg>:
Signature Digest algorithm. Either sha256, sha384 or sha512

-t, --table <tablefile>:
Filename for output SRK table binary file

-e, --efuses <efusefile>:
Filename for the output SRK efuse binary file containing the SRK table hash

-f, --fuse_format <format>:
Optional, Data format of the SRK efuse binary file. The
format may be selected by setting <format> to either:
- 0: 8 fuses per word, ex: 00 00 00 0a 00 00 00 01 ...
- 1 (default): 32 fuses per word, ex: 0a 01 ff 8e

-c, --certs <srk1>,<srk2>,...,<srk4>:
X.509v3 certificate filenames.
- Certificates may be either DER or PEM encoded format
- Certificate filenames must be separated by a ','with no spaces
- A maximum of 4 certificate filenames may be provided. Additional
certificate names are ignored

用户可以使用如下命令验证生成的SRK tableSRK hash的sha256sum是否一致。

1
2
3
4
5
6
7
8
9
# od -t x4 --endian=big SRK_1_2_3_4_fuse.bin
0000000 5d46e030 479c8368 3a73a270 90584918
0000020 30ae00fa 74f9e41b 5c99b7b6 0c6ce7a3
0000040 782ffb59 705f0e1a ae15667a 75bddf53
0000060 d27f2290 fc079e18 f2f38eaa 4b3baaa5
0000100

# sha512sum SRK_1_2_3_4_table.bin
5d46e030479c83683a73a2709058491830ae00fa74f9e41b5c99b7b60c6ce7a3782ffb59705f0e1aae15667a75bddf53d27f2290fc079e18f2f38eaa4b3baaa5 SRK_1_2_3_4_table.bin

对镜像签名

将镜像和csf文件拷贝到cst目录下,按照csf要求对镜像进行签名。其中使用mkimage生成flash.bin的时候会打印如下log,csf_boot_image.txt文件中的offset字段必须根据这个log的内容做相应的修改。csf文件用于指定从哪块区域的image去验证,使用哪个key去验证。

1
2
3
4
CST: CONTAINER 0 offset: 0x400
CST: CONTAINER 0: Signature Block: offset is at 0x590
DONE.
Note: Please copy image to offset: IVT_OFFSET + IMAGE_OFFSET

对镜像签名命令如下,生成flash.signed.bin的签名文件。

1
2
3
4
# cd ../../
# cp -rf ~/work2/xxx/uboot-imx/flash.bin ./
# cp -rf ~/work2/xxx/uboot-imx/doc/imx/ahab/csf_examples/csf_boot_image.txt ./
# ./release/linux64/bin/cst -i csf_boot_image.txt -o signed-flash.bin

烧写SRK fuse到soc中

执行如下命令,获取到烧写fuse的值:

1
2
3
4
5
6
# od -t x4 SRK_1_2_3_4_fuse.bin
0000000 475e1dca ec5c98d2 6dd5b7ec da535b48
0000020 5baa6f61 9d788292 27f53d5f 1316752a
0000040 01043451 7578275d c5fcd1e1 12bac3e2
0000060 ef6860a2 a0a12501 bc2b9c25 cfeea329
0000100

因此,烧写fuse的值为(只针对i.MX8QXP),可以在uboot命令行中使用fuse命令进行烧写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fuse prog 0 730 0x475e1dca
fuse prog 0 731 0xec5c98d2
fuse prog 0 732 0x6dd5b7ec
fuse prog 0 733 0xda535b48
fuse prog 0 734 0x5baa6f61
fuse prog 0 735 0x9d788292
fuse prog 0 736 0x27f53d5f
fuse prog 0 737 0x1316752a
fuse prog 0 738 0x01043451
fuse prog 0 739 0x7578275d
fuse prog 0 740 0xc5fcd1e1
fuse prog 0 741 0x12bac3e2
fuse prog 0 742 0xef6860a2
fuse prog 0 743 0xa0a12501
fuse prog 0 744 0xbc2b9c25
fuse prog 0 745 0xcfeea329

烧写fuse的原理如下: https://imxdev.gitlab.io/tutorial/Burning_eFuses_on_i.MX8_and_i.MX8x_families/
fuse烧录原理

验证签名的boot镜像是否认证成功

将第3步生成的签名镜像flash.signed.bin烧写到板子上,从板子启动。
在最新的imx_v2018.03_4.14.98_2.0.0_ga分支上,无需通过scu的串口来查看。直接在uboot命令行中使用ahab_status就可以确定是否验证成功。


配置SCFW支持debug monitor

配置SCFW如下几个功能:

  • 如果使用板子上使用AF28(SCU.UART0.RX)AH30(SCU.UART0.TX)做为SCU的串口,那么必须在platform/board/mx8qx_mek/board.c文件中打开ALT_DEBUG_SCU_UART宏,否则就是使用到M4 UART;
  • 编译scfw_tcm.bin的时候使用make qx B=mek V=1 R=B0 M=1 D=1 DL=2命令,M=1表示打开debug monitor功能,也就是可以通过串口与SCFW交互,D=1表示打开debug功能,DL=2表示debug level。

详细的可以参考[System Controller Firmware Porting Guide.pdf]和[sc_fw_port.pdf]下面的debug monitor的功能:


OS镜像签名

将kernel编译出来的Image.dtb文件拷贝到imx-mkimage环境中,这个可以从 imx-mkimage 下载。假定目前处于imx-mkimage环境下。

1、拷贝所需要的镜像和dtb

1
2
# cp -rf ~/work2/xxx/kernel-imx/arch/arm64/boot/Image ./iMX8QX/
# cp -rf ~/work2/xxx/kernel-imx/arch/arm64/boot/boot/dts/freescale/xxxxx.dtb ./iMX8QX/

2、修改soc.mk为:

1
2
flash_linux flash_b0_linux: $(MKIMG) Image xxxxx.dtb
./$(MKIMG) -soc QX -rev B0 -c -ap Image a35 0x80280000 --data xxxxx.dtb 0x83000000 -out flash_os.bin

3、编译生成OS镜像的flash_os.bin 镜像拷贝到cst目录下。

1
2
# make SOC=iMX8QX flash_linux
# mv i.MX8QX/flash_os.bin ~/work2/xxx/cst/

4、拷贝OS镜像签名所需的csf文件csf_linux_img.txt

5、修改csf_linux_img.txt文件中的offset字段。

6、在cst目录下对flash_os.bin进行签名:

1
# ./release/linux64/bin/cst -i csf_linux_img.txt -o os_cntr_signed.bin


SPL(Secondary Program Loader)的特殊处理

SPL被用于在初始化ARM ATF和u-boot之前初始化引导程序。u-boot中支持AHAB功能,这个功能对于完全验证flash.bin至关重要。
在SPL目标上,只有SCFW,SPL,M4镜像在SCU ROM阶段验证。为了验证ATF和U-boot,必须在SPL阶段调用sc_misc_seco_authenticate()进行验证。

包含SPL的启动镜像

包含SPL的镜像包含3个container,如下:

  • 第1个container只包含SECO FW,NXP签名,在SCU ROM阶段使用SECO ROM验证;
  • 第2个container包含SCFW,SPL,M4镜像,这些由OEM签名,在SCU ROM阶段使用SECO FW验证;
  • 第3个container包含u-boot和ATF,SPL负责load这个container,和使用接口通过SCU发送命令给SECO FW对container进行验证;
    带spl镜像处理

对包含SPL的镜像签名

对包含SPL的镜像签名

(1)、编译生成第3个container镜像:

1
make SOC=iMX8QX u-boot-atf-container.img

编译的log如下:

1
2
3
4
AP file_offset = 0x91800 size = 0x4d800
CST: CONTAINER 0 offset: 0x0
CST: CONTAINER 0: Signature Block: offset is at 0x190
DONE.

(2)、对第3个container签名:
a. 在cst中创建csf_uboot_atf.txt文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[Header]
Target = AHAB
Version = 1.0

[Install SRK]
# SRK table generated by srktool
File = "./release/crts/SRK_1_2_3_4_table.bin"
# Public key certificate in PEM format
Source = "./release/crts/SRK1_sha384_secp384r1_v3_usr_crt.pem"
# Index of the public key certificate within the SRK table (0 .. 3)
Source index = 0
# Type of SRK set (NXP or OEM)
Source set = OEM
# bitmask of the revoked SRKs
Revocations = 0x0

[Authenticate Data]
# Binary to be signed generated by mkimage
File = "u-boot-atf-container.img"
# Offsets = Container header Signature block (printed out by mkimage)
Offsets = 0x0 0x190

b. 对镜像进行签名

1
./release/linux64/bin/cst -i csf_uboot_atf.txt -o signed-u-boot-atf-container.img

将生成的signed-u-boot-atf-container.img拷贝到imx-mkimage目录中重新打包,并重命名为u-boot-atf-container.img

c、编译生成flash.bin镜像

1
make SOC=iMX8QX flash_spl_container

编译的log如下:

1
2
3
4
5
CST: CONTAINER 0 offset: 0x400
CST: CONTAINER 0: Signature Block: offset is at 0x510
DONE.
Note: Please copy image to offset: IVT_OFFSET + IMAGE_OFFSET
append u-boot-atf-container.img at 258 KB

d、对flash.bin镜像签名
将生成的flash.bin镜像拷贝到cst目录中签名。

1
./release/linux64/bin/cst -i csf_boot_image.txt -o signed-flash.bin

带SPL和不带SPL签名的差异

  • 带SPL的镜像总共有3个container,不带SPL只有2个container;
  • 带SPL的镜像需要将第3个container(u-boot + ATF)先签名,然后将签名后的镜像再跟第2个container(SCFW,SPL,M4镜像)打包再一起再进行签名最终生成flash.bin镜像。

参考资料

i.MX High Assurance Boot (HAB) / Secure Boot
mx8_mx8x_secure_boot.txt
mx8_mx8x_spl_secure_boot.txt
introduction_ahab.txt
CAAM测试程序
i.MX HAB介绍
High Assurance Boot (HAB) for dummies

Title:i.MX8 AHAB secure boot porting guide

Author:Victor Huang

Time:2020-08-02 / 12:08

Link:http://wowothink.com/258082eb/

License: Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)