SECURITY_BOOT使用参考¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.00 | 05/29/2024 | |
| 1.10 | 05/26/2025 | |
| 1.20 | 08/18/2025 |
1. SECURITY BOOT介绍¶
1.1. 概述¶
Security Boot需要做的工作总体上包括签章(或加密+签章)和验签(或验签+解密)两大部分,验签即签章的验证,其中加密和解密为可选,用户可根据自身需求取舍。
一般情况下加密是为了防止信息被泄露,而验签是为了防止信息被篡改。加密(详见1.7. 加密Security Boot流程章节)和签章(详见3.6. IPL.bin 签章部分)的工作将使用脚本完成,而验签和解密的工作将由固件中Software完成。Security Boot的验签和解密总体流程如下。

图1 验签和解密总体流程
1.1.1. 秘钥介绍¶
从秘钥使用的角度看,签章和验签分别使用了RSA Private Key和RSA Public Key,加密和解密使用同一把AES Key。
-
验签流程中所用的
RSA Public Key有两把。第一把为
OTP Key,该把Key会在系统Power On后,Hardware会自动从OTP中载入,用来做签章验证的动作,这边Software是无法介入的。而OTP Key的内容,可以通过Linux Tool或U-Boot的Command Line烧录至OTP的指定地址中。第二把为
CUST Key,该Key会嵌在IPL和IPL_CUST的bin文件中,通过Software在整个boot flow中用来做签章验证的动作。 -
验签流程中所用的
AES Key为OTP Key,该把Key使用之前需要烧录到OTP存储单元中,在使用的时候,由Hardware载入到crypto engine进行使用,可以在整个boot flow中用来做AES解密的动作。OTP AES Key的内容由用户自定义,所以由用户维护。
1.1.2. 流程介绍¶
-
Authenticate IPL by OTP Key-RSA
该流程为ROM code从OTP中读取RSA Public Key后,对IPL进行签章的验证,如图1的步骤1。由于OTP的RSA Public Key可以进行Write Lock动作(后面章节会详细提及),阻止再次被写,所以OTP的RSA Public Key可以做到不被替换,从而保证了IPL不会被篡改。
-
Authenticate IPL_CUST by IPL's CUST Key-RSA
该流程为IPL读取事先嵌在IPL的CUST RSA Public Key后,对IPL_CUST进行签章的验证,如图1的步骤3。由于IPL不会被篡改,所以保证了嵌在IPL的CUST RSA Public Key不会被篡改,从而保证了IPL_CUST也不会被篡改。
-
Authenticate U-Boot/kernel by IPL_CUST's CUST Key-RSA
该流程为IPL_CUST读取事先嵌在IPL_CUST的CUST RSA Public Key后,对U-Boot进行签章的验证,如图1的步骤6。同样U-Boot也读取这把Key对下一阶段的Linux Kernel进行签章验证,如图1的步骤8和10。
-
Decrypt U-Boot/kernel by OTP Key–AES
如果开启加密机制,U-Boot及Linux Kernel会通过AES128(ECB)来做加密动作,在Boot流程中,ROM使用OTP中事先烧录好的AES Key对U-Boot或者riscV执行解密动作,同样U-Boot也对Linux Kernel执行解密动作,如图1的步骤2、5、7、9、11。
1.2. OTP RSAKey/AESkey¶
OTP Key相应的地址空间只能烧写一次,此外,OTP Key带有Write Lock功能,来防止OTP Key被非法篡改(烧写OTP Key及其Lock相关内容后面章节会提及)。
1.2.1. OTP RSA Key¶
OTP Key为ROM code用来验证IPL的签章所使用的RSA Public Key,由N-key及E-key组成,需通过Linux Tool或在Uboot下预先烧录到OTP中。在开机时,则会由Hardware自动载入。
1.2.2. OTP AES Key¶
OTP AES Key长度为128bit,若使用"签章+加密"则会用到OTP AES Key,需要在使用之前就将Key烧录于OTP存储单元中(烧写OTP AES Key相关内容后面章节会提及)。
1.3. CUST Key¶
CUST Key即RSA Public Key(RSA-2048/RSA-4096,长度为2048或4096bit),在签章过程中,IPL的bin文件和IPL_CUST的bin文件都会嵌入RSA Public Key,bin文件组成结构变化情况分别如下图。
1.3.1. IPL结构¶

图2 IPL结构
1.3.2. IPL_CUST结构¶

图3 IPL_CUST结构
1.4. Boot Flow结构¶
Boot Flow请参考下图,该图为从ROM到Linux Kernel的Boot Flow结构,其中Signature为签章数据部分,每个Flow的Signature均会嵌入到相应bin文件的最后,每个Flow均包含Get Key和Authenticate的动作直到Linux Kernel,部分Flow支持解密(是否开启解密取决于需求);append 数据包含当前image加密信息,内容详见6.2. Header version description章节。Get Key有三种,OTP RSA Key和OTP AES Key均由Hardware获取,CUST RSA Key由Software获取。需要注意的是IPL_CUST是Insert CUST RSA Key后才进行签章的,所以其Signature嵌入在CUST RSA Key后面。

图4 Boot Flow结构
1.5. OTP开启Security Boot¶
当烧录完OTP Key后,真正启动Security Boot必须要烧录OTP_Secure_Boot相应的Register栏位(OTP烧录方法后面章节会详细提及),将该栏位烧录为0xFF,则会启动OTP的Security Boot。
(注:开启后无法关闭,每次启动都将会强制走Security Boot flow,normal boot将无法再启动,谨慎烧写!)
1.6. 普通Security Boot流程¶
如下所示,以rsa2048为例,Generate Signature是在local端执行,这部分目前方案是使用Python脚本完成(后面章节会详细提及),先对Image file进行SHA-256的计算,生成Digest,再通过RSA-2048做加密动作,最后生成256Bytes的signature。在生成signed image file的时候先插入append data(内容详见6.2. Header version description),再将signature嵌入至Image后端。
Verify Signature是在boot flow中执行,各阶段的boot code会对下一段的Image进行SHA-256计算,生成Digest,并取出signature来做RSA-2048的解密生成Digest',然后对比Digest和Digest',若对比一致,则Verify success,否则Verify fail。

图5 普通Security Boot流程
1.7. 加密Security Boot流程¶
如下所示,Generate Signature是在local端执行,这部分目前方案是使用Python脚本完成(后面章节会详细提及),一开始会先将Image file通过AES-128(ECB)加密成Cipher file,再对Cipher file + append进行SHA-256计算,生成Digest,再通过RSA-2048做加密动作,最后生成256Bytes的signature。在生成signed image file的时候先插入append data(内容详见6.2. Header version description),再将signature嵌入至Image后端。
Verify Signature是在boot flow中,各阶段的boot code会对下一段的Image进行SHA-256计算,生成Digest,并取出Signature来做RSA-2048的解密后,生成Digest',最后对比Digest和Digest'。如对比成功,则对Cipher file进行AES-128(ECB) 解密的动作,最后解密为能开机的image。

图6 加密Security Boot流程
1.8. SDK规格¶
各个阶段加签、加密的支持规格。
| STAGE | AES_MODE | AESKEY_LEN(BIT) | RSAKEY_LEN(BIT) |
|---|---|---|---|
| ROM->IPL | 不支持 | 不支持 | 2048/4096 |
| IPL->IPL_CUST | 不支持 | 不支持 | 2048/4096 |
| IPL_CUST->BOOT / IPL_CUST->RISCV | ECB/CBC/CTR | 128/256 | 2048/4096 |
| BOOT->KERNEL | ECB/CBC/CTR | 128/256 | 2048/4096 |
| BOOT->ROOTFS | ECB/CBC/CTR | 128/256 | 2048/4096 |
在启用RISCV时,IPL_CUST开启RSA解签,UBOOT和RISCV都需要使用 同一把KEY 加签。
1.9. UBOOT/KERNEL SZ IMAGE签章¶
Sigmastar分区layout中,有一些分区镜像默认是不支持压缩的,有一些分区镜像默认是支持xz或者sz压缩。
不压缩:
IPL/IPL_CUST/VMM/TF-A/TEE/PM_RTOS
既支持xz又支持sz压缩:
uboot/kernel/rtos/ramfs
XZ 压缩或者不压缩的Image方案的签章+加密的FLOW:

