Tina_Linux_安全_开发指南

Posted 韦东山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tina_Linux_安全_开发指南相关的知识,希望对你有一定的参考价值。

OpenRemoved_Tina_Linux_安全_开发指南

1 概述

1.1 编写目的

介绍TinaLinux 下安全方案的功能。安全完整的方案基于normal 方案扩展,覆盖硬件安全、安全启动(Secure Boot)、安全系统(Secure OS)、安全存储(Secure Storage)、安全应用(Trust Application)、完整性保护(Dm-Verity)、强制访问控制(MAC)等方面。

1.2 适用范围

适用于基于硬件平台: 全志R18、R30、R311、MR133、R328、MR813、MR813B、R329、R818、R818B、R528、V853 芯片。
软件平台: Tina V3.5 及其后续版本。

1.3 相关人员

适用于TinaLinux 平台的客户及相关技术人员。

1.4 配置文件

本文涉及到一些配置文件,在此进行说明。

注意:新SDK 配置文件优先级高于旧SDK 文件优先级。

env.cfg配置文件路径*

tina/device/config/chips/<chip>/configs/<board>/env.cfg #新SDK,优先级高
tina/device/config/chips/<chip>/configs/<board>/linux/env-<kernel-version>.cfg #新SDK,优先
级中
tina/device/config/chips/<chip>/configs/default/env.cfg #新SDK,优先级低
tina/target/allwinner/<board>/configs/env-<kernel-version>.cfg #旧SDK,优先级最低

sys_config.fex路径:

tina/device/config/chips/<chip>/configs/<board>/sys_config.fex #新SDK
tina/target/allwinner/<board>/configs/sys_config.fex #旧SDK,优先级最低

说明:

如果存在uboot-board.dts,uboot 会使用uboot-board.dts 中配置。不存在uboot-board.dts,uboot 会使用sys_config.fex 中的配置。

dragon_toc.cfg配置文件路径:*

tina/device/config/chips/<chip>/configs/default/dragon_toc*.cfg #新SDK,优先级高
tina/device/config/common/sign_config/dragon_toc*.cfg #新SDK,优先级低
tina/target/allwinner/<chip>-common/sign_config/dragon_toc*.cfg #旧SDK,优先级高
tina/target/allwinner/generic/sign_config/dragon_toc*.cfg #旧SDK,优先级低

version_base.mk配置文件路径:

tina/device/config/chips/<chip>/configs/default/version_base.mk #新SDK,优先级高
tina/device/config/common/version/version_base.mk #新SDK,优先级低
tina/target/allwinner/<chip>-common/version/version_base.mk #旧SDK,优先级高
tina/target/allwinner/generic/version/version_base.mk #旧SDK,优先级低

2 安全系统基础

2.1 安全系统介绍

安全系统是基于硬件配合软件的安全解决方案。其主要目的是保障系统资源的完整性、保密性、可用性,从而为系统提供一个可信的运行环境。

2.2 密码学基础介绍

2.2.1 数据加密模型

(1)明文P。准备加密的文本,称为明文。
(2)密文Y。加密后的文本,称为密文。
(3)加解密算法E(D)。用于实现从明文到密文或从密文到明文的一种转换关系。
(4)密钥K。密钥是加密和解密算法中的关键参数。

2.2.2 加密算法

对称加密算法:加密、解密用的是同一个密钥。比如AES 算法。

非对称加密算法:加密、解密用的是不同的密钥,一个密钥公开,即公钥,另一个密钥持有,即
私钥。其中一把用于加密,另一把用于解密。比如RSA 算法。
散列(hash)算法:一种摘要算法,把一笔任意长度的数据通过计算得到固定长度的输出,但不
能通过这个输出得到原始计算的数据。

2.2.3 签名与证书

数字签名:数字签名是非对称密钥加密技术与数字摘要技术的应用。数字签名保证信息是由签名者自己签名发送的,签名者不能否认或难以否认;可保证信息自签发后到收到为止未曾作过任何修改,签发的文件是真实文件。

数字证书:是一个经证书授权中心数字签名的包含公开密钥拥有者信息以及公开密钥的文件,是一种权威性的电子文档。

2.3 TrustZone

TrustZone 是ARM 提出的安全解决方案,旨在提供独立的安全操作系统及硬件虚拟化技术,提供可信的执行环境(Trust Execution Environment)。TrustZone 系统模型如下图所示。TrustZone 技术将软硬件资源隔离成两个环境,分别为安全世界(Secure World)和非安全世界(Normal World),所有需要保密的操作在安全世界执行,其余操作在非安全世界执行,安全世界与非安全世界通过monitor mode 来进行切换。具体可参考《trustzone securitywhitepaper.pdf》。

2.3.1 OP-TEE

运行在安全世界的系统称为安全操作系统。
很多机构基于TrustZone 推出了自己的安全操作系统,基本都会遵循GP(GlobalPlatform)标准。GlobalPlatform 是一个跨行业的国际标准组织,致力于开发、制定并发布安全芯片的技术标准,以促进多应用产业环境的管理及其安全、可互操作的业务部署。
当前Tina 中采用的是OP-TEE 安全系统。OP-TEE 是Linaro 联合其他公司合作开发的基于ARM TrustZone 技术实现的TEE 方案,遵循GP 标准,主要由三部分组成:
• OP-TEE client (optee_client):运行在非安全世界用户空间的客户端API。
• OP-TEE Linux Kernel device driver (optee_linuxdriver):用以控制非安全世界用户空间和安全世界通信的设备驱动。此部分代码在Linux-4.9 mainline 上已经包含。
• OP-TEE Trusted OS (optee_os):运行在安全世界的可信操作系统。

2.3.2 ARM Trusted Firmware

ARM Trusted Firmware(ATF) 是ARM 官方提供的安全世界软件的参考实现。它统一了ARM底层接口标准,包括电源状态控制接口(Power Status Control Interface, PSCI),安全启动需求(Trusted Board Boot Requirements, TTBR),安全监控模式调用(Secure Monitor Call,SMC) 等。它还提供了ARMv8 架构下Exception Level 3(EL3) Secure Monitor 的参考实现。

说明:AW ARM 64 位平台使用ATF 中的bl31 作为Secure Monitor 实现,AW ARM 32 位平台使用OP-TEE 中的SecureMonitor 实现。

2.4 硬件安全模块

ARM TrustZone 技术要求安全非安全使用独立的外设资源。在Tina SOC 系列方案中,我们设计了相关硬件模块来控制资源的安全属性。

2.4.1 SPC

Secure Peripherals Control,配置外设的安全属性,只有在安全环境才可以使用该模块。某外设被设定为安全后,该外设只有在安全世界下才能正常访问,非安全世界写无效,读为0 。

2.4.2 SMC

这里指的是Secure Memory Control(注意与ARM 指令Secure Monitor Call 区分开),配置内存地址的安全属性,只有在安全环境才可以使用该模块。某地址空间的内存被设定为安全后,该空间的内存只有安全世界可访问,非安全世界写无效,读为0。

2.4.3 SID

