跳转至

TrustZone应用

REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 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。自动签章步骤:

    1. vim project/image/security_boot_tools/config/config.ini,配置private key文件和指定key长度,是否使用调试模式等。

    2. 按照章节2.2重新编译系统镜像,生成project/image/out/images/后,执行cd project/image/security_boot_tools;make;对images进行private key签名。重新烧录images到开发板上即可。

    3. 修改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 安全储存的效能测量