XZ压缩/不压缩方案的 image只有一层header,加载和验签过程:从flash load xz镜像到 ddr -> 验签xz尾部的256/512字节签名数据 -> CPU解压xz镜像 成 binary(如果有压缩)-> 运行。
SZ压缩的Image方案的签章+加密的FLOW:

sbot header是专门为签章加的header识别,其中所含的name字段代表关键字“sbot”,目的为指示该image为带签章的binary。
SZ压缩方案的image有两层header:xzdec硬件解压边load sz边解压到ddr -> 验签binary镜像尾部的256/512字节数据 -> 运行。
SZ压缩方案需要两层header原因是:XZDEC在验签和加密前做解压,解压需要从Header_2获取到解压size。验签需要从Header_1获取到解压后的镜像size。
需要注意的是:
- Header2中的所有数据都是不安全的,Header1中的数据经过验签是安全的。所以如果是SIG or SIG+AES方案,则验签成功后,取H1的Load/RUN addr进行下一步动作。
- Header2必须加的原因是UBOOT解压时,需要用到size & CRC等数据。
- SZ方案解压缩后的文件,结构和XZ方案一样,解密验签flow没有差别。
2. OTP Key读写操作说明¶
2.1. 生成 RSA Key¶
通过openssl来生成RSA Key。相关的命令操作,请参考如下:
-
Generate Private Key
openssl genrsa -out private.pem 2048 -
Generate Public Key
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
2.2. 使用U-BOOT烧录OTP¶
注:OTP只能烧写一次,一旦烧写则无法清除和重烧,请在确认需要的场合下执行烧写动作!
2.2.1. 生成U-Boot Command Scripts¶
通过Tool (key_proc.py) 可产生U-Boot command scripts来方便通过U-Boot来将RSA-Public Key烧录至OTP指定位置上。
./key_proc.py --exportkey_reverse --rsa=public.pem
exportkey: 将public.pem 转换成rsaKey.bin的binary file
exportkey_reverse: 将public.pem 转换成rsaKey.bin的binary file,并反序rsaKey.txt的data顺序
rsa: 输入openssl所生成的public key (public.pem)
执行该command后会生成的文件如下:
-
rsaKey.bin——RSA Public N-Key binary file
-
rsaKey.txt——Otp Command List for write RSA Public N-Key rsaKey.txt,会列出烧录Key的Uboot command list,可以直接使用该command list来进行烧录。
注:RSA N-Key有4行command,要分四次执行,不可一次执行4行。
rsaKey.bin:

rsaKey.txt:

2.2.2. 启动Secure Boot¶
通过烧录OTP中的Secure Boot的栏位来启动Secure boot功能,一旦启动Secure Boot后,在ROM阶段就会开始进行IPL的签章验证。启动方式可通过烧录OTP_SECURE_BOOT (0x2)。
这边需确认是否有正确开启Secure Boot,在未开启前,其Boot行为如下:
-
[普通安全boot流程] Boot flow不会对签章进行验证,所以是可以完成整个Boot流程。
-
[加密安全boot流程] Boot flow不会对签章进行验证,也不会对Image进行解密,所以会无法正常开机。
2.3. OTP Command Format¶
如下图,列出在UBOOT下执行OTP烧录的两个COMMAND,分别能对OTP进行读写的动作。
WRITE COMMAND:

READ COMMAND:

2.4. OTP Command Support List for IC Pcupid¶
2.4.1. RSAkey/AESKEY¶
注:以下RSA/AES key所有的例子中的otpctrl -w仅限在uboot下执行。
2.4.1.1. OTP_RSA_N (0x0)¶
该Command被使用来存取OTP中的RSA Public N-Key,总共包含512-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。Pcupid支持RSA2048/4096。
需要注意Pcupid OTP中N Key的顺序与以往不同,需要使用以下cmd生成rsaKey.txt,使用rsaKey.txt中的command在UBOOT下烧写OTP
./key_proc.py --exportkey_reverse --rsa=public.pem
WRITE COMMAND:
otpctrl -w 0x0 offset writedata

READ COMMAND:
otpctrl -r 0x0

2.4.1.2. OTP_RSA_E (0x1)¶
该Command被使用来存取OTP中的RSA Public E-Key,总共包含4-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效(此处与其他 IC 不一致)。
WRITE COMMAND:
otpctrl -w 0x1 0x0 0x00010001
READ COMMAND:
otpctrl -r 0x1