Secure ID,控制efuse 的访问。efuse 的访问只能通过sid 模块进行。sid 本身非安全,安全非安全均可访问。但通过sid 访问efuse 时,安全的efuse 只有安全世界才可以访问,非安全世界访问的结果为0。

2.4.4 efuse

efuse:一次性可编程熔丝技术,是一种OTP(One-Time Programmable,一次性可编程)存储器。efuse 内部数据只能从0 变成1,不能从1 变成0,只能写入一次。efuse 中区域的划分详见各SOC 的SID spec。

2.4.5 CE

Crypto Engine,硬件加解密加速引擎。支持多种对称加密、非对称加密、摘要以及随机数生成算法等。具体见各SOC 的CE spec。

2.4.6 TZMA

TrustZone Memory Access,TZMA 是配置存储器存在安全区域的控制模块。目前仅R528 包含TZMA 模块,用于配置SRAM 区域的安全属性。

2.5 相关术语

SMC:Secure Monitor Call,ARM 给出的一条指令,可以让CPU 跳转到Monitor(安全)模式执行。
• RPC:Remote Procedure Control Protocol。optee 中,用于操作Linux 下资源的一种机制。比如,optee 中不能读写文件,就通过RPC 调用Linux 下的文件系统来完成。
• REE:Rich Execution Environment。顾名思义,是资源丰富的执行环境,比如常见的Linux,android 系统等。

TEE:Trusted Execution Environment。可信执行环境,即安全执行环境,在这个区域内,所有的代码,资源都是用户可以信任的。
• TA:Trusted Apps,在TEE 下执行的应用程序,完成用户需要保护的任务,比如对密码的保
护。
• PTA:Pesudo Trusted Apps,伪TA,OPTEE 中的一个概念,表明该TA 被集成到了OPTEE OS 中。
• NA:Normal Apps,或称为CA,Client Apps,在REE 下执行的应用程序,完成普通的,不需要保护的任务,比如看普通视频。
• UUID:Universally Unique Identifier,通用唯一识别码。由当前日期和时间,时钟序列,机器识别码(如MAC)组成。
• PRNG:Pesudo Random Number Generator,伪随机数生成器。
• TRNG:True Random Number Generator,真随机数生成器。
• RPMB:Replay Protected Memory Block,是eMMC 中的一个具有安全特性的分区。

3 Secure Boot

Secure Boot,即安全启动,是一个安全系统必不可少的组成部分,是本文后续安全功能的基础。通常来说,Secure Boot 从brom 执行开始,到Linux 启动结束。Secure Boot 主要设计目的:
• 建立完整的安全信任链,确保启动阶段加载的各种镜像是可信的。
• 相关key 的烧写。
• 安全固件版本管理。
• 设置安全的硬件环境,加载并运行Secure OS 等。

3.1 安全启动原理

Tina 安全方案基于私钥签名-公钥验签的业界公认非对称算法实现完整的安全启动方案,具体来说,选择的是RSA2048-SHA256。
先使用私钥给固件进行签名生成安全固件,再将根密钥公钥的SHA256 值即rotpk.bin 烧写至芯
片中efuse 特定区域。启动时,固化在芯片的brom 程序首先会读取efuse 中的rotpk 值,将该值与保存在flash 上的根证书中公钥进行SHA256 运算后的值进行比对,验证根证书中公钥的可信任性。然后会使用flash 上存储的证书链中的一系列公钥来对各个子镜像进行逐级安全校验。

验证顺序为brom->sboot->monitor(仅aarch64)->secure_os->uboot->kernel。efuse 的
不可更改性确保了证书链的可信任,整个流程的设计确保了整个Linux 方案的安全启动。

3.2 生成安全固件

Tina SDK 已经将安全固件制作流程中密钥的生成和必要的签名过程集成在打包脚本内部,所以安全固件的编译及打包流程与非安全固件的几乎一致,只是在最后的打包的时候有差异。非安全固件的打包可参考用户《TinaLinux SDK 开发指南》文档,安全固件的打包步骤如下:

$ source build/envsetup.sh
==> 设置环境变量。
$ lunch
==> 选择方案。
$ make [-jN]
==> 编译,-jN 参数选择并行编译进程数量。
$ ./scripts/createkeys
==> 生成一组用于签名的密钥,不需要每次执行,详见3.2.2小节。生成的密钥路径位于out/BOARD/keys/。
$ pack -s [-d]
==> 打包固件。-s 表示制作安全固件;-d 表示生成的固件包串口信息转到tf卡座输出(可选)。

后续几个小节将对安全固件生成过程中一些注意事项进行说明。

3.2.1 安全固件配置

在执行make 进行编译前,请确保包含如下配置。

3.2.1.1 内核镜像格式配置

执行make menuconfig,确保如下选项配置正确。

Tina Configuration
└─> Target Images
	└─> [ ] Build filesystem for Boot (SD Card) partition
	└─> Boot (SD Card) Kernel format (boot.img)
	└─> [ ] Build filesystem for Boot-Recovery initramfs partition
	└─> Boot-Recovery initramfs Kernel format (boot.img)

3.2.1.2 安全世界内存配置

安全世界使用的内存包含三个部分,分别为:
• Shmem,共享内存,安全与非安全世界通信使用。
• Secure OS 内存,安全世界OS 使用的内存。
• TA 内存,安全应用程序使用的内存。
在Linux 中需要将这一片内存设为保留内存。
(1) 非V853 方案保留内存设置
对于非V853 方案,安全世界使用的这三个部分内存在secure_os 镜像编译时就确定了,但是secure_os 没有开源,因此保留内存具体的地址与大小,请咨询AW 安全接口。

对于非V853 方案,以R328 为例,假设安全世界使用了4M 内存(Shmem 1M,secure os1M,TA 2M),需按照如下补丁修改tina/lichee/linux-4.9/arch/arm/boot/dts/sun8iw18p1.dtsi文件。

