TrustZone应用¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 05/22/2023 |
1. 搭建启动流程的信任链¶
1.1. 各阶段镜像的签名和加密¶
Security boot要求开发者使用private key对各阶段镜像进行签名,而对应的public key烧录到SGS chip的OTP中,并烧录OTP打开chip的security boot功能,则在TrustZone概述1.4章节介绍的芯片启动流程中,通过在每个阶段检查和验证下一阶的软件的签名,保证整个启动过程的软件都是可信的,防止恶意软件的注入和未经授权的修改。
完整security boot原理和SOP可以参考《Security Boot使用参考》。
1.1.1 刻录OTP¶
Generate Private Key:
- openssl genrsa -out private.pem 2048
Generate Public Key:
- openssl rsa -in private.pem -out public.pem -outform PEM -pubout
通过Tool (key_proc.py) 可产生U-Boot command scripts:
- ./key_proc.py --exportkey_reverse --rsa=public.pem
上一步生成的rsaKey.txt,根据其内容在boot cmd下烧录public key到OTP,例如:
-
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;
-
otpctrl -w 0x1 0x0 0x00010001
使能secure boot:
- otpctrl -w 0x2 0x0 0xFFFFFFFF
建议开发过程先用调试模式,确认串通securityboot flow后再考虑一次性烧录所有OTP。否则可能由于错误的操作导致OTP烧录后IC作废。
1.1.2 编译alkaid自动签章所有镜像¶
SGS提供的project源码包包含自动签名系统镜像的工具,project/image/security_boot_tools。自动签章步骤:
-
vim project/image/security_boot_tools/config/config.ini,配置private key文件和指定key长度,是否使用调试模式等。
-
按照章节2.2重新编译系统镜像,生成project/image/out/images/后,执行
cd project/image/security_boot_tools;make;对images进行private key签名。重新烧录images到开发板上即可。 -
修改bootcmd,让boot在加载kernel的过程中对kernel进行验签:
setenv bootcmd ‘ nand read.e 0x23000000 KERNEL ${kernel_file_size};bootm start 0x23000000;bootm loados; bootm prep; sigauth xzdec 0x22000000; bootm go;sav;
1.2. TA镜像的签名¶
生成原始的TA镜像文件之后将会对该文件进行签名生成最终的xxx.ta文件,该文件会被保存在REE的文件系统中。对原始TA镜像文件和签名是通过调用optee_os/scripts/sign_encrypt.py,使用optee_os/keys/目录下的RSA2048私钥来完成的。开发者需要使用自己生成的私钥对ta进行签名,将对应的公钥替换optee_os/keys/目录下用于运行过程的验签,optee_os需要重新编译。
-
openssl genrsa -out /path/to/private_key.pem 2048
-
openssl rsa -in /path/to/private_key.pem -pubout -out /path/to/public_key.pem
-
vim optee_os/mk/config.mk 修改
-
TA_SIGN_KEY 为指定的/path/to/private_key.pem路径名和文件名
-
TA_PUBLIC_KEY 为指定的/path/to/public_key.pem路径名和文件名
-
sign_encrypt.py digest --key /path/to/private_key.pem --uuid $(user-ta-uuid) --in (user-ta-uuid).stripped.elf (产生(user-ta-uuid).dig)
-
base64 --decode $(user-ta-uuid).dig | openssl pkeyutl -sign -inkey /path/to/private_key.pem -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:digest -pkeyopt rsa_mgf1_md:sha256 | base64 > (user-ta-uuid).sig (产生(user-ta-uuid).sig)
-
sign_encrypt.py stitch --key /path/to/public_key.pem --uuid $(user-ta-uuid) --in (user-ta-uuid).stripped.elf (产生(user-ta-uuid).ta)
1.3. TA镜像的加密¶
TA在编译阶段可以对内容加密。而载入TA时,若发现是加密过的TA,则会做解密的动作。
1.3.1 TA加密的选项¶
-
在TA的Makefile中,加上CFG_ENCRYPT_TA=y。以Hello world example为例,即在optee_examples/hello_world/ta/Makefile中加一行CFG_ENCRYPT_TA=y。如此编译出来的TA内容即会被加密过。
-
在OPTEE的Makefile中并不需要加上CFG_ENCRYPT_TA=y选项。
1.3.2 Key的指定¶
- TA_ENC_KEY:编译TA过程中,用来加密TA的key。在optee_os/ta/arch/arm/link.mk中指定,在系统中会以tee_otp_get_ta_enc_key() 的行为产生这把key,而默认的tee_otp_get_ta_enc_key() 行为是以HUK来产生TA_ENC_KEY。图1中的TA_ENC_KEY即是以默认的HUK所产生的。请注意,这部分原生代码仅做为演示功能,请替换自己的key。

图1 TA key的指定
1.4. 安全储存¶
1.4.1 安全储存介绍¶
安全储存是TEE用来储存资料的方式,只能由TA存取。储存的内容包括:
- 密钥
- 一般数据
OPTEE包含两种安全储存:
- REE-FS
- 以REE档案系统為储存
- CFG_REE_FS=y
- Replay Protected Memory Block(RPMB)
- eMMC中一个具有安全属性的分区
- CFG_RPMB_FS=y
SGS chip上默认支援REE-FS,这里皆以REE-FS做介绍。
1.4.2 档案操作流程¶
- TA呼叫GP安全储存API去寫入一個persistent object
- 呼叫TEE安全储存服務中的系统呼叫
- 接著呼叫TEE档案操作,将数据加密,並送REE的档案操作及加密過的数据給TEE supplicant
- TEE supplicant收到后将加密过后的数据储存在REE档案系统中
1.4.3 安全储存密钥管理¶
OP-TEE在开机时会先产生一把SSK放在安全內存中,产生的流程如下图:

图2 开机时产生SSK流程
安全储存会用到三种密钥

图3 安全储存的三种密钥
- Secure storage key(SSK)
- 每个装置上OP-TEE安全储存唯一的一把密钥
- 在开机时产生,并且储存在安全內存中
- SSK由hardware unique key(HUK)及Chip ID/SSK String做HMAC-SHA256所产生
- SSK String是为了用做避免装置上其他系统同时产生出相同的SSK
- TA storage key(TSK)
- 每个装置上TA唯一的一把密钥
- 由SSK及TA UUID做HMAC-SHA256所产生
- File encryption key(FEK)
- 每个档案唯一的一把密钥
- 用来对档案加解密
- 以PRNG产生,以TSK加密后储存在meta file中
1.4.4 安全储存的移植¶
- SGS OTP上HUK及Chip ID的储存方式
- 有OTP_Key1~OTP_Key8共八把密钥(128-bits)。可取任意一把来做为HUK的储存栏位
- 有UUID及UUID2共两个栏位 (64-bits)。可取任一栏位来做为Chip ID的储存栏位
- OP-TEE中与密钥管理有关的编译选项
- CFG_CORE_HUK_SUBKEY_COMPAT(预设值为y)。设定SSK的产生是否相容于HUK与Chip ID及SSK String的方式
- CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID(预设值为n)。设定Chip ID是否可由OTP die ID的方式取得
- 密钥管理中可以客制化的API
- tee_otp_get_hw_unique_key():平台取得HUK的方式。一定要实现
- tee_otp_get_die_ie():平台取得Chip ID的方式
1.4.5 安全储存的效能测量¶
OPTEE xtest有提供安全储存的效能测量的测项
- ./xtest –t benchmark 1001(测试写入)
- ./xtest –t benchmark 1002(测试读取)
- ./xtest –t benchmark 1003(测试再写入)

图4 安全储存的效能测量