2.4.1.3. OTP_AES128_KEY (0x5~0x8)¶
该Command被使用来存取OTP中的AES Key,Pcupid共有4把AES128 KEY,一把key占有16-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
ALL AESKEY WRITE COMMAND:
-
KEY1
WRITE COMMAND:
otpctrl -w 0x5 offset writedataREAD COMMAND:
otpctrl -r 0x5Example:
制作AES KEY: echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey1.bin otpctrl -w 0x5 0x0 0x03020100 otpctrl -w 0x5 0x4 0x07060504 otpctrl -w 0x5 0x8 0x0B0A0908 otpctrl -w 0x5 0xC 0x0F0E0D0C -
KEY2
WRITE COMMAND:
otpctrl -w 0x6 offset writedataREAD COMMAND:
otpctrl -r 0x6Example:
制作AES KEY: echo '00112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey2.bin otpctrl -w 0x6 0x0 0x33221100 otpctrl -w 0x6 0x4 0x77665544 otpctrl -w 0x6 0x8 0xBBAA9988 otpctrl -w 0x6 0xC 0xFFEEDDCC -
KEY3
WRITE COMMAND:
otpctrl -w 0x7 offset writedataREAD COMMAND:
otpctrl -r 0x7Example:
制作AES KEY: echo '030102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey3.bin otpctrl -w 0x7 0x0 0x03020103 otpctrl -w 0x7 0x4 0x07060504 otpctrl -w 0x7 0x8 0x0B0A0908 otpctrl -w 0x7 0xC 0x0F0E0D0C -
KEY4
WRITE COMMAND:
otpctrl -w 0x8 offset writedataREAD COMMAND:
otpctrl -r 0x8Example:
制作AES KEY: echo '04112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey4.bin otpctrl -w 0x8 0x0 0x33221104 otpctrl -w 0x8 0x4 0x77665544 otpctrl -w 0x8 0x8 0xBBAA9988 otpctrl -w 0x8 0xC 0xFFEEDDCC -
KEY256_1
WRITE COMMAND:
otpctrl -w 0x5 offset writedata otpctrl -w 0x6 offset writedataREAD COMMAND:
otpctrl -r 0x5 otpctrl -r 0x6Example:
制作AES KEY: echo '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F' | xxd -r -ps > aesKey256_1.bin otpctrl -w 0x5 0x0 0x03020100 otpctrl -w 0x5 0x4 0x07060504 otpctrl -w 0x5 0x8 0x0B0A0908 otpctrl -w 0x5 0xC 0x0F0E0D0C otpctrl -w 0x6 0x0 0x13121110 otpctrl -w 0x6 0x4 0x17161514 otpctrl -w 0x6 0x8 0x1B1A1918 otpctrl -w 0x6 0xC 0x1F1E1D1C -
KEY256_2
WRITE COMMAND:
otpctrl -w 0x7 offset writedata otpctrl -w 0x8 offset writedataREAD COMMAND:
otpctrl -r 0x7 otpctrl -r 0x8Example:
制作AES KEY: echo '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F' | xxd -r -ps > aesKey256_2.bin otpctrl -w 0x7 0x0 0x03020100 otpctrl -w 0x7 0x4 0x07060504 otpctrl -w 0x7 0x8 0x0B0A0908 otpctrl -w 0x7 0xC 0x0F0E0D0C otpctrl -w 0x8 0x0 0x13121110 otpctrl -w 0x8 0x4 0x17161514 otpctrl -w 0x8 0x8 0x1B1A1918 otpctrl -w 0x8 0xC 0x1F1E1D1C
2.4.2. OTP_SECURE_BOOT (0x2)¶
该Command被使用来启动secure boot,设置为0xFF表示启动secure boot。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x2 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x2
2.4.3. OTP_RSA_KEY_LOCK (0x3)¶
该Command被使用来对OTP内的RSA Public Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的RSA Public Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x3 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x3
2.4.4. OTP_AES128_KEY_LOCK (0xD,0xF,0x11,0x13)¶
该Command被使用来对OTP内的AES Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
-
LOCK AESkey1
WRITE COMMAND:
otpctrl -w 0xD 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xD -
LOCK AESkey2
WRITE COMMAND:
otpctrl -w 0xF 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xF -
LOCK AESkey3
WRITE COMMAND:
otpctrl -w 0x11 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0x11 -
LOCK AESkey4
WRITE COMMAND:
otpctrl -w 0x13 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0x13
2.4.5. OTP_CUSTOMER_AREA (0xA0)¶
该区域一共有8K,开放给客户使用,以下是写OTP_CUSTOMER_AREA的cmd,需注意每次写4byte.offset最大为0x3fc。
WRITE COMMAND:
otpctrl -w 0xA0 offset writedata
READ COMMAND:
otpctrl -r 0xA0
Example:
WRITE COMMAND: otpctrl -w 0xA0 0x0 0x12345678
WRITE COMMAND: otpctrl -w 0xA0 0x4 0x09ABCDEF
WRITE COMMAND: otpctrl -w 0xA0 0x8 0x33445566
最后4byte WRITE COMMAND:
WRITE COMMAND: otpctrl -w 0xA0 0x3fC 0xAA778899
Uboot下可通过otpread cmd 读取customer area data,客户可模拟otpread process在uboot/kernel下读到customer area data。
2.4.6. OTP_CUSTOMER_AREA_LOCK(0xA1~0xA8)¶
该Command被使用来对OTP内的OTP_CUSTOMER_AREA栏位进行LOCK的动作。LOCK表示无法更改OTP内的OTP_CUSTOMER_AREA。在设置完该Command后,须于下次启动才会生效。
-
LOCK 0k~1K
WRITE COMMAND:
otpctrl -w 0xA1 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA1 -
LOCK 1k ~2K
WRITE COMMAND:
otpctrl -w 0xA2 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA2 -
LOCK 2k~3K
WRITE COMMAND:
otpctrl -w 0xA3 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA3 -
LOCK 3k~4K
WRITE COMMAND:
otpctrl -w 0xA4 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA4 -
LOCK 4k~5K
WRITE COMMAND:
otpctrl -w 0xA5 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA5 -
LOCK 5k~6K
WRITE COMMAND:
otpctrl -w 0xA6 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA6 -
LOCK 6k~7K
WRITE COMMAND:
otpctrl -w 0xA7 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA7 -
LOCK 7k~8K
WRITE COMMAND:
otpctrl -w 0xA8 0x0 0xFFFFFFFFREAD COMMAND:
otpctrl -r 0xA8
2.4.7. OTP_RSA_KEY_LEN(0x2F)¶
该Command被使用来配置RSA_KEY的长度,默认长度为2048bit,设置为0xFFFFFFFF表示在整个boot阶段都使用长度为4096bit的key。在设置完该Command后,须于下次启动才会生效。
若想设置为RSA4096验签,请烧此OTP
WRITE COMMAND:
otpctrl -w 0x2F offset writedata
READ COMMAND:
otpctrl -r 0x2F
Example:
WRITE COMMAND: otpctrl -w 0x2F 0x0 0xFFFFFFFF
2.4.8. ERROR CODE¶
FF01: 无效的COMMAND
FF02: 无效的OTP地址
FF03: 无效的OTP执行许可证
FF04: 分配的buf太小
FF05: 写otp失败,会有错误打印,可能的原因如下:
写入otp失败,写入的值和读到的值不同
预写的otp位置已使能写保护
预写入的otp位置已被写,返回失败
2.5. otpfactor指令自动烧录OTP¶
在uboot下支持使用otpfactor指令自动烧录secureboot相关的OTP栏位,需要自行修改uboot otpctrl.c中定义的数据,修改为需要烧录到OTP中的数据。
在otpfator的执行函数do_otpfactor()中,会先查看芯片中的Secureboot enable是否烧录,如果没有烧录,才会往下执行其他数据的烧录。如果不需要该逻辑,可自行修改注释。

2.5.1. 烧录RSA/ECC Key¶
由于OTP对烧录的密钥顺序有特殊要求,需要使用下面方法定义需要烧录的数据。
RSA2048/RSA4096
./key_proc.py --exportkey_reverse --rsa=private.pem
执行对应指令后会生成rsaKey_c_array.txt文件,该文件存放的是Public key的C语言数据的格式。将文件中的内容替换到otpctrl.c中已定义的rsa2048[256]/rsa4096[512]数组中。如下图
RSA2048:

RSA4096:

将 OTP_SIGN_ALG 宏修改为需要使用的对应算法

| SIGN ALG | ALG MICRO |
|---|---|
| RSA2048 | SIGN_ALG_RSA2048 |
| RSA4096 | SIGN_ALG_RSA4096 |
| SM2 | SIGN_ALG_SM2 |
| ECC256 | SIGN_ALG_ECC256 |
| ECC384 | SIGN_ALG_ECC384 |
| ECC512 | SIGN_ALG_ECC512 |
do_otpfactor()中会执行对应密钥的自动烧录,如下图代码。

另外,RSA key的锁读和锁写位的烧录如下代码,可自行开启。

2.5.2. 烧录AES Key¶
修改aeskey1~8数组中的数据:

将 OTP_ROM_SELECT_AES 宏修改为需要使用的对应的AES KEY

| AES KEY | AES KEY MICRO |
|---|---|
| AES128_1 | ROM_SELECT_AES128_KEY1 |
| AES128_2 | ROM_SELECT_AES128_KEY2 |
| AES128_3 | ROM_SELECT_AES128_KEY3 |
| AES128_4 | ROM_SELECT_AES128_KEY4 |
| AES128_5 | ROM_SELECT_AES128_KEY5 |
| AES128_6 | ROM_SELECT_AES128_KEY6 |
| AES128_7 | ROM_SELECT_AES128_KEY7 |
| AES128_8 | ROM_SELECT_AES128_KEY8 |
| AES256_1 | ROM_SELECT_AES256_KEY1 |
| AES256_2 | ROM_SELECT_AES256_KEY2 |
| AES256_3 | ROM_SELECT_AES256_KEY3 |
| AES256_4 | ROM_SELECT_AES256_KEY4 |
do_otpfactor()中会执行对应ROM SELECT AESKEY的自动烧录,并烧录8把aeskey,如下图代码。如不需要烧录8把aeskey,可自行注释相关代码行。

另外,aeskey的锁读和锁写位的烧录如下代码,可自行开启。

2.5.3. 烧录Secureboot enable¶
do_otpfactor()的最后会烧录Secureboot enable