diff --git a/arch/arm/boot/dts/sun8iw18p1.dtsi b/arch/arm/boot/dts/sun8iw18p1.dtsi
index 589466f..90c4131 100644
--- a/arch/arm/boot/dts/sun8iw18p1.dtsi+++ b/arch/arm/boot/dts/sun8iw18p1.dtsi
@@ -5,7 +5,7 @@
*/
/* optee used */
-/memreserve/ 0x41a00000 0x00100000; /* optee range : [0x41a00000~0x41b00000], size = 1M
*/
+/memreserve/ 0x41900000 0x00400000; /* optee range : [0x41900000~0x41D00000], size = 4M
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/gpio/gpio.h>

(2) V853 方案保留内存设置
对于V853 方案,只有Secure OS 内存在secure_os 镜像编译时确定,Shmem 与TA 内存用户可以进行动态配置起始位置与大小。
对于V853 方案, 其中Seucre OS 内存在linux 内核dts 文件(tina/lichee/linux-4.9/arch/arm/boot/dts/sun8iw21.dtsi) 中的optee_reserve 节点中设置,如下所示,默认配置起始地址为0x41980000,大小为0x19000。

optee_reserve 
reg = <0 0x41980000 0 0x00019000>;
status = "okay";
;

对于V853 方案,Shmem 与TA 内存需要在tina/device/config/chips/v853/configs//ubootboard.dts 中的optee 节点中进行配置,当前默认的配置如下。

optee 
shm_base = <0x418E0000>;
shm_size = <0x00020000>;
ta_ram_base = <0x41a00000>;
ta_ram_size = <0x00100000>;
;

对于V853 方案:

  1. 如果打开安全启动功能,需要将Secure OS 内存预留的大小修改为0x80000。
  2. 只有安全方案才会使用Shmem 与TA,启动过程中uboot 会解析uboot-board.dts,获取Shmem 与TA 的内存
    信息,并传递给内核,因此不需要额外在内核dts 中配置Shmem 与TA 的预留内存。

3.2.2 签名密钥

注意:客户在首次进行安全固件打包之前,必须运行一次./scripts/createkeys 创建自己的签名密钥,并将创建的秘钥妥善保存。每次执行createkeys 后都会生成新的密钥,因此不用每次都执行,除非需要更换密钥。

createkeys 脚本会根据dragon_toc*.cfg生成一组用于签名的密钥,生成的密钥保存在out/BOARD/keys/目录下。执行pack -s 时,会使用这些密钥分别对相应的镜像进行签名并生成证书。

以R328 为例,其dragon_toc*.cfg文件内容如上图所示。createkeys 依据[key_rsa] 下的keyvalue生成密钥对。打包过程中会将sboot.bin 封装成toc0.fex,将optee/uboot/dts 等封装成toc1.fex。
请将生成的密钥保存到自己的私密目录,其中Trustkey.bin,Trustkey.pem 与rotpk.bin 三个文件(有的方案为RootKey_Level_0.bin, RootKey_Level_0.pem 与rotpk.bin)为根密钥相关文件,要重点保护。
Trustkey.bin 与Trustkey.pem(RootKey_Level_0.bin 与RootKey_Level_0.pem)是根密钥私钥,不能泄漏和丢失。丢失与泄露会导致一系列问题,比如:生成的安全固件无法在芯片上启动、失去防刷机功能等。

3.2.3 安全固件版本管理

注:pack -s 打包完成后,生成的安全镜像位于out/BOARD/keys/目录下,文件名为tina_BOARD_<uart0/card0>_secure_v[NUM].img。其中NUM 为固件版本号,由version_base.mk文件决定。
Tina 提供了一种安全固件防回退机制,具体实现是:在设备启动过程中会比较当前flash 上固件版本与efuse 中版本信息,如果efuse 中版本信息更高,启动失败;如果flash 上固件的版本更高,将此版本信息写入efuse 中,继续启动;如果版本信息一致,正常启动。
说明注意:最多支持更新32 个版本。另外此功能需要烧写efuse,所以务必保证efuse 供电充足。对于部分方案(R328),由于考虑硬
件成本,出厂的设备efuse 供电不足,此功能不可用。

3.3 开启安全启动

完全开启安全启动共需三个前提:

  1. 烧写efuse 中的secure enable bit。
  2. 烧写rotpk.bin 到efuse 中rotpk 区域。
  3. 烧写安全固件到flash 中。

警告
• 不同的IC,efuse 大小不同。efuse 的硬件特性决定了efuse 中每个bit 仅能烧写一次。此外,efuse 中会划分出很多区域,大部分区域也只能烧写一次。详细请参考芯片SID 规范。
• 烧写secure enable bit 后,会让设备变成安全设备,此操作是不可逆的。后续将只能启动安全固件,启动不了非安全固件。
• 默认情况下,通过LiveSuit/PhoenixSuit 烧写安全固件完成时会自动烧写secure enable bit。
• 如果既烧写了secure enable bit,又烧写了rotpk.bin,设备就只能启动与rotpk.bin 对应密钥签名的安全固件;如果只烧写secure enable bit,没有烧写rotpk.bin,此设备上烧写的任何安全固件都可以启动。调试时可只烧写secure enable bit,但是设备出厂前必须要烧写rotpk.bin。
• 为节省成本,某些硬件(R328) 方案上efuse 供电不足,导致不能写入。因此,在所有需要写efuse操作的时候,请注意给efuse 供电。通常在烧写安全固件、升级sboot/uboot、DragonSN 烧key 到efuse 等场景会写efuse。

如何判断secure enable bit 是否烧写?
• 因为只有secure enable bit 烧写后才能启动安全固件,所以如果是安全启动,secure enablebit 就一定烧写了。安全启动过程中有一些特有的打印,如“SBOOT is starting!”、“sbootcommit…”、“OLD version:…”、“NEW version: …”、“secure enable bit: 1”等等,可用来进
行判断。
• 执行cat /sys/class/sunxi_info/sys_info,如果输出的结果中sunxi_secure 为secure,则表明secure enable bit 已经烧写。

如何判断rotpk.bin 是否烧写?
• 执行cat /proc/cmdline,查看输出结果中的rotpk_status 值,如果为1 表明已经烧写。注:当前仅R328/MR813/MR813B/R818/R818B 有开发支持。需要uboot 配置中打开SID_ROTPK_CTRL,同时env 文件中setargs_nor,setargs_nand,setargs_mmc的定义中包含rotpk_status=$rotpk_status。
• 反证法。烧录使用其他key 签名的安全固件(安全版本号一致),如果不能启动,则表明已经烧写rotpk。
• 执行cat /sys/class/sunxi_info/sys_info,如果输出的结果中sunxi_rotpk 为1,则表明rotpk.bin 已经烧写。仅R329/R818/R818B/MR813/MR813B/R528/V853 支持。

3.4 烧写rotpk.bin 与secure enable bit

3.4.1 方法一

方法一为通用方法,所有IC 都支持,主要包含两个步骤:

  1. 使用LiveSuit/PhoenixSuit 烧写安全固件,安全固件烧写完毕时自动烧写efuse 中的secure
    enable bit 位。

  2. 使用DragonSN 工具将rotpk.bin 烧写到设备的efuse 中。

DragonSN 是AW 开发的PC 端烧key(SN 号、MAC 地址、rotpk 等)工具,可以将key 烧
录到private 分区、efuse 或keybox 中,当前仅支持在windows 上运行。DragonSN 与设备
之间通过USB 通信,控制设备烧录配置好的key 信息。

方法一的优缺点:
• 优点:所有IC 都支持;方便调试;
• 缺点:需要使用Windows 端工具;量产时通常需要两个工位。

3.4.1.1 DragonSN 烧写efuse 流程

DragonSN 烧写efuse 流程如下图所示。
uboot 获取到DragonSN 下发的key 数据,将其传送到ATF(aarch64)或者Secure OS(arm32),ATF 或者Secure OS 调用efuse 驱动将key 数据写入到efuse 中。

3.4.1.2 DragonSN 烧写rotpk.bin 步骤

DragonSN 烧rotpk.bin 具体步骤如下:
• 设置burn_key 属性为1。只有burn_key 的值为1,设备才会接收DragonSN 通过usb传过来的信息,进行烧录动作。该属性位于uboot-board.dts或者sys_config.fex文件中[target] 项下。如果未显式配置,按照burn_key=0 来处理。
• 打包安全固件,烧写到flash 中。

• 在PC 端对DragonSN 工具进行配置。打开DragonSNConfig.exe,如上图所示,点击“添加”,在“类型” 一栏下拉菜单中选择rotpk,点击“保存”、“确定”。点击“全局配置”, 设置“烧写模式” 为“安全key”。配置完成后,关闭配置工具。
• 运行DragonSN.exe 工具,配置rotpk.bin 所在的路径。然后将设备通过usb 与PC 连接,重启设备。当DragonSN 提示框显示设备已连接后,开始烧录。为了保证不会烧录错误的rotpk.bin,在烧录过程中,会将PC 端下发的rotpk.bin 与当前flash 上安全固件中根证书公钥的SHA256 值进行对比,匹配后才烧录该rotpk.bin。

3.4.2 方法二

方法二在烧写安全固件完毕时,解析安全固件获取rotpk.bin 并写入efuse,然后再将efuse 中的secure enable bit 置1。当前仅R328/MR813/MR813B/R329/R818/R818B/R528/V853有开发支持。

说明:

• 要支持此功能,需要在uboot 中configs/CHIP_defconfig或者configs/CHIP_tina_defconfig文件中打开如下宏:CONFIG_SUNXI_BURN_ROTPK_ON_SPRITE=y
• 此功能仅在首次烧写安全固件时生效。

方法二的优缺点:
• 优点:量产时比较方便。
• 缺点:烧写固件时默认就烧写了rotpk.bin。

3.4.3 方法三

方法三是在Linux 用户空间烧写rotpk.bin 与secure enable bit。由于rotpk.bin 与secureenable bit 只能在安全环境下读写,而Linux 环境属于非安全环境,因此在用户空间的程序会发送相关命令至安全环境下的TA,TA 收到命令后,在安全环境下对efuse 中的rotpk.bin 和
secure enable bit 进行读写。当前仅R328 有开发支持。

方法三的优缺点:
• 优点:量产比较快,比较适合固件离线烧录(即固件事先已经保存在flash 上,需要时直接组
装到设备)。
• 缺点:需要支持secure os、TA 等,增大内存消耗。

3.4.3.1 API 说明

相关源码位于tina/package/security/optee-rotpk 目录下。

其中librotpk.c 会被编译成库文件,该库提供如下三个API。

  • /**
    
    * write_rotpk_hash() - write rotpk hash to efuse.
    * @buf: input c-style string, should be 32byte hash, with a nul terminated.
      *
    * return value: zero, write success; non-zero, write failed.
      */
      int write_rotpk_hash(const char *buf);
      /**
    * read_rotpk_hash() - read rotpk hash from efuse.
    * @buf: buf used to contain the rotpk hash value.
      *
    * return value: size of hash length.
      */
      int read_rotpk_hash(char *buf);
    

    其中optee-rotpk-demo.c 是一个调用上述API 的demo 程序, 被编译成可执行文件rotpk_na,使用说明如下:

    usage: rotpk_na [options] [hex-string]
    [options]:
    r read rotpk from efuse.
    w write rotpk to efuse.
    hex-string: input hex-string to burn to efuse.
    

    常见的四种使用方法:

    "rotpk_na w",烧写90fa80f15449512a8a042397066f5f780b6c8f892198e8d1baa42eb6ced176f3 到efuse
    的rotpk 区域。
    "rotpk_na w 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", 烧写自定义
    的字符串1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 到efuse的
    rotpk 区域。
    "rotpk_na r",读取efuse 中的rotpk 内容。
    

    注:客户可依据自身需要修改应用程序,库,TA。

