跳转至

SECURITY_BOOT使用参考


REVISION HISTORY

Revision No.
Description
Date
1.00
  • Initial release
  • 05/29/2024
    1.10
  • add otpctrl write limit
  • 05/26/2025
    1.20
  • remove "otpctrl aes/rsa" limitation
  • 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 KeyRSA Public Key,加密和解密使用同一把AES Key

    1. 验签流程中所用的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中用来做签章验证的动作。

    2. 验签流程中所用的AES KeyOTP Key,该把Key使用之前需要烧录到OTP存储单元中,在使用的时候,由Hardware载入到crypto engine进行使用,可以在整个boot flow中用来做AES解密的动作。OTP AES Key的内容由用户自定义,所以由用户维护。

    1.1.2. 流程介绍

    1. 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不会被篡改。

    2. 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也不会被篡改。

    3. 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。

    4. 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 KeyROM code用来验证IPL的签章所使用的RSA Public Key,由N-keyE-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 KeyRSA 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。

    需要注意的是:

    1. Header2中的所有数据都是不安全的,Header1中的数据经过验签是安全的。所以如果是SIG or SIG+AES方案,则验签成功后,取H1的Load/RUN addr进行下一步动作。
    2. Header2必须加的原因是UBOOT解压时,需要用到size & CRC等数据。
    3. 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 writedata
      

      READ COMMAND:

      otpctrl -r 0x5
      

      Example:

      制作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 writedata
      

      READ COMMAND:

      otpctrl -r 0x6
      

      Example:

      制作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 writedata
      

      READ COMMAND:

      otpctrl -r 0x7
      

      Example:

      制作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 writedata
      

      READ COMMAND:

      otpctrl -r 0x8
      

      Example:

      制作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 writedata
      

      READ COMMAND:

      otpctrl -r 0x5
      otpctrl -r 0x6
      

      Example:

      制作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 writedata
      

      READ COMMAND:

      otpctrl -r 0x7
      otpctrl -r 0x8
      

      Example:

      制作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 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xD
      
    • LOCK AESkey2

      WRITE COMMAND:

      otpctrl -w 0xF 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xF
      
    • LOCK AESkey3

      WRITE COMMAND:

      otpctrl -w 0x11 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0x11
      
    • LOCK AESkey4

      WRITE COMMAND:

      otpctrl -w 0x13 0x0 0xFFFFFFFF
      

      READ 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 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xA1
      
    • LOCK 1k ~2K

      WRITE COMMAND:

      otpctrl -w 0xA2 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xA2
      
    • LOCK 2k~3K

      WRITE COMMAND:

      otpctrl -w 0xA3 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xA3
      
    • LOCK 3k~4K

      WRITE COMMAND:

      otpctrl -w 0xA4 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xA4
      
    • LOCK 4k~5K

      WRITE COMMAND:

      otpctrl -w 0xA5 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xA5
      
    • LOCK 5k~6K

      WRITE COMMAND:

      otpctrl -w 0xA6 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xA6
      
    • LOCK 6k~7K

      WRITE COMMAND:

      otpctrl -w 0xA7 0x0 0xFFFFFFFF
      

      READ COMMAND:

      otpctrl -r 0xA7
      
    • LOCK 7k~8K

      WRITE COMMAND:

      otpctrl -w 0xA8 0x0 0xFFFFFFFF
      

      READ 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

      1. IPL.bin需先Insert CUST Key (Public Key),然后签章必须是由OTP KEY所生成

      2. IPL_CUST.bin需先Insert CUST Key (Public Key),然后在通过CUST Key (Private Key) 生成签章,这边Insert的Key为用来验证U-Boot和Linux Kernel的签章

    • with AES

      1. IPL.bin需先Insert CUST Key (Public Key),然后签章必须是由OTP KEY所生成

      2. IPL_CUST.bin需先Insert CUST Key (Public Key),然后再通过CUST Key (Private Key) 生成签章,但不需要进行AES加密。这边Insert的CUST Key (Public Key)为用来验证U-Boot和Linux Kernel的签章。

      3. 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

    1. 生成RSA私钥

      openssl genrsa -out private.pem 2048
      
    2. 生成RSA公钥

      openssl rsa -in private.pem -out public.pem -outform PEM -pubout
      

    3.2.2. RSA4096

    1. 生成RSA私钥

      openssl genrsa -out private.pem 4096
      
    2. 生成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.binu-boot.xz.img.bin部分签章.

    USB不加密:

    1. IPL Insert Key,通过key_proc.py执行:

      ./key_proc.py --insert --rsa=./public.pem  -f ./IPL_usb.bin
      
    2. IPL 制作签章,通过key_proc.py执行:

      ./key_proc.py --sign --rsa=./private-otp.pem -f ./IPL_usb.cipher.bin
      

      执行后会生成IPL_usb.cipher.sig.bin。

    3. UBOOT 制作签章,通过key_proc.py执行:

      ./key_proc.py --sign --rsa=./private.pem -f u-boot.xz.img.bin
      

    USB加密:

    1. IPL Insert Key,通过key_proc.py执行:

      ./key_proc.py --insert --rsa=./public.pem --IV=IV.bin -f ./IPL_usb.bin
      

      执行后会生成IPL_usb.cipher.bin。

    2. IPL 制作签章,通过key_proc.py执行

      ./key_proc.py --sign --rsa=./private-otp.pem -f ./IPL_usb.cipher.bin
      

      执行后会生成IPL_usb.cipher.sig.bin。

    3. 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不加密:

    1. 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。

    2. 制作签章,通过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不加密:

    1. Insert Key,通过key_proc.py执行:

      ./key_proc.py --insert --rsa=./public.pem -f ./IPL_CUST.bin
      

      执行后会生成IPL_CUST.cipher.bin。

    2. 制作签章,通过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,实际操作步骤如下:

    1. 进入project目录,make xxx_defconfig; make clean -j32; make image-nocheck -j32;

    2. 进入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
    3. 进入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

    4. (仅 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. 签章验证

    1. 将完成签章的Images刻录至flash中,刻录后如能正常进入U-Boot,表示从IPL至U-Boot的签章是没有问题的。

    2. 在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;
        
    3. 若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 Separation3.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。

    1. ROM->IPL确认是否走SecurityBoot的方式

      ROM验签IPL成功不会有任何log,但验签失败则会打印AUTH ERR,所以可以烧入未签章的IPL到flash,若ROM->IPL已进行到SecurityBoot的flow,则会报AUTH ERR。

    2. 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 连接
    1. 开发板上电并关闭串口

      • uboot控制台下直接输入debug,然后关闭串口终端

      • kernel下,则输入11111,然后关闭串口终端

    2. Tool配置

      img

    3. 进入OTP Burn Tool

      img

    4. OTP Burn Tool主界面

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

      img

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

      img

    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. 使用说明
    1. Write:UI需要写入的位置填好后,点击Write写入OTP,如报错,请根据表1/ 2/ 3检查对应格式;

      image-20230814105307264

      注意:

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

      image-20230814105409040

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

      image-20230814105502363

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

      image-20230814105518783

    2. Read:读出OTP的值;

      image-20230814105803768

    3. Clear:清空UI所有数据;

      image-20230814110135408

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

      image-20230814110155299

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

      image-20230814110206415

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

      image-20230814110239156

    7. Fold: 折叠隐藏字段。

      image-20230814110249536

    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!

    image-20230814110500720


    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以后,才能进行正式流程。

    1. 签章和加密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 签章

    2. 烧录OTP(ALL)

      从第一套分区启动,使用U-Boot Command或Linux Tool烧录所有OTP case。

      注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。

    3. 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进版次数

    暂未支持版本控制。