3. 安全镜像生成¶
3.1. 概述¶
此功能依据用户需求可分成是否进行明文内容的加密,如下两种制作流程,此流程能一路支持到Linux Kernel,如下章节会逐步介绍如何通过tool生成Images。
注意事项:
-
without AES
-
IPL.bin需先Insert CUST Key (Public Key),然后签章必须是由OTP KEY所生成
-
IPL_CUST.bin需先Insert CUST Key (Public Key),然后在通过CUST Key (Private Key) 生成签章,这边Insert的Key为用来验证U-Boot和Linux Kernel的签章
-
-
with AES
-
IPL.bin需先Insert CUST Key (Public Key),然后签章必须是由OTP KEY所生成
-
IPL_CUST.bin需先Insert CUST Key (Public Key),然后再通过CUST Key (Private Key) 生成签章,但不需要进行AES加密。这边Insert的CUST Key (Public Key)为用来验证U-Boot和Linux Kernel的签章。
-
U-Boot和Linux Kernel都需要先进行AES加密,并append 32byte的数据(详见6.2. Header version description章节),然后再通过CUST Key (Private Key) 生成签章。

图7 签章流程
-
3.2. 制作RSA Key¶
这边的制作方式同样适用于OTP Key及CUST Key中的RSA Key,可依据客户需求使用同一把Key或制作出两把不同的RSA Key。出于安全性考虑,建议使用两把不同的RSA key。
请使用以下命令来生成Private.bin和Public.bin。
通过以下命令生成的E key值默认为0x10001,请勿自定义E key值。
3.2.1. RSA2048¶
-
生成RSA私钥
openssl genrsa -out private.pem 2048 -
生成RSA公钥
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
3.2.2. RSA4096¶
-
生成RSA私钥
openssl genrsa -out private.pem 4096 -
生成RSA公钥
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
3.3. 制作AES Key¶
3.3.1. 制作AES-128 key¶
这边通过xxd tool来生成AES-128 key binary file,请指定16bytes的key,通过如下command来生成。
echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey.bin
3.3.2. 制作AES-256 key¶
这边通过xxd tool来生成AES-256 key binary file,请指定32bytes的key,通过如下command来生成。
echo '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F' | xxd -r -ps > aesKey.bin
3.4. USB签章¶
该操作仅在USB boot flow中需要使用
USB boot将会在USB upgrade场景下使用到,在该场景下,由ROM直接引导usb_updater.bin启动到uboot。所以若此时开启securityboot,需要对usb_updater.bin中的IPL_usb.bin与u-boot.xz.img.bin部分签章.
USB不加密:
-
IPL Insert Key,通过key_proc.py执行:
./key_proc.py --insert --rsa=./public.pem -f ./IPL_usb.bin -
IPL 制作签章,通过key_proc.py执行:
./key_proc.py --sign --rsa=./private-otp.pem -f ./IPL_usb.cipher.bin执行后会生成IPL_usb.cipher.sig.bin。
-
UBOOT 制作签章,通过key_proc.py执行:
./key_proc.py --sign --rsa=./private.pem -f u-boot.xz.img.bin
USB加密:
-
IPL Insert Key,通过key_proc.py执行:
./key_proc.py --insert --rsa=./public.pem --IV=IV.bin -f ./IPL_usb.bin执行后会生成IPL_usb.cipher.bin。
-
IPL 制作签章,通过key_proc.py执行
./key_proc.py --sign --rsa=./private-otp.pem -f ./IPL_usb.cipher.bin执行后会生成IPL_usb.cipher.sig.bin。
-
UBOOT 需要先做AES加密,执行后会产生u-boot.xz.img.aes.bin,之后再对加密后的Image进行签章,最后产生u-boot.xz.img.aes.sig.bin,若使用AESkey256,需注意使用的aesKey.bin需是256bit。
./key_proc.py --encrypt --aes=./aesKey.bin -f ./u-boot.xz.img.bin ./key_proc.py --sign --rsa=./private.pem -f ./u-boot.xz.img.aes.bin
USB upgrade image的方法,具体询问FAE窗口。
3.5. IPLX Separation¶
该操作仅在EMMC boot flow中需要使用
由于EMMC采用BOOT_PART.bin方案,所以只有IPL->U-Boot的storage方式是EMMC的时候才需要执行该步骤,SPI NOR、SPI NAND、SD等方式均不需要。BOOT_PART.bin包含IPLX和U-Boot,而IPLX又包含IPL和IPL_CUST, Sigmastar将release IPLX和U-Boot给customer,customer需自行使用如下命令从IPLX中分离出IPL和IPL_CUST,再分别进行签章。
通过key_proc.py执行:
./key_proc.py --split -f ./IPLX.bin
执行后会生成IPL.bin和IPL_CUST.bin
3.6. IPL.bin 签章¶
先将IPL Binary 重命名 为IPL.bin,IPL需要先Insert Key后再做签章。
IPL签章整个步骤如下:
IPL不加密:
-
Insert Key,通过key_proc.py执行:
./key_proc.py --insert --rsa=./public.pem -f ./IPL.bin执行后会生成IPL.cipher.bin。
./add_ipl_header.py ./IPL.cipher.bin ./IPL.cipher2.bin 0 1(调试模式) ./add_ipl_header.py ./IPL.cipher.bin ./IPL.cipher2.bin 0 0(正式模式)执行后会生成IPL.cipher2.bin。
-
制作签章,通过key_proc.py执行(注:必须用OTP的RSA Private Key签章)
./key_proc.py --sign --rsa=./private-otp.pem -f ./IPL.cipher2.bin执行后会生成IPL.cipher2.sig.bin。
3.7. IPL_CUST.bin 签章¶
先将IPL_CUST Binary 重命名 为IPL_CUST.bin,IPL_CUST仅有一种方案,步骤如下:
IPL_CUST不加密:
-
Insert Key,通过key_proc.py执行:
./key_proc.py --insert --rsa=./public.pem -f ./IPL_CUST.bin执行后会生成IPL_CUST.cipher.bin。
-
制作签章,通过key_proc.py执行
./key_proc.py --sign --rsa=./private.pem -f ./IPL_CUST.cipher.bin执行后会生成IPL_CUST.cipher.sig.bin。
3.8. U-Boot 签章¶
如下设定针对SPI NOR的U-Boot版本,其档名为u-boot.xz.img.bin,如为SPI-NAND版本,请改u-boot_spinand.xz.img.bin。Uboot有两种方案,分为UBOOT不加密和UBOOT加密。
UBOOT不加密:
不需做Image的加密动作,执行后会产生u-boot.xz.img.sig.bin。
./key_proc.py --sign --rsa=./private.pem -f u-boot.xz.img.bin
UBOOT加密:
需要先对Image做AES加密,执行后会产生u-boot.xz.img.aes.bin,之后再对加密后的Image进行签章,最后产生u-boot.xz.img.aes.sig.bin,若使用AESkey256,需注意使用的aesKey.bin需是256bit。
./key_proc.py --encrypt --aes=./aesKey.bin -f ./u-boot.xz.img.bin
./key_proc.py --sign --rsa=./private.pem -f ./u-boot.xz.img.aes.bin
3.9. riscv 签章¶
riscv有两种方案,分为riscv不加密和riscv加密。
riscv不加密方案:
不需做Image的加密动作,执行后会生成kernel.sig.bin
./key_proc.py --sign --rsa=./private.pem -f riscv.bin
riscv加密方案:
需要先对Image做AES加密,执行后会生成riscv.aes.bin,之后再对加密后的Image进行签章,最后生成riscv.aes.sig.bin,若使用AESkey256,需注意使用的aesKey.bin需是256bit。
./key_proc.py --encrypt --aes=./aesKey.bin -f ./riscv.bin
./key_proc.py --sign --rsa=./private.pem -f ./riscv.aes.bin
3.10. BOOT_PART.bin Pack¶
该操作仅在EMMC boot flow中需要使用。
如 3.5. IPLX Separation 介绍,BOOT_PART.bin需要拆分为IPL、IPL_CUST和U-Boot单独签章,所以签章后需要再将三个image打包为新的BOOT_PART.bin。且同样地,只有IPL → U-Boot的storage方式是EMMC的时候才需要执行该步骤,SPI NOR、SPI NAND、SD等方式均不需要。
通过cat执行即可:
cat IPL.cipher2.sig.bin IPL_CUST.cipher.sig.bin > IPLX.bin
cat IPLX.bin u-boot.xz.img.sig.bin > BOOT_PART.bin
3.11. Linux Kernel 签章¶
KERNEL有两种方案,分为KERNEL不加密和KERNEL加密。
Kernel不加密方案:
不需做Image的加密动作,执行后会生成kernel.sig.bin。
./key_proc.py --sign --rsa=./private.pem -f kernel.bin
Kernel加密方案:
需要先对Image做AES加密,执行后会生成kernel.aes.bin,之后再对加密后的Image进行签章,最后生成kernel.aes.sig.bin,若使用AESkey256,需注意使用的aesKey.bin需是256bit。
./key_proc.py --encrypt --aes=./aesKey.bin -f ./kernel.bin
./key_proc.py --sign --rsa=./private.pem -f ./kernel.aes.bin
3.12. Linux Rootfs 签章¶
Rootfs不加密:
不需做Image的加密动作,执行后会生成rootfs.sig.sqfs
./key_proc.py --sign --rsa=./private.pem -f rootfs.sqfs
Rootfs加密:
非ramdisk属性的rootfs无法支持加解密机制。rootfs验证可使用dm-verity,见文档device mapper使用参考。
3.13. 自动签章¶
支持自动签章,会自动生成已签章的Image,实际操作步骤如下:
-
进入project目录,make xxx_defconfig; make clean -j32; make image-nocheck -j32;
-
进入project/image/security_boot_tools/下,修改sign_image.config文件
根据实际的需求配置config文件,选择是哪种安全启动方式
sign_image.config文件中参数说明(Image做签章等动作取决于该文件):