3.4.3.2 开启方法

首先,需要开启secure os 与TA/CA 开发环境支持,具体参考第4、5 章。
其次,执行make menuconfig,开启如下选项。

Tina Configuration
Global build settings --->
[*] OP-TEE Support
choose OP-TEE version (optee version x.x.0) --->
Security --->
OPTEE --->
-*- optee-client-x.x
-*- optee-os-dev-kit
<*> optee-rotpk

然后重新打包安全固件并烧写。

3.4.3.3 使用例子
root@TinaLinux:/# tee-supplicant &
root@TinaLinux:/# rotpk_na w
buf_in: 90fa80f15449512a8a042397066f5f780b6c8f892198e8d1baa42eb6ced176f3, size: 64
NA: write efuse hash
NA: init context
NA: open session
TA: create entry!
TA: open session!
NA: allocate memory
NA: invoke command
TA: rec cmd 0x221
TA: keyname:rotpk,key len:32,keydata:
0x90 0xfa 0x80 0xf1 0x54 0x49 0x51 0x2a
0x8a 0x04 0x23 0x97 0x06 0x6f 0x5f 0x78
0x0b 0x6c 0x8f 0x89 0x21 0x98 0xe8 0xd1
0xba 0xa4 0x2e 0xb6 0xce 0xd1 0x76 0xf3
NA: finish with 0

3.5 校验rootfs

3.1 节中提到,Secure Boot 从brom 执行开始,到Linux 启动结束。但是rootfs 没有进行校验,为了校验rootfs 的完整性,将Secure Boot 延展至rootfs,Tina 引入两种方法:uboot校验rootfs 与dm-verity。

警告:

• rootfs 必须为只读才能进行校验。
• rootfs 类型必须是squashfs。

3.5.1 uboot 校验rootfs

由于rootfs 通常来说较大,从flash 中读取以及校验时间都比较长。Tina 上提供了一种在uboot阶段校验rootfs 的方法,可以提取部分rootfs 的数据来进行校验,有效减少校验时间。
注:仅R328/R329/MR813/MR813B/R818/R818B/R528/V853 有开发支持该功能。

3.5.1.1 uboot 校验squashfs rootfs 功能实现

主要思路是:
• 使用extract_suqashfs 工具对squashfs rootfs 进行采样, 具体为每1M 取前面rootfs_per_MB 字节的数据,最后不足1M 的不采样。rootfs_per_MB 在env 中设置,必须为4096 的倍数或者full,其中full 表示对整个rootfs 进行校验;如未设置,默认
取4096 字节。
• 将所有采集的数据组合成新的文件,对该文件进行签名,生成证书。
• 使用update_squashfs 工具将证书附着在squashfs rootfs 的结尾处。
具体来说,使用extract_squashfs 将out/BOARD/image/rootfs.fex 进行采样,获取文件out/BOARD/image/rootfs-extract.fex。使用秘钥SCPFirmwareContentCertPK 对该rootfs-extract.fex 进行签名,生成证书out/BOARD/image/toc1/cert/rootfs.der。然后
使用工具update_squashfs 将该rootfs.der 证书附着在out/BOARD/image/rootfs.fex 的结尾处。启动过程,在uboot 中按照相反的步骤对rootfs 进行校验。
以上操作都是在打包脚本scripts/pack_img.sh 中实现。

3.5.1.2 uboot 校验squashfs rootfs 开启

首先,执行make menuconfig,打开CONFIG_USE_UBOOT_VERIFY_SQUASHFS 选项。

Tina Configuration
└─> Global build settings --->
	└─> [*] Verify squashfs rootfs in uboot

