Security Boot使用参考
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
1.0 | 05/09/2024 | |
1.1 | 05/29/2024 |
1. Security Boot概述¶
为防止用户产品的固件被抄板或者刷机,Sigmastar固件在启动过程自动进行验签(或验签+解密),验签即签章的验证,防止软件加载的镜像内容被恶意篡改。其中加密和解密为可选,一般情况下镜像加密是为了防止镜像中的信息被泄露,而镜像验章是为了防止镜像的信息被篡改,用户可根据自身需求取舍。使用Security Boot的核心工作有两步:人为将镜像文件进行签章(或加密+签章),以及将签章使用到的对应key通过烧录保存在芯片OTP中。
烧录芯片OTP的常用方式是使用uboot下的otpctrl cmd,(详见5. OTP 栏位介绍章节)。请注意OTP烧录无法反悔,为了防止误操作导致系统无法启动甚至IC作废,一般建议开发者先使用调试流程确认key内容正确。签章镜像的常用方式是使用security_boot_tools自动处理alkaid image包,(详见4. Security_boot_tools工具使用介绍章节),如果客户有特殊需要,也可以选择手动签章方式《[Security Boot手动签章使用参考]》。
Security Boot还提供了防回滚机制(Anti-rollback),确保能正常加载和启动的镜像版本一定比用户在OTP里存储的版本号高,(详见3. Anti-rollback原理介绍章节),用户可根据自身需求使用。开启Anti-rollback的核心工作有两步:使用security_boot_tools签章过程将版本号嵌入镜像中,以及将拦截的镜像版本号保存在芯片OTP中。
2. Security Boot原理介绍¶
2.1. 开启Security Boot¶
当烧录完OTP Key后,真正启动Security Boot需要烧录OTP里的OTP_Secure_Boot相应的栏位(OTP烧录方法详见5.2 security boot相关的OTP栏位章节),将该栏位烧录为0xFFFFFFFF,则会启动OTP的Security Boot(注:开启后无法关闭,每次启动都将会强制走Security Boot flow)。
2.2. 单个镜像签章和Security Boot流程¶
Generate Signature一般是在local端执行security_boot_tools脚本完成,流程如下:
- security_boot_tools对Image file进行SHA-256的计算,生成Digest
- 通过RSA-2048做加密动作,生成256Bytes的signature
- 将signature嵌入至Image尾端
- 将Image烧录把系统存储器中启动。
Verify Signature是在固件boot flow中执行,流程如下:
- 各阶段的boot code会对下一段的Image进行SHA-256计算,生成Digest
- 根据header信息取出嵌入在尾部的signature来做RSA-2048的解密生成Digest'
- 对比Digest和Digest',若对比一致,则Verify success,否则Verify fail。
图2 签章Security Boot流程
2.3. 单个镜像签章+加密和Security Boot流程¶
Generate Signature一般是在local端执行security_boot_tools脚本完成:security_boot_tools先对Image通过AES加密成Cipher file,再对Cipher file进行SHA-256计算,生成Digest,再通过RSA-2048做加密动作,生成256Bytes的signature,再将signature嵌入至Image后端,最后将Image烧录把系统存储器中启动。
Verify Signature是在boot flow中,各阶段的boot code会对下一段的Image进行SHA-256计算,生成Digest,并根据header信息取出嵌入在取出Signature来做RSA-2048的解密后,生成Digest',最后对比Digest和Digest'。如对比成功,则对Cipher file进行AES解密的动作,最后解密为能开机的image。
图3 签章+加密Security Boot流程
需要注意: IPL只支持AES-CBC加密,而IPL_CUST不支持加密。 其他image支持AES (ECB/CBC/CTR加密),当使用CBC/CTR模式时,对应的IV key会被security_boot_tools制作成32字节的append段落,嵌入在image信息里,(详见3.1. Append data说明章节)。
2.4. Security Boot流程中Image File变化¶
需要注意:
- IPL/IPL_CUST没有uimage header,但有自己特殊的header且此header不参与加密和签章,此头部的具体变化在2.5.1介绍
- 除IPL/IPL_CUST/Rootfs外,其他image的头部会加上一层独立的secure_boot header表示image已经支持secure boot,且此header不参与加密和签章
2.5. 密钥介绍¶
从密钥使用的角度看,同一个image签章和验签必须使用一对RSA Private Key
和RSA Public Key
,加密和解密使用同一把AES Key
。
2.5.1. RSA Public Key¶
验签流程中所用的RSA Public Key
最多有三组。
第一把为 OTP Key
,该把Key会在系统Power On后,Hardware会自动从OTP中载入,用来做验签IPL的可靠性,加载和验签过程Software是无法介入的。而OTP Key的内容,可以通过U-Boot的Command Line烧录至OTP的指定地址中。一旦OTP KEY锁读后,cpu或其他调试工具再也无法access rsakey(otp aes key同理)此时只有aesdma engine can access。
第二把为CUST Key
,该Key会嵌在IPL的bin文件中,通过Software在整个boot flow中用来验签IPL_CUST的可靠性,因为IPL的可靠性有保证,因此验签IPL_CUST的过程也是可靠的。而 CUST KEY的内容,一般是使用security_boot_tools工具将key文件insert到IPL的bin文件内容的指定位置。
第三把为Image Key
,该Key会嵌在IPL_CUST的bin文件中,通过Software在整个boot flow中用来验签UBOOT/VMM/RTOS/LINUX/ROOTFS的可靠性,因为IPL_CUST的可靠性有保证,因此验签后面所有镜像的过程也是可靠的。而Image Key的内容,一般是使用security_boot_tools工具将key文件insert到IPL_CUST的bin文件内容的指定位置。
2.5.2. AES KEY¶
解密流程中所用的AES Key
最多为4把。
在Sigmastar固件在bootflow过程,由Hardware载入OTP里指定的AES key到crypto engine进行镜像解密。至于镜像使用4把AES key中的哪一把,一般是使用security_boot_tools工具在镜像中嵌入指定AES key 信息,(详见3.1. Append data说明章节)。除了IPL只支持CBC mode以及IPL_CUST不支持加密,其余image都支持ECB/CBC/CTR mode,一般也是使用security_boot_tools工具在镜像中嵌入IV信息。
所有bootload image用于解密的AES Key需要烧录到OTP存储单元中,OTP存储单元最多保存4把128bit的AESKEY或者4把256bit的AESKEY。所有bootload image可以任意指定4把中的任意1把key,甚至所有bootload image都共用其中1把key。
2.6. Security boot system flow介绍¶
下图为从ROM到Linux Kernel的Security Boot Flow结构,其中Signature为签章数据部分,每个Flow的Signature均会嵌入到相应bin文件的最后,每个Flow均包含Get Key和Authenticate的动作直到Linux Kernel,部分Flow支持解密(是否开启解密取决于需求)。
-
Authenticate IPL by OTP Key-RSA
该流程为ROM code从OTP中读取RSA Public Key后,对IPL进行签章的验证。由于OTP的RSA Public Key可以进行Write Lock动作(后面章节会详细提及),阻止再次被写和被读取,所以OTP的RSA Public Key可以做到不被替换,从而保证了IPL不会被篡改。如果开启加密机制,ROM code根据OTP_ROM_SEL_AESKEY继续从OTP中读取AES key对IPL进行解密。
-
Authenticate IPL_CUST by IPL's CUST Key-RSA
该流程为IPL读取事先嵌在IPL的CUST RSA Public Key后,对IPL_CUST进行签章的验证。由于IPL不会被篡改,所以保证了嵌在IPL的CUST RSA Public Key不会被篡改,从而保证了IPL_CUST也不会被篡改。IPL_CUST不支持加密。
-
Authenticate U-Boot by IPL_CUST's Image Key-RSA
该流程为IPL_CUST读取事先嵌在IPL_CUST的Image RSA Public Key后,对U-Boot进行签章的验证。如果开启加密机制,IPL_CUST根据U-Boot镜像里的append data里的IV和aes_keynum信息继续从OTP中读取AES key对U-Boot进行解密。
-
Authenticate Kernel/ramdiskfs by IPL_CUST's Image Key-RSA
该流程为U-Boot bootcmd读取事先嵌在IPL_CUST的Image RSA Public Key后,对kernel/ramdiskfs进行签章的验证。如果开启加密机制,bootcmd根据kernel/ramdiskfs镜像里的append data里的IV和aes_keynum信息继续从OTP中读取AES key对kernel/ramdiskfs进行解密。
3. Anti-rollback原理介绍¶
防回滚机制,其目的是为了防止IPL/IPL_CUST/UBOOT/KERNEL 降级到以前的版本。各个阶段的boot code通过检查下一阶段的boot code(IPL/IPL_CUST/UBOOT/KERNEL) image信息里的Image Version,与保存在OTP里对应的OTP Version 进行对比,如果:
Image Version >= OTP Version ==> 正常加载并启动下一阶段的boot code image
Image Version < OTP Version ==> 提示系统卡住,不启动下一阶段的boot code image
以此来保证IPL/IPL_CUST/UBOOT/KERNEL 的版本为最新。
以下是各个Image的可用进版数(otp version烧录详见5.3. anti-rollback相关的OTP栏位章节)。
Name | 最多可进版次数 | otp name | otp cmd offset |
---|---|---|---|
IPL | 64 | OTP_VERSION_CTL | 0x0~0x7 |
IPL_CUST | 16 | OTP_VERSION2_CTL | 0x0~0x1 |
uboot | 24 | OTP_VERSION2_CTL | 0x8~0xA |
kernel | 24 | OTP_VERSION2_CTL | 0xB~0xD |
注意:
- 在OTP Version中,用1个bit表示进阶一次版本。以IPL为例,当IPL OTP Version 从0进版到1,需要使用OTP_VERSION_CTL命令将0x0刻录成0x00000001; 当IPL OTP Version需要再次进版到2,需要使用OTP_VERSION_CTL命令将0x0刻录成0x0x00000003;
- Image Version为当前image的版本号,对于IPL和IPL_CUST,Image Version是保存在header data里;对于UBOOT/KERNEL,Image Version是保存在appended data里; 除此之外的其他image(RTOS/ROOTFS)虽然也会追加appended data,但不支持anti-rollback功能。
- otp version可具有自动更新功能(默认关闭)。当header version大于otp version时,会更新otp version与header version一致。
3.1. Append data说明¶
只要使用securityboot功能,目前除了IPL/IPL_CUST,security_boot_tools会用同样的方式处理其余每个Image(UBOOT/KERNEL/RTOS等):先在尾部追加 32byte appended data,再追加256/512 byte signature data。
以下是 32byte appended data的说明:
Member | Description |
---|---|
magic | 检索的标志,固定为“SSTARSBT” |
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 | 除IPL,IPL_CUST之外的其他image的版本号 |
IV1&IV2 | CBC/CTR解密需要传入的IV值 |
aes_keynum | 0000 ==> 没有经过AES加密 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] |
可以看出,镜像信息:如anti-rollback功能的Image Version、Image是否经过AES加密、使用哪种类型AES(CBC/CTR/ECB、128/256)加密、加密使用的IV值、使用OTP里哪一把AES key,都是保存在这32字节的appended data里。系统启动过程中,每一个阶段的boot code就是根据下一阶段的boot code image里的appended data,对其进行相应的version check和解密镜像。
4. Security_boot_tools工具使用介绍¶
使用Security_boot_tools对alkaid image进行签章的步骤主要有以下几步:
- 先编译打包,生成未签章的完整镜像烧录包。
- 手动制作RSA key和aes Key,替换Security_boot_tools工具目录下默认的RSA key和aes Key。
- 编译配置文件sign_image.config,指定各阶段的boot Image的Image version/rsa key/aes key/aes加密模式(CBC/CTR/ECB)/aes IV值等信息。
- 执行Security_boot_tools即可根据配置信息,自动完成对完整镜像烧录包的拆包、签名、嵌入CUST Key、嵌入Image Key、嵌入appended data、打包、压缩等工作,输出已签章的完整镜像烧录包。
4.1. 制作RSA key和aes Key¶
4.1.1 制作RSA Key¶
制作方式适用于OTP Key/CUST Key/Image Key中的RSA Key,可依据客户需求,多个Image使用同一把Key或多个Image使用不同的RSA Key。出于安全性考虑,建议使用多把不同的RSA key。
请使用以下命令来生成Private.bin和Public.bin。
通过以下命令生成的E key值默认为0x10001,security boot flow不支持自定义E key值。
RSA2048:
-
生成RSA私钥
openssl genrsa -out private.pem 2048
-
生成RSA公钥
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
将上述生成的n对RSA key,替换project/image/security_boot_tools/下的rsa2048 目录下对应的需要用到的key binary文件即可。
key type | Description |
---|---|
private-otp.pem | 被security_boot_tools用来签章IPL |
public-otp.pem | 需要人为烧录到OTP里,用于启动过程ROM code验签IPL |
private-cust.pem | 被security_boot_tools用来签章IPL_CUST |
public-cust.pem | 被security_boot_tools嵌入到IPL里,用于启动过程IPL验签IPL Load的所有Image |
private-image.pem | 被security_boot_tools用来签章除了IPL/IPL_CUST的其他Image |
public-image.pem | 被security_boot_tools嵌入到IPL_CUST里,用于启动过程IPL_CUST阶段后的所有Image,包括Uboot Load Kernel等 |
注意:像MISC这样的Image由于在使用过程中会变化,故不做验签
4.1.2. 制作AES Key¶
这边通过xxd tool来生成AES key binary file
,制作方式适用于OTP里的4把 aes-128 key或者2把aes-256 key。可依据客户需要求,多个Image使用同一把aes Key或者多个Image使用不同的aes Key。出于安全性考虑,建议使用多把不同的aes key。
-
AES-128 Key
echo '00102030405060708090A0B0C0D0E0FF' | xxd -r -ps > aesKey_128.bin
-
AES-256 Key
echo '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F' | xxd -r -ps > aesKey_256.bin
-
IV
echo '303132333435363738393A3B3C3D3E3F' | xxd -r -ps > IV.bin
将上述生成的n把AES key,替换project/image/security_boot_tools/下的aesKey目录下对应的需要用到的key binary文件即可。
4.2. 配置文件sign_image.config¶
进入project/image/security_boot_tools/下,修改sign_image.config文件。
sign_image.config文件中参数说明:
Name | Description |
---|---|
rsalen | rsalen的值为 2048,各阶段boot code都由该参数指定RSA2048 |
ipl_abk | IPL的image version版本号,anti-rollback func used,当ipl_abk=0时表示不使用antirollback |
ipl_aeskeynum | IPL加密功能。aeskey目录下有4把aes128和2把aes256,可以选择使用2把aes256和4把aes128中的一把,和aeskeylen搭配使用,当ipl_aeskeynum=0时表示不使用aes加密。以ipl_aeskeylen=128&&ipl_aeskeynum=1为例,说明IPL将使用security_boot_tools/aeskey/aesKey128_1.bin作为aes-key进行加密 |
ipl_aeskeylen | IPL加密功能。aeskey目录下有4把aes128和2把aes256,aeskeylen的值为128 或者256。当ipl_aeskeylen=0时表示不使用aes加密,和ipl_aeskeynum搭配使用。 |
ipl_IV | IPL加密方式一定是cbc。如果加密的话,此项填入IV的binary的名字 |
sw_debug | 测试时代替OTP_Secure_boot使用,调试模式 |
ipl_cust_abk | IPL_CUST的版本号, antirollback func used |
Name | Description |
---|---|
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值file 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值file name |
kernel_enable | 是否使能以上参数,若为0,则默认使用image的参数 |
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值file 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值file name |
image_abk | 预保留,若使用anti rollback功能,填写在对应image的abk |
4.3. 运行Security_boot_tools¶
实际操作步骤如下:
-
进入project目录,make xxx_defconfig; make clean -j32; make image -j32;
-
进入project/image/security_boot_tools/下,make clean;make;即可生成security_boot_tools/image_secure目录(目录下Image已签章)
如果签章的动作需要在别的目录下做或者需要在不同电脑上签章,Step2中请执行make image_prepare,并把security_boot_tools完整copy到另一个位置,再执行make即可。
注:security_boot_tools生成的image,estar会自动配置bootcmd来验签(或者解密+验签)kernel。默认rootfs会加签,但bootcmd不会验签(或者解密+验签)rootfs。如需验签rootfs,请手动修改bootcmd,增加signature 验签rootfs步骤。
4.4. signature cmd介绍¶
在Uboot阶段需要修改环境变量bootcmd来对Linux Kernel/rtos/ramdiskfs等binary进行验证,其原理是通过sigauth命令来对Binary进行验签和解密:
sigauth <Binary_Addr> <KEY_Addr> [--aes] <Binary_Addr>: 需要验签(或者加密)的binary在ddr里的加载地址。 <KEY_Addr>: IPL_CUST在ddr里的加载地址,sigauth cmd会根据IPL_CUST头部信息找到IPL_CUST内部的public N key。一般在启动过程IPL_CUST固定被加载在0x21000000位置。 [--aes]: 可选项,表示验签前是否先对binary进行aes解密。sigauth cmd会自动根据binary的appended data找到指定的OTP AES key和指定的AES解密模式。
U-boot启动pure linux,验签前:
EX: setenv bootcmd ' dcache on; loados nand 0x23000000 KERNEL ${kernel_file_size}; bootm 0x23000000; dcache on; loados nand 0x23000000 RECOVERY ${recovery_file_size}; bootm 0x23000000;
U-boot启动pure linux,验签后:
EX: setenv bootcmd ' dcache off; loados nand 0x23000000 KERNEL ${kernel_file_size}; sigauth 23000000 0x21000000 ; dcache on;bootm 0x23000000; dcache on; loados nand 0x23000000 RECOVERY ${recovery_file_size}; bootm 0x23000000;
如果镜像使用了加密,请在对应的启动方式上的sigauth命令的尾部加上 --aes。
U-boot启动dualos,验签前:
EX: setenv bootcmd ' loados nand by_header MISC by_header; loados nand by_header RTOS by_header;bootm start ${loados_addr};bootm loados;bootm prep;wakeupcpu 3 s 0x2ef08000; loados nand by_header RAMDISK by_header; loados nand by_header KERNEL by_header;dcache off;bootm ${loados_addr};
U-boot启动dualos,验签后:
EX: setenv bootcmd ' loados nand by_header MISC by_header; loados nand by_header RTOS by_header;sigauth ${loados_addr} 0x21000000;bootm start ${loados_addr};bootm loados;bootm prep;wakeupcpu 3 s 0x2ef08000; loados nand by_header RAMDISK by_header;sigauth ${loados_addr} 0x21000000; loados nand by_header KERNEL by_header;sigauth ${loados_addr} 0x21000000;dcache off;bootm ${loados_addr};
如果customer有验签rootfs的需求,在Uboot阶段需要设定环境变量来对Linux Rootfs进行验证,请参考如下Command设定
在ENV中设定rootfs_size的大小:
rootfs_size <rootfs_sieze>; saveenv; EX: rootfs_size 1af100; saveenv;
在对应的存储介质读取rootfs后加上:
dcache off;sigauth <Binary_Addr> <KEY_Addr> [--aes];dcache on; EX: setenv bootcmd ' dcache off; loados nand 0x22000000 roofs 0x600000; sigauth 22000000 0x21000000 ; loados nand 0x23000000 KERNEL ${kernel_file_size};sigauth 23000000 0x21000000; dcache on; bootm 0x23000000; loados nand 0x23000000 RECOVERY ${recovery_file_size}; bootm 0x23000000;
5. OTP 栏位介绍¶
OTP各个bit只能烧写一次,一旦置1后不可置0,请在确认需要的场合下执行烧写动作!
5.1. OTP Command Format¶
烧录芯片的OTP栏位一般是在uboot下使用otpctrl进行烧录操作。烧录完OTP后,一般需要下次启动才会生效。 如下图,列出在UBOOT下执行OTP烧录的两个COMMAND,分别能对OTP进行读写的动作。
WRITE COMMAND:
READ COMMAND:
ERROR CODE:
FF01: 无效的COMMAND
FF02: 无效的OTP地址
FF03: 无效的OTP执行许可证
5.2. security boot相关的OTP栏位¶
对于Ifado系统芯片,如果客户使用security boot功能,需要关注OTP以下内容:
OTP | command ID | length(byte) | Description |
---|---|---|---|
OTP_RSA_N | 0X00 | 256 | 保存用于验签IPL的RSA public key的 N 值 |
OTP_RSA_E | 0X01 | 4 | 保存用于验签IPL的RSA public key的 E 值 |
OTP_SECURITY_BOOT | 0X02 | 1 | 启动security boot功能开关,需要在确认正确烧录完RSA/AES key才开启 |
OTP_RSA_KEY_LOCK | 0X03 | 4 | 对OTP内的RSA Public Key栏位进行LOCK的动作,LOCK后不可再修改,客户可根据需求使用 |
OTP_RSA_KEY_BLOCK | 0X04 | 4 | 对OTP内的RSA Public Key栏位进行BLOCK的动作,BLOCK后CPU无法读出OTP内的RSA Public Key,客户可根据需求使用 |
OTP_KEY1 | 0X05 | 16 | 第1把AES128 key |
OTP_KEY2 | 0X06 | 16 | 第2把AES128 key,也可以和OTP_KEY1组合成第1把AES256 key |
OTP_KEY3 | 0X07 | 16 | 第3把AES128 key |
OTP_KEY4 | 0X08 | 16 | 第4把AES128 key,也可以和OTP_KEY3组合成第2把AES256 key |
OTP_AES_KEY1_LOCK | 0X0D | 4 | LOCK后不可再修改即16byte OTP内容非0bit也不可置1,客户可根据需求使用 |
OTP_AES_KEY1_BLOCK | 0X0E | 4 | BLOCK后不可再修改,只有HW aesdma能够访问而CPU无法访问,客户可根据需求使用 |
OTP_AES_KEY2_LOCK | 0X0F | 4 | LOCK后不可再修改,即16byte OTP内容非0bit也不可置1,客户可根据需求使用 |
OTP_AES_KEY2_BLOCK | 0X10 | 4 | BLOCK后不可再修改,只有HW aesdma能够访问而CPU无法访问,客户可根据需求使用 |
OTP_AES_KEY3_LOCK | 0X11 | 4 | LOCK后不可再修改,即16byte OTP内容非0bit也不可置1,客户可根据需求使用 |
OTP_AES_KEY3_BLOCK | 0X12 | 4 | BLOCK后不可再修改,只有HW aesdma能够访问而CPU无法访问,客户可根据需求使用 |
OTP_AES_KEY4_LOCK | 0X13 | 4 | LOCK后不可再修改,即16byte OTP内容非0bit也不可置1,客户可根据需求使用 |
OTP_AES_KEY4_BLOCK | 0X14 | 4 | BLOCK后不可再修改,只有HW aesdma能够访问而CPU无法访问,客户可根据需求使用 |
OTP_ROM_SELECT_AES_KEY | 0X24 | 4 | 选择OTP中哪一把AESKey对IPL进行解密,一旦写入此OTP,IPL必须使用CBC加密 |
OTP_ROM_SELECT_AES_KEY_LOCK | 0X25 | 4 | LOCK后OTP_ROM_SELECT_AES_KEY不可再修改。 |
各个OTP栏位的烧录方法举例说明如下。
5.2.1. OTP_RSA_N (0x0) / OTP_RSA_E (0x1)¶
对于现成的需要rsa-public.pem文件,需要先将pem格式转化成可以用于烧录的格式。使用以下cmd生成rsaKey.txt,rsaKey.txt中的command在UBOOT下烧写OTP。
./key_proc.py --exportkey_reverse --rsa=public.pem
举例使用现成的pem文件转化后的rsaKey.txt内容如下,直接复制粘贴到uboot 菜单命令行下执行即可:
####### RSA N-Key ######## otpctrl -w 0x0 0x0 0x58653431;otpctrl -w 0x0 0x4 0x06ba8f4a;otpctrl -w 0x0 0x8 0x5caee61a;otpctrl -w 0x0 0xc 0x1912648d;otpctrl -w 0x0 0x10 0xb3b77f1c;otpctrl -w 0x0 0x14 0xd116e973;otpctrl -w 0x0 0x18 0x74f82967;otpctrl -w 0x0 0x1c 0xf85d78e8;otpctrl -w 0x0 0x20 0x55a92d7a;otpctrl -w 0x0 0x24 0xf807ef92;otpctrl -w 0x0 0x28 0xeaca7ab8;otpctrl -w 0x0 0x2c 0x2d33149a;otpctrl -w 0x0 0x30 0xc47f6cfb;otpctrl -w 0x0 0x34 0x99d0fb2b;otpctrl -w 0x0 0x38 0xb94e529f;otpctrl -w 0x0 0x3c 0x09d1e66a; otpctrl -w 0x0 0x40 0x93614b62;otpctrl -w 0x0 0x44 0x40db5115;otpctrl -w 0x0 0x48 0x4d37ec4c;otpctrl -w 0x0 0x4c 0xd7ac36da;otpctrl -w 0x0 0x50 0x8bbef7bb;otpctrl -w 0x0 0x54 0x459ffe82;otpctrl -w 0x0 0x58 0xea5aa7ed;otpctrl -w 0x0 0x5c 0x979ac988;otpctrl -w 0x0 0x60 0xd9ad7843;otpctrl -w 0x0 0x64 0xb086c544;otpctrl -w 0x0 0x68 0x75248853;otpctrl -w 0x0 0x6c 0xd0c61f34;otpctrl -w 0x0 0x70 0xd4fd028a;otpctrl -w 0x0 0x74 0x93037bd3;otpctrl -w 0x0 0x78 0x2b3cd0e2;otpctrl -w 0x0 0x7c 0x12b49f2d; otpctrl -w 0x0 0x80 0x72fc0405;otpctrl -w 0x0 0x84 0xc1fb6cfd;otpctrl -w 0x0 0x88 0xb42fb860;otpctrl -w 0x0 0x8c 0xa06e8c6e;otpctrl -w 0x0 0x90 0x43870bc3;otpctrl -w 0x0 0x94 0xb97ebe88;otpctrl -w 0x0 0x98 0x45113bd1;otpctrl -w 0x0 0x9c 0xb7974436;otpctrl -w 0x0 0xa0 0x47c3d001;otpctrl -w 0x0 0xa4 0x3611716d;otpctrl -w 0x0 0xa8 0x67abc2d5;otpctrl -w 0x0 0xac 0x773ac1cd;otpctrl -w 0x0 0xb0 0x7d1ee609;otpctrl -w 0x0 0xb4 0xc72e97ee;otpctrl -w 0x0 0xb8 0x91af8bd5;otpctrl -w 0x0 0xbc 0xd516243d; otpctrl -w 0x0 0xc0 0x949b2522;otpctrl -w 0x0 0xc4 0x3d73c4d7;otpctrl -w 0x0 0xc8 0xcf2fde53;otpctrl -w 0x0 0xcc 0xbd35d242;otpctrl -w 0x0 0xd0 0x2362de0f;otpctrl -w 0x0 0xd4 0x8d9f7418;otpctrl -w 0x0 0xd8 0x861f69d5;otpctrl -w 0x0 0xdc 0x0736f5ff;otpctrl -w 0x0 0xe0 0x7655b44e;otpctrl -w 0x0 0xe4 0x06198429;otpctrl -w 0x0 0xe8 0xe0975a88;otpctrl -w 0x0 0xec 0x6fcec320;otpctrl -w 0x0 0xf0 0x49480b57;otpctrl -w 0x0 0xf4 0xea4a5ee3;otpctrl -w 0x0 0xf8 0x6502ddee;otpctrl -w 0x0 0xfc 0xd6d17ae2; ####### RSA E-Key ######## otpctrl -w 0x1 0x0 0x00010001
注意:因为uboot 菜单命令行的buf缓存长度有限制,不可直接将64条otpctrl命令当成一次复制粘贴回车运行。建议至少分成4次执行。
5.2.2. OTP_SECURE_BOOT (0x2)¶
确认RSA/AES key都烧录后,启动security boot功能(下次启动才会生效):
otpctrl -w 0x2 0x0 0xFFFFFFFF
检查security boot功能是否已开启:
otpctrl -r 0x2
5.2.3. OTP_RSA_KEY_LOCK (0x3) / OTP_RSA_KEY_BLOCK (0x4)¶
非必要操作,客户可根据需求使用。
确认LOCK和BLOCK rsa key(下次启动才会生效):
otpctrl -w 0x3 0x0 0xFFFFFFFF otpctrl -w 0x4 0x0 0xFFFFFFFF
检查LOCK和BLOCK是否已开启:
otpctrl -r 0x3 otpctrl -r 0x4
5.2.4. OTP_AES128_KEY (0x5~0x8)¶
如果客户使用security boot的签章+加密功能,烧录AES KEY是必要操作。
如果是制作AES128 KEY:
echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey128_1.bin
烧录AES key到 OTP_KEY1位置:
otpctrl -w 0x5 0x0 0x03020100 otpctrl -w 0x5 0x4 0x07060504 otpctrl -w 0x5 0x8 0x0B0A0908 otpctrl -w 0x5 0xC 0x0F0E0D0C
如果是制作AES256 KEY:
echo '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F' | xxd -r -ps > aesKey256_1.bin
烧录AES key到 OTP_KEY1和OTP_KEY2位置:
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
烧录4把AES128 key或者2把AES256 key的操作同理。
5.2.5. OTP_AES128_KEY1~4_LOCK (0xD,0xF,0x11,0x13) / OTP_AES128_KEY1~4_BLOCK (0xE,0x10,0x12,0x14)¶
非必要操作,客户可根据需求使用。
确认LOCK和BLOCK 第一把AES128 key(下次启动才会生效):
otpctrl -w 0xD 0x0 0xFFFFFFFF otpctrl -w 0xE 0x0 0xFFFFFFFF
第一把AES128 key检查LOCK和BLOCK是否已开启:
otpctrl -r 0xD otpctrl -r 0xE
确认LOCK和BLOCK 第一把AES256 key(下次启动才会生效):
otpctrl -w 0xD 0x0 0xFFFFFFFF otpctrl -w 0xF 0x0 0xFFFFFFFF otpctrl -w 0xE 0x0 0xFFFFFFFF otpctrl -w 0x10 0x0 0xFFFFFFFF
第一把AES256 key检查LOCK和BLOCK是否已开启:
otpctrl -r 0xD otpctrl -r 0xF otpctrl -r 0xE otpctrl -r 0x10
LOCK和BLOCK4把AES128 key或者2把AES256 key的操作同理。
5.2.6. OTP_ROM_SEL_AESKEY (0x24)¶
如果客户使用security boot的签章+加密功能,烧录OTP_ROM_SEL_AESKEY用来选择OTP中哪一把AESKey对IPL进行解密是必要操作。
如果客户只使用security boot的签章,不可烧录OTP_ROM_SEL_AESKEY,一旦写入此OTP,IPL必须使用CBC加密。
Example:
-
选择 AESKEY128_1
otpctrl -w 0x24 0x0 0x80
-
选择 AESKEY128_2
otpctrl -w 0x24 0x0 0x90
-
选择 AESKEY128_3
otpctrl -w 0x24 0x0 0xA0
-
选择 AESKEY128_4
otpctrl -w 0x24 0x0 0xB0
另外IPL可以使用AES256解密,OTP中AESKEY256实际上是由OTP中两把AES128组合而成,组合和设置方式举例如下:
-
选择 AESKEY256_1(Composition mode: AES128key1 + AES128key2)
otpctrl -w 0x24 0x0 0x40
-
选择 AESKEY256_2(Composition mode: AES128key3 + AES128key4)
otpctrl -w 0x24 0x0 0x50
5.2.7. OTP_ROM_SEL_AESKEY_LOCK (0x25)¶
非必要操作,客户可根据需求使用。 确认LOCK和BLOCK OTP_ROM_SEL_AESKEY里的内容(下次启动才会生效):
otpctrl -w 0x25 0x0 0xFFFFFFFF
检查LOCK和BLOCK是否已开启:
otpctrl -r 0x25
5.3. anti-rollback相关的OTP栏位¶
如果客户不使用anti-rollback功能,将security_boot_tools/sign_image.config里的所有Image version默认保持为0即可。
如果客户使用anti-rollback功能,才需要关注OTP以下内容:
OTP | command ID | length(bit) | Description |
---|---|---|---|
OTP_IPL_ANTI_ROLLBACK | 0x2B | 64 | 保存IPL的OTP version,每1个bit表示一次进阶版本,最多可进版64次 |
OTP_IPL_CUST_ANTI_ROLLBACK | 0x2C | 16 | 保存IPL_CUST的OTP version,每1个bit表示一次进阶版本,最多可进版16次 |
OTP_UBOOT_ANTI_ROLLBACK | 0x2C | 24 | 保存BOOT的OTP version,每1个bit表示一次进阶版本,最多可进版24次 |
OTP_KERNEL_ANTI_ROLLBACK | 0x2C | 24 | 保存KERNEL的OTP version,每1个bit表示一次进阶版本,最多可进版24次 |
各个OTP栏位的烧录方法举例说明如下。
5.3.1. OTP_IPL_ANTI_ROLLBACK (0x2B, OFFSET 0X0, 0X4, MAX 64 bit)¶
IPL 的 Image version 在security_boot_tools/sign_image.config通过修改参数 'ipl_abk'指定。需要确认 Image version 大于烧录的 OTP Version。
烧录 IPL 的 OTP Version 举例:
IPL OTP Version = 1
otpctrl -w 0x2B 0x0 0x00000001
IPL OTP Version = 2
otpctrl -w 0x2B 0x0 0xFFFFFFFF
IPL OTP Version = 33
otpctrl -w 0x2B 0x0 0xFFFFFFFF otpctrl -w 0x2B 0x4 0x00000001
IPL OTP Version = 64
otpctrl -w 0x2B 0x0 0xFFFFFFFF otpctrl -w 0x2B 0x4 0xFFFFFFFF
以此类推。
5.3.2 OTP_IPL_CUST_ANTI_ROLLBACK (0x2C, OFFSET 0X0, MAX 16 bit)¶
IPL_CUST 的 Image version 在security_boot_tools/sign_image.config通过修改参数 'ipl_cust_abk'指定。需要确认 Image version 大于烧录的 OTP Version。
烧录 IPL_CUST 的 OTP Version 举例:
IPL_CUST OTP Version = 1
otpctrl -w 0x2C 0x0 0x0001
IPL_CUST OTP Version = 16
otpctrl -w 0x2C 0x0 0xFFFF
以此类推。
5.3.3 OTP_UBOOT_ANTI_ROLLBACK (0x2C, OFFSET 0X8, MAX 24 bit)¶
UBOOT 的 Image version 在security_boot_tools/sign_image.config通过修改参数 'uboot_abk'指定。需要确认 Image version 大于烧录的 OTP Version。
烧录 UBOOT 的 OTP Version 举例:
UBOOT OTP Version = 1
otpctrl -w 0x2C 0x8 0x000001
UBOOT OTP Version = 24
otpctrl -w 0x2C 0x8 0xFFFFFF
以此类推。
5.3.4 OTP_KERNEL_ANTI_ROLLBACK (0x2C, OFFSET 0XB, MAX 24 bit)¶
KERNEL 的 Image version 在security_boot_tools/sign_image.config通过修改参数 'kernel_abk'指定。需要确认 Image version 大于烧录的 OTP Version。
烧录 KERNEL 的 OTP Version 举例:
KERNEL OTP Version = 1
sotpctrl -w 0x2C 0xB 0x000001
KERNEL OTP Version = 24
otpctrl -w 0x2C 0xB 0xFFFFFF
以此类推。
6. Security BOOT部署步骤¶
OTP只能烧写一次,一旦烧写则无法清除和重烧。为了防止误操作导致系统无法启动甚至IC作废,一般建议调试流程PASS以后,才能进行正式OTP流程。即先烧录部分OTP进行测试,确认调试流程PASS,以后再补充烧录剩余OTP。
调试模式下,Security_boot_tools会将IPL和IPL_CUST header里的AUTH栏位置1,rom code加载IPL、IPL加载IPL_CUST、IPL_CUST加载UBOOT/RTOS/LINUX会根据AUTH标记决定走验签启动流程。
OTP正式模式下,rom code加载IPL、IPL加载IPL_CUST、IPL_CUST加载UBOOT/RTOS/LINUX会根据OTP是否烧录 OTP_SECURITY_BOOT 标记决定走验签启动流程。
6.1. Security Boot调试流程¶
第一步:用户自行生成三组RSA public/private key,替换security_boot_tools/aes/和rsa2048目录下的key文件。详见4.1. 制作RSA key和aes Key。
第二步:使用U-Boot Command otpctrl 烧录RSA Public NKey/Ekey(或AES Key),详见5.2. security boot相关的OTP栏位。
- 调试阶段建议只烧录 OTP_RSA_N / OTP_RSA_E / OTP_RSA_KEY_LEN / OTP_KEY1~4。
- 不建议烧录 OTP_SECURITY_BOOT 栏位,即使在调试阶段错误烧录了OTP内容,该芯片board无法启动签章image,但依然可以用来启动未签章image。
- 不建议烧录 所有 OTP LOCK & BLOCK 栏位,即使调试阶段错误烧录了OTP内容,还有机会检查和修改OTP内容。
- 不建议烧录 OTP_ROM_SELECT_AES_KEY,即使调试阶段错误烧录了OTP AES-key 内容,ROM code依然可以启动未加密签章的IPL。
第三步:根据客户需要配置security_boot_tools配置文件sign_image.config,但在调试阶段以下配置需要注意:
sw_debug=1 #即使OTP没有烧录 OTP_SECURITY_BOOT 栏位,系统启动过程也会走security boot验签和解密流程。 ipl_aeskeynum=0 #因为OTP没有烧录 OTP_ROM_SELECT_AES_KEY,系统启动过程不会对IPL进行解密,因此不使用security_boot_tools对IPL进行加密。 ipl_aeskeylen=0
第四步: 检查系统打印
检查系统打印确认ROM->IPL->IPL_CUST->U-Boot已进行到SecurityBoot的flow。
-
ROM->IPL确认是否走SecurityBoot的方式
ROM验签IPL成功不会有任何log,但验签失败则会打印AUTH ERR(波特率可能需要调为38400或57600,否则乱码)。
-
IPL->IPL_CUST->U-Boot确认是否走SecurityBoot的方式
查看log即可,一般带有Authenticate image关键字,若开启解密流程则还会有AES ECB关键字。
举例如下:
-
U-Boot -> kernel确认是否走SecurityBoot的方式
直接查看bootcmd是否有验签signature。详见4.4. signature cmd介绍。
6.2. Security Boot正式流程¶
调试模式能正常走Secruty boot启动后,说明调试阶段烧录的OTP RSA N/E KEY、AES KEY的步骤是可靠的,后续芯片可以直接复制调试模式总结下来的OTP烧录命令。
正式流程只需要补充烧录部分OTP栏位即可。
第一步:使用U-Boot Command otpctrl 烧录 OTP_SECURITY_BOOT、 RSA KEY的LOCK和BLOCK、OTP_ROM_SELECT_AES_KEY等。
第二步:配置security_boot_tools配置文件sign_image.config:
sw_debug = 0 ipl_aeskeynum = 1 #举例使用第一把AES-128 KEY ipl_aeskeylen = 128
第三步: 检查系统打印
- 烧录后同样按照7.1的方法确认ROM->IPL->IPL_CUST->U-Boot->Kernel有走到SecurityBoot并能启动到U-Boot,到此ROM->IPL->IPL_CUST->U-Boot->Kernel的SecurityBoot flow和OTP相关验证已经PASS。