Name Description rsalen rsalen的值为 2048 或 4096,即RSA2048 or RSA4096 ipl_abk IPL的版本号,antirollback func used,当ipl_abk=0时表示不使用antirollback ipl_aeskeynum 暂无使用 ipl_aeskeylen 暂无使用 ipl_IV 暂无使用 sw_debug 测试时代替OTP_Secure_boot使用,调试模式 ipl_cust_abk IPL_CUST的版本号, antirollback func used tf_a_abk TF_A的版本号,antirollback func used tf_a_aes_type tf_a的加密方式(支持ecb cbc ctr),若选CBC or CTR,则需要IV值 tf_a_aeskeylen aeskeylen的值为128 或者256。当tf_a_aeskeylen=0时表示不使用aes加密,和tf_a_aeskeynum搭配使用 tf_a_aeskeynum aeskeylen=128下aeskeynum有效范围为[1-4]。
aeskeylen=256下aeskeynum有效范围为[1-2],当tf_a_aeskeynum=0时表示不使用aes加密tf_a_IV CBC or CTR所需要的IV值name tf_a_enable 是否使能以上参数,若为0,则默认使用image的参数 optee_abk OPTEE的版本号,antirollback func used optee_aes_type optee的加密方式(支持ecb cbc ctr),若选CBC or CTR,则需要IV值 optee_aeskeylen aeskeylen的值为128 或者256。 当optee_aeskeylen=0时表示不使用aes加密,和optee_aeskeynum搭配使用 optee_aeskeynum aeskeylen=128下aeskeynum有效范围为[1-4]。
aeskeylen=256下aeskeynum有效范围为[1-2],当optee_aeskeynum=0时表示不使用aes加密optee_IV CBC or CTR所需要的IV值name optee_enable 是否使能以上参数,若为0,则默认使用image的参数 
Name Description vmm_abk VMM的版本号, antirollback func used,暂不支持版本控制 vmm_aes_type 加密方式(支持ecb cbc ctr),若选CBC or CTR,则需要IV值 vmm_aes_enable VMM是否使用AES加密,若为0表示不适用aes加密 vmm_aeskeylen aeskeylen的值为128 或者256。当vmm_aeskeylen=0时表示不使用aes加密,和vmm_aeskeynum搭配使用 vmm_aeskeynum aeskeylen=128下aeskeynum有效范围为[1-4]。
aeskeylen=256下aeskeynum有效范围为[1-2],当vmm_aeskeynum=0时表示不使用aes加密vmm_IV CBC or CTR所需要的IV值name vmm_enable 是否使能以上参数,若为0,则默认使用image的参数 uboot_abk uboot的版本号,antirollback func used uboot_aes_type 加密方式(支持ecb cbc ctr),若选CBC or CTR,则需要IV值 uboot_aeskeylen aeskeylen的值为128 或者256。 当uboot_aeskeylen=0时表示不使用aes加密,和uboot_aeskeynum搭配使用 uboot_aeskeynum aeskeylen=128下aeskeynum有效范围为[1-4]。
aeskeylen=256下aeskeynum有效范围为[1-2],当uboot_aeskeynum=0时表示不使用aes加密uboot_IV CBC or CTR所需要的IV值name uboot_enable 是否使能以上参数,若为0,则默认使用image的参数 kernel_abk kernel的版本号,antirollback func used kernel_aes_type 加密方式(支持ecb cbc ctr),若选CBC or CTR,则需要IV值 kernel_aeskeylen aeskeylen的值为128 或者256。 当kernel_aeskeylen=0时表示不使用aes加密,和kernel_aeskeynum搭配使用 kernel_aeskeynum aeskeylen=128下aeskeynum有效范围为[1-4]。
aeskeylen=256下aeskeynum有效范围为[1-2],当kernel_aeskeynum=0时表示不使用aes加密kernel_IV CBC or CTR所需要的IV值name kernel_enable 是否使能以上参数,若为0,则默认使用image的参数 
注:其他未指定的image中的abk等配置,都根据image_xx的设定值进行配置。
Name Description rtos_abk RTOS的版本号, antirollback func used,暂不支持版本控制 rtos_aes_type 加密方式(支持ecb cbc ctr),若选CBC or CTR,则需要IV值 rtos_aeskeylen aeskeylen的值为128 或者256。 当rtos_aeskeylen=0时表示不使用aes加密,和rtos_aeskeynum搭配使用 rtos_aeskeynum aeskeylen=128下aeskeynum有效范围为[1-4]。
aeskeylen=256下aeskeynum有效范围为[1-2],当rtos_aeskeynum=0时表示不使用aes加密rtos_IV CBC or CTR所需要的IV值name rtos_enable 是否使能以上参数,若为0,则默认使用image的参数 image_aes_type 加密方式(支持ecb cbc ctr),若选CBC or CTR,则需要IV值 image_aeskeylen aeskeylen的值为128 或者256。 当image_aeskeylen=0时表示不使用aes加密,和image_aeskeynum搭配使用 image_aeskeynum aeskeylen=128下aeskeynum有效范围为[1-4]。
aeskeylen=256下aeskeynum有效范围为[1-2],当image_aeskeynum=0时表示不使用aes加密image_IV CBC or CTR所需要的IV值name image_abk 预保留,若使用anti rollback功能,填写在对应image的abk -
进入project/image/security_boot_tools/下,make clean;make;即可生成image_secure目录(目录下Image已签章)
注:如果签章的动作需要在别的目录下做或者需要在不同电脑上签章,Step3中请执行make image_prepare,并把security_boot_tools完整copy到另一个位置,再执行make即可。
注:security_boot_tools生成的image,estar会自动配置uboot cmd来验签kernel。默认rootfs会加签,但不会在uboot下设置验签的env。如需验签rootfs, 请手动添加或者在project下的image/configs/general/xxxx.config中,设置rootfs$(BOOTCMD),设置完成后在securityboot_tools下make,用生成的image进行estar,即会自动设置uboot下的env来验签rootfs
-
(仅 USB boot flow 需要)可以使用 usb 自动签章方式,在project/image/security_boot_tools/下,执行
make usb_factory_sigmastar IPL=XXX UBOOT=XXX TFA=XXX例:
make usb_factory_sigmastar IPL=IPL.pcupid_usb.DDR4_3200_NTC8G_BGA2=y.MIU_MEMAUTOK=y.CPUFREQ1500=y.bin UBOOT=u-boot_emmc.xz.img.bin TFA=u-bl31.bin注:可以先单独执行 make usb_factory_sigmastar,将提示目前支持的IPL和UBOOT文件,进行选择填入。 最后生成usb factory usb image文件, USB upgrade image的方法,具体见文档usb_factorytool_update
若需要生成 emmc 安全启动升级包,可以在project/image/security_boot_tools/下,执行:
make emmc_upgrade_sigmastar若需要生成 sd 安全启动升级包,可以在project/image/security_boot_tools/下,执行:
make sd_upgrade_sigmastar若需要生成 u盘 安全启动升级包,可以在project/image/security_boot_tools/下,执行:
make usb_upgrade_sigmastar最后可以在project/image/security_boot_tools/image_secure获取到 SigmastarUpgradeXX.bin 升级包。
3.14. 签章验证¶
-
将完成签章的Images刻录至flash中,刻录后如能正常进入U-Boot,表示从IPL至U-Boot的签章是没有问题的。
-
在Uboot阶段需要设定环境变量来对Linux Kernel进行验证,其原理是通过sigauth命令来对Binary进行验签和解密,如下:
-
验签
请在对应存储介质读取Kernel后加上:
sigauth <Binary_Addr> <KEY_Addr>;EX:
setenv bootcmd 'loados nand 0x23000000 KERNEL 0x500000; sigauth 23000000 0x21000000 ; bootm 0x23000000'; saveenv;
-
-
若customer有验签rootfs的需求,在Uboot阶段需要设定环境变量来对Linux Rootfs进行验证,请参考如下command进行设定:
-
rootfs验签:
请在对应存储介质读取rootfs后加上:
sigauth <Binary_Addr> <KEY_Addr>;EX:
setenv bootcmd 'loados nand 0x22000000 rootfs 0x600000; sigauth 0x22000000 0x23C00000; loados nand 0x22000000 KERNEL 0x500000; sigauth 0x22000000 0x23C00000; bootm 0x22000000'; saveenv;
-
4. 注意事项¶
4.1. 自编tool签章¶
AES加密都不包含Header,仅将Data部分来进行加密。
4.2. EMMC BOOT_PART.bin签章¶
必须单独对IPL、IPL_CUST、U-Boot进行签章,签章后再重新打包为新的BOOT_PART.bin烧入(见3.5. IPLX Separation和3.9. BOOT_PART.bin Pack)
5. SECURITYBOOT部署流程¶
5.1. SecurityBoot调试流程¶
若确认需要使用OTP烧录来串通SecurityBoot flow,则调试阶段务必按照以下flow,即先烧录部分OTP进行测试,否则可能由于错误的操作导致系统无法启动甚至IC作废,待调试PASS以后再考虑一次性烧录所有OTP
5.1.1. 烧录OTP(KEY)¶
使用U-Boot Command或Linux Tool烧录RSA Public NKey/Ekey(或AES Key)。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明。
5.1.2. 签章image¶
对IPL/IPL_CUST/U-Boot进行签章(或加密)并烧入flash。
其中IPL/IPL_CUST务必用调试流程的签章方法(目的是代替OTP中的SecurityBoot enable bit来开启SecurityBoot flow)。
注意: 调试流程的签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章
5.1.3. 检验验签(或解密)结果¶
首先需要确认ROM->IPL->IPL_CUST->U-Boot已进行到SecurityBoot的flow。
-
ROM->IPL确认是否走SecurityBoot的方式
ROM验签IPL成功不会有任何log,但验签失败则会打印AUTH ERR,所以可以烧入未签章的IPL到flash,若ROM->IPL已进行到SecurityBoot的flow,则会报AUTH ERR。
-
IPL->IPL_CUST->U-Boot确认是否走SecurityBoot的方式
查看log即可,一般带有-Authenticate image关键字代表执行验签的结果,若开启解密流程则还会有[SECURE]关键字提示解密key的类型。
举例如下:

确认后,需确保能启动到U-Boot才能继续下一步烧录。
5.1.4. 烧录OTP(ENABLE)¶
使用U-Boot Command或Linux Tool烧录SecurityBoot enable bit。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
烧录后按照上述方法确认ROM->IPL->IPL_CUST->U-Boot有走到SecurityBoot并能启动到U-Boot,然后继续下一步烧录。
5.1.5. 烧录OTP(LOCK)¶
使用U-Boot Command或Linux Tool烧录RSA KEY的LOCK。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
烧录后同样按照5.1.3的方法确认ROM->IPL->IPL_CUST->U-Boot有走到SecurityBoot并能启动到U-Boot,到此ROM->IPL->IPL_CUST->U-Boot的SecurityBoot flow和OTP相关验证已经PASS。
接下来根据3.14. 签章验证的方法验证U-Boot以后的SecurityBoot flow。
5.1.6. 用SigmaStar TV System Tool烧录OTP¶
5.1.6.1 连接¶
-
开发板上电并关闭串口
-
uboot控制台下直接输入
debug,然后关闭串口终端
-
kernel下,则输入
11111,然后关闭串口终端
-
-
Tool配置

-
进入OTP Burn Tool

-
OTP Burn Tool主界面
进入OTP时,会检查当前chip,如未正常连接会弹窗提示(如下),需确认连接后关闭重开该页面。

正常显示的页面如下所示:

5.1.6.2 格式说明¶
可以将鼠标放在UI对应文本框中,会显示格式说明,部分说明如下:
| OTP名称 | 说明(输入方式如下: ①手动输入; ②点击右测按钮导入16进制bin文件) | 输入示例 |
|---|---|---|
| CID | 1byte,16进制输入 | 88 |
| UUID | 8byte,16进制输入,空格分隔 | 88888888 88888888 |
| DID1 | 8byte,16进制输入,空格分隔 | 88888888 88888888 |
| DID2 | 8byte,16进制输入,空格分隔 | 88888888 88888888 |
| PASSWORD | 8byte,16进制输入,空格分隔 | 88888888 88888888 |
| KEY1/KEY2/KEY3/KEY4 KEY4/KEY5/KEY6/KEY7 | 16byte,16进制输入,空格分隔 | 88888888 88888888 88888888 88888888 |
| RSA_N | 256byte,16进制输入,空格分隔 | 88888888 88888888 88888888 88888888 … |
| VERSION_CTL | 256byte,16进制输入,空格分隔 | 88888888 88888888 88888888 88888888 … |
| VERSION2_CTL | 512byte,16进制输入,空格分隔 | 88888888 88888888 88888888 88888888 … |
| CUSTOMER_SREA | 1024byte,16进制输入,空格分隔 | 88888888 88888888 88888888 88888888 … |
2.4节各字段解释:点击跳转
5.1.6.3. 使用说明¶
-
Write:UI需要写入的位置填好后,点击Write写入OTP,如报错,请根据表1/ 2/ 3检查对应格式;