其次,确保uboot 文件lichee/brandy-2.0/u-boot-2018*/configs/CHIP_defconfig中开启了CONFIG_SUNXI_PART_VERIFY=y 的配置。
使能该功能后,在启动过程中,uboot 会出现类似如下的log。

pubkey rootfs valid
partition rootfs verify pass

3.5.2 dm-verity 机制

Tina dm-verity 是为了在启动过程中验证特定分区(通常是rootfs 分区)的完整性而设计的一套解决方案。dm-verity 从启动开始,在整个设备运行过程中,提供对特定分区数据的验证。
dm-verity 在开机过程中,依靠内核提供的device mapper 机制,验证特定分区hash tree 数据。验证通过后,在设备节点上添加dm-verity 设备。以后任何对该特定分区上数据的操作,都会映射到dm-verity 设备节点上,首先对待操作数据所在的block 计算一次hash,将此hash值与该block 在初始hash tree 中对应的hash 进行对比,一旦对比失败,dm-verity 就会返回失败给此次操作的调用者。

Tina dm-verity 主要用在安全平台,是Secure Boot 最后一个环节,目的是校验根文件系统分区的完整性,确保根文件系统的数据没有被篡改。
dm-verity 验证根文件系统分区的流程如上图所示。

3.5.2.1 Initramfs 构建

Tina 启动时,在initramfs 中验证dm-verity table 签名完整性,并挂载dm-verity 分区,因此必须要使用initramfs,同时initramfs 中需要包含有相关的工具,如openssl、veritysetup等。
Tina 3.0 版本之后提供了一个initramfs 生成办法。下面以cowbell-perf1 为例给出构建步骤,其他方案类似。

1. source build/envsetup.sh
2. lunch cowbell_perf1-tina
3. make ramfs_menuconfig

make ramfs_menuconfig 命令对target/allwinner/cowbell-perf1/defconfig_ramfs 进行配置修改,并基于该配置生成initramfs。如果该方案没有defconfig_ramfs,请复制defconfig 为defconfig_ramfs,为节省空间,对于不需要的配置请尽可能关闭。

请查看如下选项是否配置正确:

Tina Configuration
└─> Target Images
└─> [*] customize image name
└─> --- customize image name
└─>Boot Image(kernel) name suffix (boot_ramfs.img/boot_initramfs_ramfs.img)
└─> Rootfs Image name suffix (rootfs_ramfs.img)
└─> System init (busybox-init)
└─> Base system
└─> -*- busybox-init-base-files
└─> [*] Customize busybox init base files options
└─> (busybox-init-base-files_ramfs) PATH for busybox base files
└─> Security --->
└─> Device Mapper --->
└─> <*> cryptsetup
└─> use crypt lib (use libopenssl) --->
└─> <*> dm-verity
└─> Utilities --->
└─> <*> openssl-util
4. make_ramfs [-jN]

警告:
此处必须是make_ramfs,不能是make。

以上步骤执行完后,生成的initramfs 位于out/cowbell-perf1/compile_dir/target/rootfs_ramfs目录下。
通常来说,initramfs 只需要构建一次,可以将构建好的initramfs 保存在一个地方,以免以后重新生成。如需更改initramfs 的内容,才需要重新构建。

3.5.2.2 dm-verity 启用

前提是参考3.5.2.1 小节的说明构建好initramfs。
下面以cowbell-perf1 为例给出构建步骤,其他方案类似。

1. source build/envsetup.sh
2. lunch cowbell_perf1-tina
3. make menuconfig
Tina Configuration
└─> target Images
	└─> [*] ramdisk
		└─> --- ramdisk
			└─> Compression (gzip)
			└─> (../../out/cowbell-perf1/compile_dir/target/rootfs_ramfs) Use external cpio
└─> Global build settings --->
	└─> [*] Device Mapper Verity
  1. make kernel_menuconfig

选中如下配置。

Linux/arm 4.9.118 Kernel Configuration
└─> General setup --->
	└─> [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
	└─> [*] Support initial ramdisks compressed using gzip
└─> Device Drivers --->
	└─> [*] Multiple devices driver support (RAID and LVM) --->
		└─> <*> Device mapper support
            └─> <*> Verity target support
  1. ./scripts/dm-verity-key.sh

注意:

执行该脚本,将在out/cowbell-perf1/verity/keys 下生成一组key,为dm-verity-pri.pem 与dm-veritypub.pem,并复制到package/security/dm-verity/files/目录下,同时将公钥dm-verity-pub.pem 复制到out/cowbell-perf1/compile_dir/target/rootfs_ramfs 下,重命名为verity_key,设备启动时需要使用此公钥来验证rootfs。

警告:

• dm-verity-pri.pem 是私钥,非常重要的隐私数据,用以对dm-verity table 进行签名,请妥善保存。
• 如果不执行此脚本,将使用package/security/dm-verity/files/下默认的key,因此请务必执行一次来替换此目录下的key。每运行一次脚本,就会更新一次key。

  1. make -j
  2. pack -s [-d]

经过以上步骤,可以生成一个支持dm-verity 的安全固件。

3.5.2.3 dm-verity 测试

方法一:查看设备节点

root@TinaLinux:/# ls -l /dev/dm-0 /dev/mapper/rootfs
brw-r--r-- 1 root root 254, 0 Jan 1 08:21 /dev/dm-0
brw------- 1 root root 254, 0 Jan 1 08:21 /dev/mapper/rootfs

如果没有/dev/mapper/rootfs 文件,执行mount -t devtmpfs devtmpfs /dev后即可看到。
• 方法二:查看挂载

root@TinaLinux:/# mount
/dev/mapper/rootfs on /rom type squashfs (ro,relatime)
3.5.2.4 dm-verity 影响

占用flash 空间需要新增dm-verity 相关信息。同时会用到initramfs,导致内核镜像增大。
• 系统性能影响
dm-verity 功能可以提高Tina 系统安全性能,但是从其实现机制来讲,会延长启动时间,降低rootfs 分区的读取速度。

3.6 安全启动代价

3.6.1 启动时间增加

安全启动过程中会逐级对下一阶段运行的镜像进行校验,会增加启动时间。相对于非安全启动,整体会增长500ms 左右(不包括rootfs 的校验)。实际增加时间会因存储介质、硬件CE 版本、cpu/dram 频率等因素的影响而不同。

3.6.2 ota 升级的变化

由3.2 小节可知,安全固件封包与非安全固件有一定的差异,因此在ota 升级时,请确保使用正确的文件。
• 升级optee/uboot/dts/sys_config,需要使用tina/out/BOARD/image/toc1.fex 文件;

• 升级sboot,需要使用tina/out/BOARD/image/toc0.fex 文件;
• 升级linux kernel,需要使用tina/out/BOARD/image/boot.fex 文件;
• 升级rootfs,需要使用tina/out/BOARD/image/rootfs.fex 文件。

4 Secure OS

ARM 利用CPU 分时复用的思路,设计了SMC 指令切换到另外一个特殊状态再结合SOC 级别的硬件IP 构建了被称为ARM TrustZone 的安全技术。
Tina 从SOC 层面支持ARM Trustzone, 但要设计满足Linux 系统安全标准和需求的安全方案,除了实现ARM TrustZone,还必须有一套软件可信执行环境TEE。Tina 采用的OP-TEE便是一种特定安全系统实现,它严格遵循ARM TrustZone 和TEE/GP 等产业标准。

4.1 optee 总体框架

optee 系统,是由运行在TEE 环境下的optee os、TA、以及运行在REE 环境下的client、driver、NA 组成,一共五个部分。optee 总体架构如下图所示:

4.2 开启Secure OS

4.2.1 Secure OS 镜像

Tina 固件在打包会自动把Secure OS 镜像打包到安全固件中。Secure OS 镜像位于device/config/chips/IC/bin/optee_CHIP.bin。
TEE 环境使用的内存有3 个部分,各部分大小与起始地址在Secure OS 编译时指定。各部分作用如下:
• 共享内存。REE 与TEE 通过smc 指令进行交互,smc 只能通过寄存器交换有限的数据,更多的数据通过共享内存进行交换。REE 和TEE 都有访问权限。
• optee os 内存。optee_os 专用的内存。optee_os 被加载到此处开始运行。REE 无权访问。
• TA 内存堆。加载TA、放置TA 堆、栈的内存空间。由optee_os 进行分配。分配给某一个TA的内存只能由该TA 或optee_os 访问,其他TA 无法访问。REE 无权访问。

警告
在内核中需要为TEE 环境预留内存,预留内存的大小与地址需要按照optee_CHIP.bin 编译时指定的大小与地址来设置。

假设R328 Secure 环境需要使用的内存如下:

1. SHARE MEM: 0x41900000-0x41A00000
2. OPTEE OS: 0x41A00000-0x41B00000
3. OPTEE TA: 0x41B00000-0x41C00000

在文件tina/lichee/linux-4.9/arch/arm/boot/dts/sun8iw18p1.dtsi 也必须预留3M 的内存。

4.2.2 内核支持optee 驱动

在内核中使能optee 驱动,执行make kernel_menuconfig,选中如下几项:

Device Drivers --->
	<*> Trusted Execution Environment support
		TEE drivers --->
			<*> OP-TEE

5 TA/CA 开发环境

Tina 上包含了TA/CA 开发环境,便于用户在Tina 上开发TA 与CA 应用程序。
Tina 上TA/CA 开发环境主要涉及如下几个packages:

  1. tina/package/security/optee-client-x.x,提供CA 所需的tee-supplicant 以及libteec
    库,其中x.x 为不同的版本。
  2. tina/package/security/optee-os-dev-kit,提供TA 端编译环境。
  3. tina/package/security/optee-helloworld,关于helloworld 的TA/CA demo 程序。
  4. tina/package/security/optee-secure-storage,关于optee Seucre Storage 的TA/CA
    demo 程序。
  5. tina/package/security/optee-base64,关于base64 算法的TA/CA demo 程序。
  6. tina/package/security/optee-efuse-read, 关于读取efuse 中CHIPID,ROTPK,
    SSK,OEM 或OEM_SEC 等区域的TA/CA demo 程序。
  7. tina/package/security/optee-getdmkey,关于从keybox 中读取dm-crypt 加密key 的
    程序。
    上面1 与2 是开发TA/CA 所需的环境,3-7 分别是一些TA/CA demo 程序,这些demo 程序
    需要依赖1、2 这两个包。
    !警告:
    • 要使用TA/CA 开发环境,前提是要支持Secure boot 以及Secure OS。
    • demo 程序仅用于开发测试,实际产品根据需要选中。

5.1 TA/CA 开发环境使用

CA 属于Linux 端应用程序,同其他应用程序一样,编译比较简单,只需要依赖optee-client 所提供的库,即可编译完成。
TA 属于安全应用程序,编译需要借助TA dev-kit。如要使用TA/CA 开发环境,执行make menuconfig,开启如下选项:

Tina Configuration
└─> Global build settings --->
	└─> [*] OP-TEE Support
	└─> choose OP-TEE version (optee version x.x.0) --->
└─> Security --->
	└─> OPTEE --->
		└─> <*> optee-client-x.x............................................ optee-client
		└─> <*> optee-os-dev-kit........................................ optee-os-dev-kit

说明
开启选项时,建议使用默认的OP-TEE 版本。当前仅MR813/MR813B/R329/R818/R818B/R528/V853 使用3.7.0。

编译时,将会把TA 所需的编译环境从tina/package/security/optee-os-dev-kit/dev_kit 复制到tina/out/BOARD/staging_dir/target/usr/dev_kit。

5.2 TA/CA 开发及编译

TA/CA 的开发需要参考GlobalPlatform 提供的标准接口说明文档。编译TA/CA 的关键点在设置编译环境变量,如CROSS_COMPILE_HOST, CROSS_COMPILE_TA以及TA_DEV_KIT_DIR 等。
TA/CA 开发环境使用可参考Tina 上的optee-helloworld 包tina/package/security/opteehelloworld/src 的实现。相关编译选项设置可参考下图:

说明
OPTEE 中通过UUID 唯一标识系统中的TA,因此开发TA 时需要在ta/include/user_ta_header_defines.h 文件中设置TA_UUID。UUID 可使用uuidgen 工具生成。

5.3 TA 签名

Tina 上支持更换TA 签名key。在编译TA 之前,务必使用openssl genrsa -out default_ta.pem 2048命令重新生成一个key,对默认key 进行替换;默认key 的路径位于package/security/optee-os-dev-kit/dev_kit/arm-plat-CHIP/export-ta_arm32/keys/default_ta.pem。
编译TA 的过程中,会使用该key 对TA 进行签名;在打包过程中,会通过scripts/update_optee_pubkey.py 脚本提取该key 的公钥并将其保存到optee_os 的image 中;这样就保证了只有经过该key 签名后的TA 才可以运行在包含该key 公钥的optee_os 上。因此请注意
妥善保存该key。

scripts/update_optee_pubkey.py 脚本使用说明如下:

usage: update_optee_pubkey.py [-h] --in_file IN_FILE --out_file OUT_FILE --key KEY
optional arguments:
-h, --help show this help message and exit
--in_file IN_FILE Name of in file
--out_file OUT_FILE Name of out file
--key KEY Name of key file

5.4 TA 加密

默认情况下,Tina 编译的TA 只进行了签名,不进行加密,TA 二进制文件以明文形式存放在rootfs 中的/lib/optee_armtz 目录下。
当前,Tina 支持在R328/MR813/MR813B/R329/R818/R818B/R528/V853 方案上将TA 加密后再签名,其他方案暂未开发此功能。
执行make menuconfig,开启如下选项使能TA 加密(一旦开启,所有的TA 都会进行加密)。

Tina Configuration
└─> Security --->
	└─> OPTEE --->
		└─> -*- optee-os-dev-kit
		└─> [*] whether encrypt ta
			└─> [*] encrypt ta with which key (ssk) --->

目前加密密钥来源有两种(加密密钥长度为128bit):
• 使用ssk 来作为加密秘钥。此方法需要烧写efuse 上的ssk 区域,然后将ssk 的内容复制到tina/package/security/optee-os-dev-kit/dev_kit/arm-plat-CHIP/export-ta_arm32/keys/ta_aes_key.
bin中,重新编译TA。有些方案efuse 中ssk 区域的长度为256bit,那么仅取其中前128bit作为ta_aes_key.bin 文件。
• 使用rotpk 派生的key 作为加密密钥。需要借助tina/scripts/generate_ta_key.py 工具来生成。其使用方法如下,将生成的OUT 文件重命名为tina/package/security/optee-os-dev-kit/dev_kit/arm-plat-CHIP/export-ta_arm32/keys/ta_aes_key.bin,重新编译系统。

usage: generate_ta_key.py [-h] --rotpk ROTPK --out OUT

5.5 安全应用demo

5.5.1 optee-helloworld 效果

该demo 展示CA 如何调用TA,以及如何通过共享内容向TA 传输数据。

root@TinaLinux:/# tee-supplicant &
root@TinaLinux:/# hello_world_na 1234
NA:init context
NA:open session
TA:creatyentry!
TA:open session!
NA:allocate memoryTA:rec cmd 0x210
NA:invoke command: hello 1234
TA:hello 1234
NA:finish with 0

5.5.2 optee-efuse-read 效果

该demo 中TA 通过系统调用utee_sunxi_read_efuse 与utee_sunxi_keybox 来获取efuse与keybox 中的内容。

警告:
本demo 只是演示作用,实际使用时不要将获取的内容打印或传递到CA

root@TinaLinux:/# tee-supplicant &
root@TinaLinux:/# efuse_read_demo_na rotpk
NA:init context
NA:open session
TA:creatyentry!
TA:open session!
NA:allocate memory
NA:invoke command
TA:rec cmd 0x210
read efuse:rotpk
read result:
0x90 0xfa 0x80 0xf1 0x54 0x49 0x51 0x2a
0x8a 0x04 0x23 0x97 0x06 0x6f 0x5f 0x78
0x0b 0x6c 0x8f 0x89 0x21 0x98 0xe8 0xd1
0xba 0xa4 0x2e 0xb6 0xce 0xd1 0x76 0xf3
NA:finish with 0

6 Secure Storage

数据是最核心资产,存储系统作为数据的保存空间,是数据保护的最后一道防线。当前Tina 上提供了三种Secure Storage 参考实现:
• keybox Secure Storage
• OP-TEE Secure Storage
• dm-crypt Secure Storage

6.1 keybox Secure Storage

由于efuse 空间受限,Tina 上支持了keybox Secure Storage 功能,该功能默认开启。keybox是Tina 上实现的一种安全存储技术,它将待烧写的key 传递到secure os,在secure os中使用efuse 中的ssk 或huk 对key 进行加密,然后将加密后的key 保存在flash 上一片特定
预留的区域。该区域未映射到逻辑扇区,通常的数据操作无法访问,正常量产也不会被擦除。

6.1.1 keybox 烧写及读取流程

写keybox 有两种方式,一种是使用DragonSN,写入的数据被efuse 中的ssk 进行加密,所有安全方案均支持;另一种是使用keybox_na,仅MR813/MR813B/R818/R818B/R528 有开发支持,写入的数据会被efuse 中的huk 加密,如果efuse 没有huk 区域,则通过chipid派生出一个key 来进行加密。

说明:
烧写keybox 之前,请注意提前烧写efuse 中的ssk 或huk 区域,烧写方法参考6.1.2 小节。

6.1.1.1 DragonSN 烧写keybox

使用DragonSN 烧写keybox 流程如下图所示。

6.1.1.2 keybox_na 烧写keybox

keybox_na 可以在用户空间烧写keybox, 其源码位于tina/package/security/opteekeybox。keybox_na 是一个NA,它发送key data 到optee os 的PTA,PTA 将其加密后,再将加密后的数据返回给NA 端,写入到keybox 中。make menuconfig 选中如下配置,编译生成keybox_na。

Tina Configuration
	--> Security
		--> OPTEE
			--> <*> optee-keybox

keybox_na 使用方法如下。

usage: keybox_na [-rw] [-k key_name] <-f key_file>
[options]:
	-r read key named 'dm_crypt_key'
	-w write key named [key_name] with binary [key_file]
	-k key name
	-f key file, binary
6.1.1.3 keybox 读取流程

keybox 读取流程如下图所示。启动过程中uboot 会按照一定的条件(见6.1.1.4 小节)将flash上加密的key 读取到secure os 进行解密,并一直保存在secure os 的内存中,供TA 调用。

6.1.1.4 keybox 列表

对于非R328/MR813/MR813B/R329/R818/R818B/R528/V853 方案,uboot 会将所有加密的key 加载至secure os 中进行解密。
对于R328/MR813/MR813B/R329/R818/R818B/R528/V853,uboot 会根据环境变量keybox_ist 来选择加载至secure os 中的key。keybox_list 环境变量在env 文件中进行配置,使用逗号分隔各key。比如下面的例子中,名称为rsa_key,ecc_key 与testkey 的key 会被加载至secure os 中进行解密。

keybox_list=rsa_key, ecc_key, testkey

说明:
对于R328/MR813/MR813B/R329/R818/R818B/R528/V853,使用DragonSN 烧key 到keybox 之前,必须要配置好keybox_list,否则烧写的key 不会经过secure os 加密,只会以明文保存。

6.1.2 DragonSN 烧写efuse 与keybox 的配置

前面已经介绍了烧写rotpk 时的配置,下图给出烧录efuse 中其他key 的配置。

烧录efuse 时配置“烧写模式” 为“安全key”。
其中“显示名称” 只是显示在DragonSN 工具上的名字,不会影响设备端。其中的“Key 名称” 只能是特定的字符串。对于R328 来说包括chipid、oem、rotpk、ssk、oem_secure 五种,其他方案有一些差异,通常chipid、rotpk 等都是可行的。
烧录efuse 时,“key type” 需要选成efuse。
烧写keybox key 时,DragonSN 的关键配置如下图所示。

烧录keybox 时配置“烧写模式” 为“安全key”。其中“显示名称” 只是显示在DragonSN 工具上的名字,不会影响设备端。
其中的“Key 名称” 对于不同的IC 有不同的配置。对于R328、MR813、MR813B、R329、R818、R818B、R528、V853,可以自己定义。对于其他方案,必须是widevine、ec_key、rsa_key、ec_cert1、ec_cert2、ec_cert3、rsa_cert1、rsa_cert2、rsa_cert3 这些特定的
字符串,如果希望自定义名字,则需要修改uboot、monitor/secure os 等。烧录keybox 时,“key type” 需要选成flash。
说明
如果“类型” 选择为“二进制文件”,那么待烧写的key 文件名必须要以.bin为后缀。

6.2 OP-TEE Secure Storage

OP-TEE Secure Storage 是根据GP TEE Internal API 规范实现的安全存储技术。它借助Secure OS 将数据进行加密,然后保存到文件系统(/data/tee)或RPMB 中。此功能可以与具体的设备绑定,充分保证了数据的私密性与完整性。
根据数据存储位置的不同,Tina 上支持两种OP-TEE Secure Storage:• REE FS Secure Storage。加密后的数据保存在linux 文件系统中(/data/tee)。
• RPMB Secure Storage。加密后的数据保存在eMMC 设备的RPMB(Replay ProtectedMemory Block)分区中。
说明
• Secure Storage 依赖Secure OS,因此只有安全固件中才包含OP-TEE Secure Storage 功能。
• RPMB 是eMMC 中的一个具有安全特性的分区,因此只有eMMC 才支持。
• 当前仅R18、R328、MR813/MR813B、R329、R818/R818B、R528、V853 支持OP-TEE REE FS Secure
Storage 功能,具体原因见6.2.1.3 小节。仅MR813/MR813B/R818/R818B/R528 支持OP-TEE RPMB Secure
Storage 功能。

6.2.1 OP-TEE REE FS Secure Storage

6.2.1.1 REE FS Secure Storage 功能框架

OP-TEE REE FS Secure Storage 的软件架构如下图所示。

6.2.1.2 REE FS Secure Storage 文件操作流程

当要写入数据时,TA 调用GP Trusted Storage API 提供的写接口,此接口会调用TEETrusted Storage Service 中的相关syscall 实现陷入到OP-TEE 的kernel space 中,该syscall 会调用一系列的TEE File Operation Interface 接口来存储写入的数据。TEE 文件系统会将写入的数据进行加密,然后通过一系列的RPC 消息向TEE supplicant 发送REE 文件操作命令以及已加密的数据。TEE Supplicant 对这些消息进行解析,按照参数的定义将加密的数据存放到对应的Linux 文件系统中(默认是/data/tee 目录)。以上是对写数据的处理,对读数
据的处理类似。

6.2.1.3 REE FS Secure Storage 密钥管理Key Manager

Key Manager 是TEE file system 中的一个组件,它主要是用来处理数据加解密,并对敏感的key 进行管理。在Key Manager 中会使用三种类型的key:Secure Storage Key(SSK)、TAStorage Key(TSK)、File Encryption Key(FEK)。
(1)Secure Storage Key - SSK
SSK 是一个per-device key,当OP-TEE 启动时,会生成此key,并保存在安全内存中。SSK用来生成TSK。SSK 由如下公式计算得出:
SSK = HMACSHA256 (HUK, Chip ID || “static string”)其中HUK 为Hardware Unique Key.

说明
• 这里的HUK 是通过tee_otp_get_hw_unique_key 函数获取的。对于
R18/MR813/MR813B/R818/R818B/R528 来说,该函数会获取efuse 中HUK 内容的前128bit;对于
R328/R329 来说,由于efuse 中不存在HUK 区域,该函数会读取efuse 中chipid 的内容并进行派生;对于其他方
案,此函数没有实现,即该函数获取的内容全部为0。
• 这里的SSK 是由HUK 与Chip ID 等运算得到,与efuse 中的ssk 区域不是同一个意思,要注意区分。
• 对于MR813/MR813B/R818/R818B/R528,固件第一次启动时,会由CE 模块的TRNG 生成192bit 的随机数,写
入到efuse 的HUK 中。对于其他平台,默认efuse 中的HUK 区域(如果efuse 中存在HUK 区域)为全0,需要借
助DragonSN 工具来进行烧写。具体烧写说明详见6.1.2 小节。

(2)TA Storage Key - TSK
TSK 是一个per-Trusted Application key,用来对FEK 进行加解密。TSK 公式计算如下:TSK = HMACSHA256 (SSK, TA_UUID)
(3)File Encryption Key - FEK
当创建一个TEE 文件时,Key Manager 会通过PRNG 为此文件生成一个新的FEK。并将加密之后的FEK 存放在meta file 中。而FEK 本身用来对TEE 文件进行加解密。

6.2.1.4 REE FS Secure Storage Meta Data 加密流程

6.2.1.5 REE FS Secure Storage Block data 加密流程

6.2.2 OP-TEE RPMB Secure Storage

6.2.2.1 RPMB Secure Storage 功能框架

RPMB Secure Storage 软件框架如下图所示。

OP-TEE OS 中并不包含eMMC 驱动,因此会借助Linux 端的tee-supplicant 通过ioctl 来对RPMB 分区进行访问。

6.2.2.2 RPMB Secure Storage 密钥管理与加解密

RPMB Secure Storage 文件加解密过程如下:

FEK = AES-Decrypt(TSK, encrypted FEK);
k = SHA256(FEK);
IV = AES-Encrypt(128 bits of k, block index padded to 16 bytes)
Encrypted block = AES-CBC-Encrypt(FEK, IV, block data);
Decrypted block = AES-CBC-Decrypt(FEK, IV, encrypted block data);

其中SSK、TSK 与FEK 的处理与REE FS Secure Storage 一致,最终的加解密算法有差异,RPMB 用的是AES-CBC:ESSIV,REE FS 用的是AES-GCM。

6.2.2.3 RPMB Secure Storage 功能启用

首先需要生成rpmb key 并写入到eMMC 的OTP 区域,同时设备端也需要保留该key(当前Tina 上将此key 写入到keybox 中)。整个配置步骤如下:
(1)uboot rpmb 支持
uboot 中,默认没有开启rpmb 的支持,需要手动开启。在平台头文件tina/lichee/brandy-2.0/uboot-2018/include/configs/IC.h加入如下宏来使能。

#define CONFIG_SUPPORT_EMMC_RPMB

(2)uboot 加载rpmb_key 到optee
在env 文件中的keybox_list 项中加入rpmb_key,uboot 在启动过程中,就会自动读取rpmb_key的安全key,送到optee os 中。
(3)烧写rpmb_key
rpmb_key 的烧录,请参考本文档6.1 小节关于keybox 的说明,这里需要注意的是,名字必须是rpmb_key。
烧写过程中,如果uboot 或optee 检测到名字为rpmb_key 的安全key,首先将此key 烧录到emmc 的OTP 中,然后再保存到keybox。

警告
• rpmb_key 是安全key,长度是256bit,请注意保密。
• RPMB Secure Storage 需要特定的optee.bin,Tina SDK 默认没有包含此optee.bin。如需支持
此功能,请联系AW 安全接口人。

6.2.2.4 RPMB 调试工具

Tina 上集成了mmc-utils 工具包,用于调试RPMB。执行"mmc -h"查看使用说明。
mmc 工具使用时,在没有传入rpmb_key 的情况下,可以读取RPMB 数据,但是并不能保证这个数据没有被修改过。传入rpmb_key 才能保证读取的数据没有被修改。RPMB 的写入需要传入rpmb_key。如果传入的rpmb_key 不匹配,读写都会报错。

6.2.3 Tina OP-TEE Secure Storage demo

Tina OP-TEE Secure Storage demo 是基于第三方开源库optee-test 中的测试样例修改而来,客户也可以参考optee-test 自行编写代码。
相关文

以上是关于Tina_Linux_安全_开发指南的主要内容,如果未能解决你的问题,请参考以下文章

Tina_Linux_图形系统_开发指南

Tina_Linux_系统裁剪_开发指南

Tina_Linux_音频_开发指南

Tina_Linux_功耗管理_开发指南

Tina_Linux_功耗管理_开发指南

Tina_Linux_系统软件 开发指南