注意:
①写入成功会提示:Burning OTP completed!

②写入失败提示:Burning OTP Failed,please read OTP_DATA_COMPARE.txt!

其中,OTP_DATA_COMPARE.txt 文件存放在tool根目录,记录了数据写入过程中字段地址写入与读出数据不符合的集合。

-
Read:读出OTP的值;

-
Clear:清空UI所有数据;

-
Upload: 上传 bin文件(包含UI所有字段数据设置);

-
Download: 下载bin文件(当前UI所有字段数据设置)存放至 OTP_DATA.bin 文件中;

-
UnFold: 展开隐藏字段(有些字段不常用,所以预设隐藏);

-
Fold: 折叠隐藏字段。

5.1.6.4. 烧写实例¶
准备预烧写数据:
制作rsa key见章节3.2[点击跳转]
得到需要的public-otp.bin
a. 普通流程,Only RSA
勾选SECURITY_BOOT并点击RSA_N右侧的"...",打开文件选择上一步生成的public-otp.bin。
点击Write,等待烧录完成,烧录成功出现Burning OTP completed!

5.2. SecurityBoot正式流程(普通流程,Only RSA)¶
为了防止误操作导致系统无法启动甚至IC作废,调试流程PASS以后,才能进行正式流程。
5.2.1. 签章image(ALL)¶
使用python script将所有需要验签的image都执行一遍签章,再烧入flash,其中IPL/IPL_CUST可以使用正式模式的签章方法(因为OTP中的SecurityBoot enable bit会被烧录,不需要用software来模拟了)
注意: 正式模式的签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章。
5.2.2. 烧录OTP(ALL)¶
使用U-Boot Command或Linux Tool烧录所有OTP case。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
5.3. SecurityBoot正式流程(加密流程,RSA+AES)¶
5.3.1. 参考理论设计方案一¶
为了防止误操作导致系统无法启动甚至IC作废,调试流程PASS以后,才能进行正式流程。
-
签章image(ALL)
使用python script对image只执行签章(或不签章,若只进行签章则需用特定的IPL/IPL_CUST),烧入flash,再使用python script对image执行签章和加密,用于网络或USB等方式升级。
注意:签章方法见第3章,其中IPL/IPL_CUST可以使用 正式模式 的签章方法(因为OTP中的SecurityBoot enable bit会被烧录,不需要用software来模拟了), 正式模式 的签章方法签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章。
-
烧录OTP(ALL)
使用U-Boot Command或Linux Tool烧录所有OTP case。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
-
Upgrade
若分区中image未签章,则OTP烧录后,不能重启,应立即通过网络或USB upgrade加密image。
若分区中image有签章,则OTP烧录后,可以重启,但仍需通过网络或USB upgrade加密image。
5.3.2. 参考理论设计方案二¶
为了防止误操作导致系统无法启动甚至IC作废,调试流程PASS以后,才能进行正式流程。
-
签章和加密image(ALL)
划分两套分区,使用python script对image只执行签章(或不签章,若只进行签章则需用特定的IPL/IPL_CUST),烧入第一套分区,再使用python script对image执行签章和加密,烧入第二套分区。
注意: 签章方法见第3章,其中IPL/IPL_CUST可以使用 正式模式 的签章方法(因为OTP中的SecurityBoot enable bit会被烧录,不需要用software来模拟了), 正式模式 的签章方法签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章。
-
烧录OTP(ALL)
从第一套分区启动,使用U-Boot Command或Linux Tool烧录所有OTP case。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
-
Upgrade
若第一套分区未签章,则OTP烧录后,不能重启,应立即将第二套分区内容upgrade到第一套分区中。
若第一套分区有签章,则OTP烧录后,可以重启,但仍需将第二套分区内容upgrade到第一套分区中。
6. Anti_rollback¶
6.1. 概述¶
防回滚机制,其目的是为了防止IPL/IPL_CUST/TF-A/OPTEE/UBOOT/KERNEL 降级到以前的版本,通过OTP中的Version Ctrl与IPL/IPL_CUST/TF-A/OPTEE/UBOOT/KERNEL Header Version进行对比,如果:
Header Version >= OTP Version ==> booting
Header Version < OTP Version ==> halt
以此来保证IPL/IPL_CUST/TF-A/OPTEE/UBOOT/KERNEL 的版本为最新。
以下是各个Image的可用进版数和OTP VERSION对应烧录的OTP栏位说明。
| Name | 可用进版数 | OTP CMD | OTP OFFSET范围 |
|---|---|---|---|
| IPL | 64 | OTP_VERSION_CTL | 0x0 ~ 0x100 |
| IPL_CUST | 16 | OTP_VERSION2_CTL | 0x0 ~ 0x40 |
| tfa | 24 | OTP_VERSION2_CTL | 0x40 ~ 0xA0 |
| optee | 24 | OTP_VERSION2_CTL | 0xA0 ~ 0x100 |
| uboot | 24 | OTP_VERSION2_CTL | 0x100 ~ 0x160 |
| kernel | 24 | OTP_VERSION2_CTL | 0x160 ~ 0x1C0 |
注意:
- Header Version为当前image的版本号, OTP Version的一个版本号则以otp栏位里4bytes为单位,再与Header Version进行对比。
- IPL_CUST/TF-A/OPTEE/UBOOT/KERNEL 的可用进版数加起来不能超过128。
- otp version可具有自动更新功能。当header version大于otp version时,会更新otp version与header version一致。(otp自动更新功能默认关闭)
6.2. Header version description¶
目前每个Image Tail 需要 append 32byte data,append数据插入在image tail,以下是 sstar_pend的说明:

| Member | Description |
|---|---|
| magic | 检索的标志 |
| pend_version | Secure append的版本 |
| sstar_pend_size | Secure append的长度,32Byte |
| aes_msg | bit 0 - decrypt_enable,bit [1:2] - 00:ecb 01: ctr 10:cbc |
| AntiRollback_version | uImage的版本号 |
| IV1&IV2 | CBC/CTR解密需要传入的值 |
| aes_keynum | 0100 ==> AES256 with {Key1[127:0], Key2[127:0] 0101 ==> AES256 with {Key3[127:0], Key4[127:0] 1000 ==> AES128 with Key1[127:0] 1001 ==> AES128 with Key2[127:0] 1010 ==> AES128 with Key3[127:0] 1011 ==> AES128 with Key4[127:0] |
结构体中的数据为了表明当前image是否加密,以及使用ecb/ctr/cbc aeskeylen的值,使得secure boot的过程中可以对某个image特殊处理。
以UBOOT为例,Secure boot自动签章的过程中会根据secure_image.config中的配置,生成一份sstar_sbt的数据(见上述结构体)
- 仅签章:将该32byte的数据插入在image的尾部,uboot header中的size不包含sstar_append。最后再做signature.
- 签章+加密:先将payload data进行加密,再进行将32byte数据进行append。最后再做signature.
以上步骤完成后,如果是SZ,则做sz压缩的动作, 并加入Header2。(sz压缩加header2可参考1.9 UBOOT/KERNEL SZ IMAGE签章)

6.3. IPL进版次数¶
6.3.1. OTP Version Ctrl¶
IPL的OTP版本号有64次进版次数。
可在UBOOT下通过以下cmd来修改读取IPL OTP Version
| WRITE COMMAND: otpctrl -w 0x2B 0x0 0xFFFFFFFF |
|---|
| READ COMMAND: otpctrl -r 0x2B |
OTP Version Ctrl 烧录举例:
| Purpose:IPL OTP Version = 1 |
|---|
| WRITE COMMAND: otpctrl -w 0x2B 0x0 0xFFFFFFFF |
| Purpose:IPL OTP Version = 2 |
| WRITE COMMAND: otpctrl -w 0x2B 0x0 0xFFFFFFFF otpctrl -w 0x2B 0x4 0xFFFFFFFF |
| Purpose:IPL OTP Version = 4 |
| WRITE COMMAND: otpctrl -w 0x2B 0x0 0xFFFFFFFF otpctrl -w 0x2B 0x4 0xFFFFFFFF otpctrl -w 0x2B 0x8 0xFFFFFFFF otpctrl -w 0x2B 0xC 0xFFFFFFFF |
6.3.2. IPL Header Version¶
打开文件 project/image/security_boot_tools/sign_image.config,修改参数 'ipl_abk'。
| Purpose:IPL HEADER Version 为12 |
|---|
| ipl_abk=C |
6.4. IPL_CUST进版次数¶
6.4.1. OTP Version Ctrl¶
IPL_CUST的OTP版本号有16次进版次数。
可在UBOOT下通过以下cmd来修改读取IPL_CUST OTP Version
| WRITE COMMAND: otpctrl -w 0x2C 0x0 0xFFFFFFFF |
|---|
| READ COMMAND: otpctrl -r 0x2C |
OTP Version Ctrl 烧录举例:
| Purpose:IPL_CUST OTP Version = 1 |
|---|
| WRITE COMMAND: otpctrl -w 0x2C 0x0 0xFFFFFFFF |
| Purpose:IPL_CUST OTP Version = 2 |
| WRITE COMMAND: otpctrl -w 0x2C 0x0 0xFFFFFFFF otpctrl -w 0x2C 0x4 0xFFFFFFFF |
| Purpose:IPL_CUST OTP Version = 4 |
| WRITE COMMAND: otpctrl -w 0x2C 0x0 0xFFFFFFFF otpctrl -w 0x2C 0x4 0xFFFFFFFF otpctrl -w 0x2C 0x8 0xFFFFFFFF otpctrl -w 0x2C 0xC 0xFFFFFFFF |
6.4.2 IPL_CUST Header Version¶
打开文件 project/image/security_boot_tools/sign_image.config,修改参数 'ipl_cust_abk',举例请参考6.2.2 IPL Header Version
6.5. TF_A进版次数¶
6.5.1. OTP Version Ctrl¶
TF_A的OTP版本号有24次进版次数。
可在UBOOT下通过以下cmd来修改读取TF_A OTP Version
| WRITE COMMAND: otpctrl -w 0x2C 0x40 0xFFFFFFFF |
|---|
| READ COMMAND: otpctrl -r 0x2C |
OTP Version Ctrl 烧录举例:
| Purpose:TF_A OTP Version = 1 |
|---|
| WRITE COMMAND: otpctrl -w 0x2C 0x40 0xFFFFFFFF |
| Purpose:TF_A OTP Version = 2 |
| WRITE COMMAND: otpctrl -w 0x2C 0x40 0xFFFFFFFF otpctrl -w 0x2C 0x44 0xFFFFFFFF |
| Purpose:TF_A OTP Version = 4 |
| WRITE COMMAND: otpctrl -w 0x2C 0x40 0xFFFFFFFF otpctrl -w 0x2C 0x44 0xFFFFFFFF otpctrl -w 0x2C 0x48 0xFFFFFFFF otpctrl -w 0x2C 0x4C 0xFFFFFFFF |
6.5.2. TF_A Header Version¶
打开文件 project/image/security_boot_tools/sign_image.config,修改参数 'tf_a_abk',举例请参考6.2.2 IPL Header Version
6.6. optee进版次数¶
6.6.1. OTP Version Ctrl¶
optee的OTP版本号有24次进版次数。
可在UBOOT下通过以下cmd来修改读取optee OTP Version
| WRITE COMMAND: otpctrl -w 0x2C 0xA0 0xFFFFFFFF |
|---|
| READ COMMAND: otpctrl -r 0x2C |
OTP Version Ctrl 烧录举例:
| Purpose:optee OTP Version = 1 |
|---|
| WRITE COMMAND: otpctrl -w 0x2C 0xA0 0xFFFFFFFF |
| Purpose:optee OTP Version = 2 |
| WRITE COMMAND: otpctrl -w 0x2C 0xA0 0xFFFFFFFF otpctrl -w 0x2C 0xA4 0xFFFFFFFF |
| Purpose:optee OTP Version = 4 |
| WRITE COMMAND: otpctrl -w 0x2C 0xA0 0xFFFFFFFF otpctrl -w 0x2C 0xA4 0xFFFFFFFF otpctrl -w 0x2C 0xA8 0xFFFFFFFF otpctrl -w 0x2C 0xAC 0xFFFFFFFF |
6.6.2. optee Header Version¶
打开文件 project/image/security_boot_tools/sign_image.config,修改参数 'optee_abk',举例请参考6.2.2 IPL Header Version
6.7. VMM进版次数¶
暂未支持版本控制。
6.8. UBOOT进版次数¶
6.8.1. OTP Version Ctrl¶
UBOOT的OTP版本号有24次进版次数。
可在UBOOT下通过以下cmd来修改读取UBOOT OTP Version
| WRITE COMMAND: otpctrl -w 0x2C 0x100 0xFFFFFFFF |
|---|
| READ COMMAND: otpctrl -r 0x2C |
OTP Version Ctrl 烧录举例:
| Purpose:UBOOT OTP Version = 1 |
|---|
| WRITE COMMAND: otpctrl -w 0x2C 0x100 0xFFFFFFFF |
| Purpose:UBOOT OTP Version = 2 |
| WRITE COMMAND: otpctrl -w 0x2C 0x100 0xFFFFFFFF otpctrl -w 0x2C 0x104 0xFFFFFFFF |
| Purpose:UBOOT OTP Version = 4 |
| WRITE COMMAND: otpctrl -w 0x2C 0x100 0xFFFFFFFF otpctrl -w 0x2C 0x104 0xFFFFFFFF otpctrl -w 0x2C 0x108 0xFFFFFFFF otpctrl -w 0x2C 0x10C 0xFFFFFFFF |
6.8.2. UBOOT Header Version¶
打开文件 project/image/security_boot_tools/sign_image.config,修改参数 'uboot_abk',举例请参考6.2.2 IPL Header Version
6.9. KERNEL进版次数¶
6.9.1. OTP Version Ctrl¶
KERNEL的OTP版本号有24次进版次数。
可在UBOOT下通过以下cmd来修改读取KERNEL OTP Version
| WRITE COMMAND: otpctrl -w 0x2C 0x160 0xFFFFFFFF |
|---|
| READ COMMAND: otpctrl -r 0x2C |
OTP Version Ctrl 烧录举例:
| Purpose:KERNEL OTP Version = 1 |
|---|
| WRITE COMMAND: otpctrl -w 0x2C 0x160 0xFFFFFFFF |
| Purpose:KERNEL OTP Version = 2 |
| WRITE COMMAND: otpctrl -w 0x2C 0x160 0xFFFFFFFF otpctrl -w 0x2C 0x164 0xFFFFFFFF |
| Purpose:KERNEL OTP Version = 4 |
| WRITE COMMAND: otpctrl -w 0x2C 0x160 0xFFFFFFFF otpctrl -w 0x2C 0x164 0xFFFFFFFF otpctrl -w 0x2C 0x168 0xFFFFFFFF otpctrl -w 0x2C 0x16C 0xFFFFFFFF |
6.9.2. KERNEL Header Version¶
打开文件 project/image/security_boot_tools/sign_image.config,修改参数 'kernel_abk',举例请参考6.2.2 IPL Header Version
6.10. RTOS进版次数¶
暂未支持版本控制。