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 及其后续版本。

image-20230103095336137

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。密钥是加密和解密算法中的关键参数。

image-20230103095847960

2.2.2 加密算法

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

image-20230103095914998

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

image-20230103095938483

2.2.3 签名与证书

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

image-20230103100010011

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

image-20230103100026829

2.3 TrustZone

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

image-20230103100105265

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 时,会使用这些密钥分别对相应的镜像进行签名并生成证书。

image-20230103101032932

以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 中。

image-20230103101453785

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 中。

image-20230103101524737

• 在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 目录下。

image-20230103101720738

其中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 就会返回失败给此次操作的调用者。

image-20230103102201476

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 总体架构如下图所示:

image-20230103102922052

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 的内存。

image-20230103103045891

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 的实现。相关编译选项设置可参考下图:

image-20230103103333395

说明
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 流程如下图所示。

image-20230103103739138

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 调用。

image-20230103103902688

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 的配置。

image-20230103104012598

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

image-20230103104027342

烧录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 的软件架构如下图所示。

image-20230103104202781

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 加密流程

image-20230103104355519

6.2.1.5 REE FS Secure Storage Block data 加密流程

image-20230103104412370

6.2.2 OP-TEE RPMB Secure Storage

6.2.2.1 RPMB Secure Storage 功能框架

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

image-20230103104442759

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/package/security/optee-secure-storage 目录中,其内容如下:

.
├── Makefile
└── src
	├── Makefile
	├── na
	│ 	├── demo.c
	│ 	├── libstorage.c
	│ 	├── libstorage.h
	│	├── Makefile
	│ 	├── tee_api_defines_extensions.h
	│ 	└── tee_api_defines.h
└── ta
	├── include
	│ 	├── storage.h
	│	├── ta_storage.h
	│   └── user_ta_header_defines.h
	├── Makefile
	├── storage.c
	├── sub.mk
	├── ta_common.mk
	└── ta_entry.c
6.2.3.1 Tina OP-TEE Secure Storage TA

我们在Secure World 端实现了一个TA demo,用来调用Secure OS 中的TEE File System对数据进行加解密等操作。TA 的源码位于optee-secure-storage/src/ta 下。当Normal World 中有应用程序发起请求时,此TA 会被加载到Secure World 并运行。
Ta 目录下还包含了ta_storage.h 头文件,此文件中包含了TA 的UUID 以及相关的command编号。

6.2.3.2 Tina OP-TEE Secure Storage Library

我们将Normal World 中同Secure Storage TA 交互的接口进行了封装,具体实现在opteesecure-storage/src/na/libstorage.c 文件中,默认编译成库文件。Linux 端应用程序可以直接调用封装好的接口,便于开发。包含如下五个API。

(1) 创建文件

TEEC_Result OP-TEE_fs_create(TEEC_Context ctx, TEEC_Session *sess, void *file_name,
uint32_t file_size, uint32_t flags, uint32_t *obj, uint32_t storage_id);

函数功能:创建一个文件。
参数说明:

TEEC_Context ctx:NA 端打开TA 前创建初始化的一个TEE context,主要用于申请共享
内存。
• TEEC_Session *sess:NA 端创建一个TA 连接的一个session 结构体。
• void *file_name:创建文件的索引指针。
• uint32_t file_size:创建文件的大小。
• uint32_t flags:打开文件的权限,一般配置如下三种:TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_META 其中分别对
应对文件的写、读、擦除权限。
• uint32_t *obj:文件描述符指针,成功创建文件时,会赋予obj 打开文件的文件描述符,供后
面读写擦除等操作使用。
• uint32_t storage_id:配置存储属性。默认有三种:
1. TEE_STORAGE_PRIVATE
2. TEE_STORAGE_PRIVATE_RE_REE
3. TEE_STORAGE_PRIVATE_RPMB
前面两种支持文件加密存储在REE 端/data/tee 目录,最后一种表示存储在eMMC 的RPMB
分区。

(2) 打开文件

TEEC_Result OP-TEE_fs_open(TEEC_Context ctx, TEEC_Session *sess, void *file_name, uint32_t
file_size, uint32_t flags, uint32_t *obj, uint32_t storage_id);

函数功能:打开一个文件,如果文件不存在,返回错误。
参数说明:

• TEEC_Context ctx:NA 端打开TA 前创建初始化的一个TEE context,主要用于申请共享
内存。
• TEEC_Session *sess:NA 端创建一个TA 连接的一个session 结构体。
• void *file_name:打开文件的索引指针。
• uint32_t file_size:打开文件名的大小。
• uint32_t flags:打开文件的权限,一般配置如下三种:TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_META 其中分别对
应对文件的写、读、擦除权限。
• uint32_t *obj:文件描述符指针,成功打开或者创建文件时,会赋予obj 打开文件的文件描述
符,供后面读写擦除等操作使用。
• uint32_t storage_id:配置存储属性。默认有三种:
1. TEE_STORAGE_PRIVATE
2. TEE_STORAGE_PRIVATE_RE_REE
3. TEE_STORAGE_PRIVATE_RPMB

(3) 读取文件

TEEC_Result OP-TEE_fs_read(TEEC_Context ctx, TEEC_Session *sess, uint32_t obj, void *data,
uint32_t data_size, uint32_t *count);

函数功能:读取一个文件指定长度。
参数说明:

• TEEC_Context ctx:NA 端打开TA 前创建初始化的一个TEE context,主要用于申请共享
内存。
• TEEC_Session *sess:NA 端创建一个TA 连接的一个session 结构体。
• uint32_t obj:文件描述符。
• void *data:承载读取文件数据的buffer 地址。
• uint32_t data_size:读取文件数据长度。
• uint32_t *count:实际读取文件的长度。

(4) 写文件

TEEC_Result OP-TEE_fs_write(TEEC_Context ctx, TEEC_Session *sess, uint32_t obj, void *data,
uint32_t data_size);

函数功能:向文件写入指定长度数据。
参数说明:

• TEEC_Context ctx:NA 端打开TA 前创建初始化的一个TEE context,主要用于申请共享
内存。
• TEEC_Session *sess:NA 端创建一个TA 连接的一个session 结构体。
• uint32_t obj:文件描述符。
• void *data:写入文件数据的buffer 地址。
• uint32_t data_size:写入文件数据长度。

(5) 删除文件

TEEC_Result OP-TEE_fs_unlink(TEEC_Session *sess, uint32_t obj);

函数功能:关闭并删除文件
参数说明:
• TEEC_Session *sess:NA 端创建一个TA 连接的一个session 结构体。
• uint32_t obj:文件描述符。

6.2.3.3 Tina OP-TEE Secure Storage Demo

此为Linux 端的demo 程序,源文件为demo.c,默认编译成ss_demo。使用方法如下:

usage: ss_demo [type] [options] [file name]
[type]: 'ree_fs' or 'rpmb_fs'
[options]:
-c create a file named [file name] to secure storage
-r read a file named [file name] from secure storage
-w write a file named [file name] to secure storage
content is 256 bytes random number
-d delete a file named [file name] from secure storage
[file name]: file name

比如,当运行"ss_demo ree_fs -w 1.file",会随机生成256 个字节的数据,保存到Secure Storage中的1.file 文件中。

6.2.4 Tina OP-TEE Secure Storage 开启

6.2.4.1 OP-TEE Secure Storage 配置

(1) 开启Tina 相关配置
在Tina 环境下,执行"make menuconfig",确保如下选项已经开启。

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

(2) 开启内核相关配置版在Tina 环境下,执行"make kernel_menuconfig",确保如下选项已经开启。

Linux/arm 4.9.118 Kernel Configuration
Device Drivers --->
<*> Trusted Execution Environment support
TEE drivers --->
<*> OP-TEE

(3) 设置dts
在Tina 环境下,确保tina/lichee/linux-<kernel_version>/arch/arm*/boot/dts/sunxi/{CHIP}.dtsi文件中的firmware 下包含如下内容:

optee {
compatible = "linaro,optee-tz";
method = "smc";
};

(4) 确保huk 烧写
对于MR813/MR813B/R818/R818B/R528,安全固件第一次启动时自动使用CE 产生的随机数对efuse 中huk 进行烧写。对于其他方案,如果efuse 中有huk 区域的,需要通过DragonSN烧写efuse 中的huk 区域;如果efuse 中没有huk 区域的,optee 中会基于chipid 派
生出一个密钥。

6.2.4.2 编译安全固件

在Tina 环境下,按照第3 章说明来编译安全固件。

6.2.5 OP-TEE Secure Storage 使用

root@tulip-mozart:/# tee-supplicant &
root@TinaLinux:/# ss_demo rpmb_fs -c test.file
root@TinaLinux:/# ss_demo rpmb_fs -r test.file
---- Read file:test.file 0 Bytes data: ----
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
---- Read file:test.file end! ----
root@TinaLinux:/# ss_demo rpmb_fs -w test.file
---- Write file:test.file with 256 Bytes data: ----
0d 84 14 34 76 19 a9 c2 98 76 86 f9 2f c7 07 29
77 3b 9b 98 cb dd 57 f4 5f d5 b3 f6 d1 01 f4 5e
05 88 12 fa 22 3c be 3a b2 c4 34 61 8d ba 8b 84
76 27 9d c1 84 f4 b7 e4 4a 6b db 1c ec 51 f9 f1
d9 0c ed 7b c7 2c b5 7b f0 6a 5c 7e 25 e7 83 9b
8e 21 5e 14 16 95 f8 60 01 54 fb ed 25 75 60 7f
01 cd fa c9 f9 b1 c4 ea 9b 21 e9 40 89 6d dc 18
8e ba 2c 24 cf a4 84 d0 79 00 3f 9e 75 9f 1e f5
6d 1a bf e6 4b 04 d1 66 26 bb a6 af a8 03 47 37
bd 74 5b 0d 98 5f de 12 de 9d b1 d3 bc 4f ca a9
e8 0a 90 b3 0f e1 1a 35 9e c1 64 c6 c4 ab fe 03
9f d9 10 39 b9 6e ca 18 8b fb ec 48 4c b7 f1 b4
41 82 69 50 65 03 05 83 44 e8 4a 89 95 c8 8c b4
23 1c ed 5c 0b b9 74 96 b5 61 df 81 98 51 37 da
d4 20 aa b9 23 b0 bc e7 99 86 71 ae cf 7d 64 72
99 d1 ce 24 0b c2 bb 41 a4 1b c2 3d 6c 79 97 c0
---- Write file:test.file end! ----
root@TinaLinux:/# ss_demo rpmb_fs -r test.file
---- Read file:test.file 256 Bytes data: ----
0d 84 14 34 76 19 a9 c2 98 76 86 f9 2f c7 07 29
77 3b 9b 98 cb dd 57 f4 5f d5 b3 f6 d1 01 f4 5e
05 88 12 fa 22 3c be 3a b2 c4 34 61 8d ba 8b 84
76 27 9d c1 84 f4 b7 e4 4a 6b db 1c ec 51 f9 f1
d9 0c ed 7b c7 2c b5 7b f0 6a 5c 7e 25 e7 83 9b
8e 21 5e 14 16 95 f8 60 01 54 fb ed 25 75 60 7f
01 cd fa c9 f9 b1 c4 ea 9b 21 e9 40 89 6d dc 18
8e ba 2c 24 cf a4 84 d0 79 00 3f 9e 75 9f 1e f5
6d 1a bf e6 4b 04 d1 66 26 bb a6 af a8 03 47 37
bd 74 5b 0d 98 5f de 12 de 9d b1 d3 bc 4f ca a9
e8 0a 90 b3 0f e1 1a 35 9e c1 64 c6 c4 ab fe 03
9f d9 10 39 b9 6e ca 18 8b fb ec 48 4c b7 f1 b4
41 82 69 50 65 03 05 83 44 e8 4a 89 95 c8 8c b4
23 1c ed 5c 0b b9 74 96 b5 61 df 81 98 51 37 da
d4 20 aa b9 23 b0 bc e7 99 86 71 ae cf 7d 64 72
99 d1 ce 24 0b c2 bb 41 a4 1b c2 3d 6c 79 97 c0
---- Read file:test.file end! ----
root@TinaLinux:/# ss_demo rpmb_fs -d test.file
Delete file:test.file !
root@TinaLinux:/# ss_demo rpmb_fs -r test.file
Failed to optee_fs_open: test.file, ret = 0xffff0008

6.3 dm-crypt Seucre Storage

为防止未授权用户通过对设备进行物理攻击(如直接读取Flash)来获取敏感信息,造成用户数据泄露,Tina 引入dm-crypt 机制,对用户文件系统的数据提供加密保护。

image-20230103105451159

dm-crypt 是使用linux 内核加密API 框架和设备映射(device mapper)子系统的磁盘加密技术。Device mapper 在内核中作为一个块设备驱动被注册的,它包含三个重要的对象概念:mapped device、映射表、target device。Mapped device 是一个逻辑抽象,可以理解成为
内核向外提供的逻辑设备,它通过映射表描述的映射关系和target device 建立映射。这里的映射关系可以是verity(完整性校验),也可以是crypt(加密)。上图示例中,将/dev/mmcblk0p1 通过device mapper 映射称/dev/dm-0 设备,对/dev/dm-0进行文件系统格式化后可将/dev/dm-0 挂载至/data 目录。

6.3.1 Tina dm-crypt

dm-crypt 中的加解密可使用内核原生的软件加解密实现,也可以使用AW SOC 自带的硬件加密引擎(CE Crypto Engine)来实现。
当前Tina dm-crypt 分区的初始化、挂载与卸载借助package/security/dm-crypt/dmcrypt.sh 脚本来实现。该脚本默认将映射后的分区格式化为ext4。

说明
该脚本是一个demo,客户可依据需求自行开发。

6.3.1.1 dm-crypt 配置

使用Tina dm-crypt 需要三个先决条件:
(1) 配置Linux 内核。
执行make kernel_menuconfig,开启内核dm-crypt 相关功能以及加解密API:

Device Drivers --->
	[*] Multiple devices driver support (RAID and LVM) --->
		<*> Device mapper support
		<*> Crypt target support
File systems --->
    <*> The Extended 4 (ext4) filesystem
	[*] 	Use ext4 for ext2 file systems
-*- Cryptographic API --->
	<*> XTS support
	<*> SHA224 and SHA256 digest algorithm
	<*> AES cipher algorithms
	<*> User-space interface for hash algorithms
	<*> User-space interface for symmetric key cipher algorithms

如果希望使用硬件加密引擎,开启如下配置。

-*- Cryptographic API --->
[*] Hardware crypto devices --->
<*> Support for Allwinner Sunxi CryptoEngine

如果方案使用了UBI,即Linux 内核中开启了UBI 相关选项,还需开启如下配置。

Device Drivers --->
<*> Memory Technology Device (MTD) support --->
<*> Caching block device access to MTD devices
-*- Enable UBI - Unsorted block images --->
<*> MTD devices emulation driver (gluebi)

(2) 配置rootfs。
执行make menuconfig,开启如下选项。

Tina Configuration
	Security --->
		Device Mapper --->
			<*> dm-crypt

(3) 配置分区表,新增一个需要加密的分区。
修改sys_partition*.fex 文件,新增secret 分区,用来对其进行加密,分区size 可以自定义。

[partition]
	name = secret
	size = 40960
	user_type = 0x8000

6.3.1.2 dm-crypt 使用
开启如上配置之后,rootfs 中或包含相关工具及脚本。其中dm-crypt.sh 脚本会借助cryptsetup
与openssl 相关工具来执行映射、格式化、打开、挂载dm-crypt 分区等操作,其使用说明如下(当前加密算法为aes-xts-plain64):

dm-crypt.sh - this script helps you to use the secret partition.
Usage: /usr/bin/dm-crypt.sh <op_flag> <type> <keyfile>
<op_flag>:
'c' - create & format secret partition;
'm' - mount secret partition;
'u' - unmount secret partition and close mapper device
<type>: Device type, can be 'plain' or 'luks'.
<keyfile>: Key, can be 'keyfile' or 'pass' or 'optee-pass'

cryptsetup 支持使用keyfile、pass 或optee-pass。
• keyfile,这可以是任何文件,但建议使用具有适当保护的随机数据的文件(考虑到访问此密钥文件将意味着访问加密数据)。
• pass, 此模式下需要手动输入key。
• optee-pass,此模式下会调用getdmkey_na 程序从optee 中获取一个256bit 的key,此部分将在下一小结详细说明。cryptsetup 还支持多次加密操作模式,如luks,plain,loopaes 等,当前dm-crypt.sh 支持luks 与plain 模式。
(1) 格式化dm-crypt 分区
执行dm-crypt.sh c luks pass,创建并格式化dm-crypt 分区。

root@TinaLinux:/# dm-crypt.sh c luks pass
Enter passphrase:
Enter same passphrase again:
Creating Filesystems...
mke2fs 1.42.12 (29-Aug-2014)

(2) 挂载dm-crypt 分区
执行dm-crypt.sh m luks pass。

root@TinaLinux:/# dm-crypt.sh m luks pass
Enter passphrase:
Enter same passphrase again:
[ 412.744846] EXT4-fs (dm-0): mounted filesystem with ordered data mode. Opts: (null)
mount /dev/mapper/secret to /mnt/secret

查看secret 分区是否挂载成功,是否可以读写。

root@TinaLinux:/# mount | grep secret
/dev/mapper/secret on /mnt/secret type ext4 (rw,relatime,data=ordered)
root@TinaLinux:/# ls /mnt/secret/
lost+found
6.3.1.3 dm-crypt key

dm-crypt 的key 可以是两种模式,一种是passphrase,最大长度是512B;另一种是keyfile,文件的最大长度是8192KB。
为增加key 的安全性,Tina 上支持从optee os 中获取用于dm-crypt 的key。该key 需要预先烧录到keybox 中,具体烧录方法请参考本文档6.1 小节关于keybox 的说明,这里需要注意的是,名字必须是dm_crypt_key,key 长度为256bit。
Linux 端对应的应用程序是getdmkey_na, 源码位于tina/package/security/opteegetdmkey/目录下,具体使用方法参考第5 章关于TA/CA 开发环境的说明。

7 SELinux

SELinux (Security-Enhanced Linux) 是美国国家安全局(NSA)对强制访问控制(MAC,Mandatory Access Control)的实现。
强制访问控制是相对于Linux 传统的自主访问控制(DAC,Discretionary Access Control)一种访问控制机制。
DAC 控制的主体是用户,其最大的缺点是它无法分离用户与进程,进程能够继承用户的访问控制。由于程序是存在漏洞的,一旦被入侵,则入侵者具有该用户在系统上的所有权限。
MAC 中所有的访问权限是由访问控制策略来定义的,用户无法超越策略的限制。SELinux 以最小权限原则(principle of least privilege)为基础,在策略之外的访问都是无权的。

7.1 基本概念

7.1.1 主体Subject

可完全等同于进程。

7.1.2 客体Object

被主体访问的系统资源。可以是文件、目录、共享内存、套接字、端口、设备等。

7.1.3 安全上下文Secure Context

SELinux 对主体与客体的标记称做安全上下文,也称为安全标签,或标签。安全上下文的构成是一个四元组,包含User:Role:Type:MLS/MCS。每个字段都可以用来决定访问控制,其中
最重要的是Type,大多数Policy 都是针对Type 来制定的。进程安全上下文被记录在task_struct 中,客体安全上下文来源是文件的扩展属性(xattr)。

7.1.4 策略Policy

安全策略是使用策略语言编写的具体的访问控制规则。

主体访问客体时,SELinux 会根据安全策略来判断访问是否允许。
如策略语句:allow init sshd_exec_t:file {open read execute}; 表明允许init 类型的主体对sshd_exec_t 类型的客体执行file 的open/read/execute 操作。
策略使用策略语言编写的。为了让策略语言起作用,需要用相关的用户态工具将策略语言编译成二进制文件,通过selinuxfs 接口,将二进制文件所表示的策略输入到Security Server 中。

7.1.5 SELinux 的运行模式

SELinux 共有三种运行模式:
• enforcing,默认值,表示会强制禁止违反策略的访问。
• permissive,表示不强制禁止,违反策略会生成一条拒绝访问的信息。
• disable,禁用SELinux。

7.2 LSM 框架

LSM(Linux Security Module)是内核为支持不同安全机制的实现所设计的一个通用访问控制框架。目前LSM 框架下访问决策模块包括SELinux、SAMCK、tomoyo、yama、apparmor。

image-20230103110205745

SELinux 的决策流程如上图所示。策略管理工具将策略文件载入到内核中的Security server中。当主体访问客体时,首先进行DAC 检测,通过后再进行MAC 检测。

在Security server 与客体管理器之间有一个缓存AVC(Access Vector Cache),用来提高检测效率。主体发出访问客体的请求时,内核中的客体管理器首先查看AVC,如果AVC 中有缓存策略决策结果,根据缓存情况执行放行或拒绝;如果AVC 中没有缓存,安全服务器在策略中查找规则,按规则执行放行或拒绝的决策,策略决策的结果缓存到AVC 中。SELinux 的策略是允许策略,在策略中没有定义的访问都是被禁止的。

7.3 Tina SELinux 开启

Linux 主线很早就包含了SELinux 的实现,Tina 上主要是集成了SELinux 相关库、调试工具、参考策略以及策略加载等组件。
• 库:libsepol、libselinux、libaudit、libcap-ng、libsemanage 等
• 调试工具:policycoreutils、checkpolicy、audit、selinux-python 等。
• 参考策略:refpolicy 与sepolicy。
• 策略加载:busybox 与procd 的init 进程中执行策略加载与安全上下文设置。

警告
我们没有提供一个专门为tina 系统定制的selinux policy, 只是简单的使用refpolicy 和sepolicy(基于android),用户需要根据产品需求开发合适的策略。

7.3.1 menuconfig 配置

进入Tina 根目录,执行make menuconfig 进入配置主界面,开启如下配置(以refpolicy 为例,最小配置)。

Tina Configuration
	Global build settings --->
		[*] NSA SELinux Support
			choose the SELinux Policy (the reference policy) --->
		[*] Compile the kernel with device tmpfs enabled
		[*] Automatically mount devtmpfs after root filesystem is mounted
Base system --->
		<*> busybox --->
			[*] Customize busybox options
			Busybox Settings --->
				[*] Support NSA Security Enhanced Linux
				What kind of applet links to install (as script wrappers) --->
				/bin/sh applet link (as script wrapper) --->
Security --->
	SELINUX --->
		<*> refpolicy

可以根据需要加入相关调试工具,如checkpolicy、policycoreutils 等。

7.3.2 kernel_menuconfig 配置

在命令行中进入Tina 根目录,执行make kernel_menuconfig 进入配置主界面,新增如下配置。

Linux Kernel Configuration
	General setup --->
		[*] Auditing support
File systems --->
	<*> The Extended 4 (ext4) filesystem
		[*] Ext4 extended attributes
		[*] Ext4 Security Labels
	[*] Miscellaneous filesystems --->
		<*> SquashFS 4.0 - Squashed file system support
			[*] Squashfs XATTR support
Security options --->
	[*] Enable different security models
	[*] Socket and Networking Security Hooks
	[*] NSA SELinux Support
	[*] NSA SELinux boot parameter
	(1) NSA SELinux boot parameter default value (NEW)
	[*] NSA SELinux runtime disable
	[*] NSA SELinux Development Support
	[*] NSA SELinux AVC Statistics
	(1) NSA SELinux checkreqprot default value
Default security module (SELinux) --->

注意,不同内核版本可能有细微差异,另上面只列举了ext4/squashfs 文件系统的配置,如果想支持更多的文件系统,请打开对应文件系统的xattr 的支持。
对于Linux-5.4 版本内核,Selinux 配置还需要新增如下配置,在“Ordered list of enabled LSMs” 选项中加入关键字selinux。

Linux Kernel Configuration
	Security options --->
	First legacy 'major LSM' to be initialized (SELinux) --->
        (selinux,lockdown,yama,loadpin,safesetid,integrity) Ordered list of enabled LSMs

7.3.3 SELinux 初始化

系统启动时,在init 进程里,会加载策略文件、文件上下文到系统中,同时根据加载的策略文件初始化系统的安全上下文。具体的初始化过程需要根据实际情况进行适配,当前Tina 启动后相关log 如下所示。

[ 3.734518] device_chose finished 122!
[ 5.124774] SELinux: 32768 avtab hash slots, 117923 rules.
[ 5.199800] SELinux: 32768 avtab hash slots, 117923 rules.
[ 5.234633] SELinux: 6 users, 176 roles, 4773 types, 317 bools
[ 5.241333] SELinux: 129 classes, 117923 rules
[ 5.262431] SELinux: Completing initialization.
[ 5.267662] SELinux: Setting up existing superblocks.
[ 5.330382] audit: type=1403 audit(5.280:3): policy loaded auid=4294967295 ses
=4294967295
SELinux policy load success!
set init context success!
/etc/selinux/targeted/contexts/files/file_contexts load success!

启动后,可以执行sestatus 查看当前selinux 状态。

root@TinaLinux:/# sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: disabled
Policy deny_unknown status: denied
Memory protection checking: requested (insecure)
Max kernel policy version: 30

查看文件安全上下文。

root@TinaLinux:/# ls -Z
system_u:object_r:bin_t bin
system_u:object_r:device_t dev
system_u:object_r:etc_t etc
system_u:object_r:lib_t lib
system_u:object_r:mnt_t mnt
system_u:object_r:unlabeled_t overlay
system_u:object_r:proc_t proc
system_u:object_r:default_t rdinit
system_u:object_r:root_t rom
root:object_r:user_home_dir_t root
system_u:object_r:bin_t sbin
system_u:object_r:sysfs_t sys
system_u:object_r:tmpfs_t tmp
system_u:object_r:usr_t usr
system_u:object_r:default_t var
system_u:object_r:default_t www

查看进程安全上下文。

root@TinaLinux:/# ps -Z
PID CONTEXT STAT COMMAND
1537 system_u:system_r:kernel_t SW [RTWHALXT]
1549 system_u:system_r:initrc_t S /sbin/swupdate-progress -w
1568 system_u:system_r:init_t S< {ntpd} /bin/busybox /usr/sbin/ntpd
1618 system_u:system_r:sysadm_t R {ps} /bin/busybox /bin/ps -Z

7.4 策略开发

SELinux 的策略是允许策略,在策略中没有定义的操作都是被禁止的。所以对于一个新程序,需要新增对应的策略。

本节以Tina 上sepolicy-demo 策略为基础,举例说明如何新增策略来实现需要的强制访问控制。

7.4.1 限制主体的权限

要求:限制进程fork_test 不能fork 子进程。

7.4.1.1 fork_test 源代码

写一个简单包含fork 的程序,命名为fork_test.c,编译完成后,生成fork_test 的二进制文件,存放在/usr/bin/下。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t pid = fork();
if(pid < 0)
printf("fork error\n");
else if(pid == 0)
printf("this is child\n");
else
printf("this is parent, pid = %d\n", pid);
return 0;
}
7.4.1.2 添加策略

首先,定义该文件的安全上下文。在tina/package/security/sepolicy-demo/src/file_contexts文件中新增如下行,表明/usr/bin/fork_test 的安全上下文是u:object_r:fork_test_exec:s0

/usr/bin/fork_test u:object_r:fork_test_exec:s0

其次,定义该进程的安全上下文,以及该进程访问资源的权限。新增tina/package/security/sepolicydemo/src/fork_test.te 文件,其内容如下:

type fork_test, domain;
type fork_test_exec, exec_type, file_type;
# permissive fork_test;
init_daemon_domain(fork_test)
domain_auto_trans(shell,fork_test_exec,fork_test)
allow fork_test serial_device:chr_file rw_file_perms;
allow fork_test shell:fd use;
neverallow fork_test self:process fork;

• 第一句,定义一个fork_test 的类型,其属性集是domain。Sepolicy 中domain 表示进程属性集。
• 第二句,定义一个fork_test_exec 的类型,其属性集是exec_type 和file_type。表明该类型即是一个可执行的类型,又是一个文件类型。属性集的好处是可以对属性集下的组进行统一处理。
• 第三句,“#permissive fork_test”,前面的# 表示注释。如果不注释,表示fork_test 在执行的时候,如果没有相关的权限也能继续执行,同时会打印一条提示信息,这在开发阶段有好处,因为很难一开始就知道该主体需要多少权限。但是在最终产品上,不允许任何的permissive,否则就起不到强制访问控制的作用了。
• 第四句,init_daemon_domain(fork_test),这里的init_daemon_domain 是一个宏,该宏的定义位于te_macros 文件中。这句主要就表明允许init 类型的进程执行fork_test_exec 类型的文件,新进程的安全上下文是fork_test。
• 第五句,domain_auto_trans(shell,fork_test_exec,fork_test),表示shell 类型的进程执行fork_test_exec 类型的文件,新进程的安全上下文自动变为是fork_test。注:如果不进行设置,默认情况下,子进程的安全上下文继承父进程的安全上下文。
• 第六句,allow fork_test serial_device:chr_file rw_file_perms; 允许fork_test 类型的进程对serial_device 的客体进行chr_file 的rw 操作。因为程序中有打印,所以需要添加对串口设备的读写权限。
• 第七句,allow fork_test shell:fd use; fd,文件描述符,表示当进程执行完后,domain 改变时继承fd 的权限。
• 第八句,neverallow fork_test self:process fork; 是不允许fork_test 对自己进行process的fork 操作。

新增完策略之后,编译,提示有一个冲突。如下图所示,原本在domain.te 文件中允许domain对自己有process 的fork 操作,但是在fork_test.te 中又不允许,所以有冲突,将这里的domain减去fork_test。

image-20230103115326454

7.4.1.3 测试

如下图所示,/usr/bin/fork_test 与/usr/bin/fork_test_bak 内容完全一样,安全上下文有差异。

image-20230103115347951

fork_test 执行时提示错误,错误信息中的scontext 表示主体的上下文,tcontext 表示客体的安全上下文,tclass 表示操作的类型,fork 表示具体的操作,permissive=0 表示上述的操作不被允许。(如果fork_test.te 中包含了permissive fork_test; 那么这里也会出现提示语句,但是permissive=1,表示允许fork)。
fork_test_bak 文件的类型是system_file,shell 执行该文件时,新进程的安全上下文就是shell,shell 可以对自己进行fork 操作,所以执行成功。

7.4.2 限制客体的访问权限

要求:限制只有特定进程sunxi_info 才能访问/dev/sunxi_soc_info。

7.4.2.1 sunxi_info 源代码
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define CHECK_SOC_SECURE_ATTR 0x00
#define CHECK_SOC_VERSION 0x01
#define CHECK_SOC_BONDING 0x03
int main(void)
{
int fd = 0;
int cmd;
int arg = 0;
char Buf[4096];
fd = open("/dev/sunxi_soc_info",O_RDWR);
if(fd < 0)
{
printf("Open Dev Mem Erro\n");
return -1;
}
cmd = CHECK_SOC_SECURE_ATTR;
if(ioctl(fd,cmd,&arg) < 0)
{
printf("call cmd CHECK_SOC_SECURE_ATTR fail\n");
return -1;
}
printf("CHECK_SOC_SECURE_ATTR get data is 0x%x\n\n",arg);
cmd = CHECK_SOC_VERSION;
if(ioctl(fd,cmd,&arg) < 0)
{
printf("call cmd CHECK_SOC_VERSION fail\n");
return -1;
}
printf("CHECK_SOC_VERSION get data is 0x%x\n\n",arg);
cmd = CHECK_SOC_BONDING;
if(ioctl(fd,cmd,&Buf) < 0)
{
printf("call cmd CHECK_SOC_BONDING fail\n");
return -1;
}
printf("CHECK_SOC_BONDING get data is %s\n\n",Buf);
close(fd);
return 0;
}
7.4.2.2 添加策略

在tina/package/security/sepolicy-demo/src/file_contexts 文件中新增如下两行:

/usr/bin/sunxi_info u:object_r:sunxi_info_exec:s0
/dev/sunxi_soc_info u:object_r:sunxi_info_device:s0

在tina/package/security/sepolicy-demo/src/device.te 文件中新增如下行:

type sunxi_info_device, dev_type;

新增tina/package/security/sepolicy-demo/src/sunxi_info.te 文件,内容如下:

type sunxi_info, domain;
type sunxi_info_exec, exec_type, file_type;
init_daemon_domain(sunxi_info)
domain_auto_trans(shell,sunxi_info_exec,sunxi_info)
allow sunxi_info { serial_device sunxi_info_device }:chr_file rw_file_perms;
allow sunxi_info shell:fd use;
7.4.2.3 测试

image-20230103115539968

测试结果,/usr/bin/sunxi_info 与/usr/bin/sunxi_info_bak 文件内容一样,安全上下文不同,只有/usr/bin/sunxi_info 才能正确执行。/usr/bin/sunxi_info_bak 执行的时候,提示shell 对sunxi_info_device 设备没有chr_file 的read 与write 权限。
最后一条指令"ls /dev/sunxi_soc_info"执行也失败,提示shell 对sunxi_info_device 设备没有chr_file 的getattr 权限(获取属性权限)。

8 量产工具

从整个安全系统的角度看,需要一整套工具来配合完成对应的工作。

8.1 RSA 密钥对生成工具

目前,有公开的密钥对生成工具openssl,可以生成足够长度的密钥对。Tina 开发平台scripts 下提供了一个生成密钥对的脚本createkeys,该脚本调用dragonsecboot工具,解析dragon_toc*.cfg 中[key_rsa] 字段,并基于字段的内容生成对应名字的密钥
对。关于dm-verity 所需要的keys 是由tina/scripts/dm-verity-key.sh 生成。

8.2 安全固件版本管理

安全固件打包时会解析version_base.mk文件决定。在efuse 中会有一块区域用来记录固件版本。当设备启动时,会将efuse 中记录的版本号同固件中的版本号比较,如果固件中的版本较低,则不能继续启动;如果固件中的版本比较高,将固件中的版本写入efuse,继续启动;如果版本相同,正常启动。可防止固件版本回退。

8.3 数据封包工具

Tina 开发平台中提供固件封包工具dragonsecboot,在安全固件打包过程中会对相关的镜像文件(sboot、uboot、kernel 等)进行签名,并生成证书以及相关信息,以便启动时对这些镜像文件进行校验,验证完整性。

8.4 烧key 工具

烧key 工具用来将rotpk.bin 烧写到设备的efuse 中,efuse 位于IC 内部,由于efuse 中内容一旦写入便不可更改,所以从根源上保证了根证书公钥hash 的安全性。可用的烧key 工具包含DragonKey 或者DragonSN,工具的使用说明位于工具包中。

8.5 关闭jtag

将sys_config.fex 中jtag_para 节下的jtag_enable 设置为0 即可关闭jtag 调试功能。

8.6 密钥说明

8.6.1 固件签名密钥

密钥 安全固件签名私钥
功能 RSA2048 类型私钥。对sboot、monitor、scp、optee、uboot、boot、
rootfs 等分区进行签名
SDK 路径 tina/out/ B O A R D / k e y s / ∗ . p e m 与 t i n a / o u t / {BOARD}/keys/*.pem与tina/out/ BOARD/keys/.pemtina/out/{BOARD}/keys/*.bin,除开rotpk.bin
设备位置 设备上不保存
烧写方式 不烧写
保密
密钥 安全固件签名私钥
功能 RSA2048 类型私钥。对sboot、monitor、scp、optee、uboot、boot、
rootfs 等分区进行签名
SDK 路径 位于tina/out/ B O A R D / i m a g e / t o c 0 以及 t i n a / o u t / {BOARD}/image/toc0以及tina/out/ BOARD/image/toc0以及tina/out/{BOARD}/image/toc1目录下的证书中
设备位置 flash 上TOC0、TOC1、boot、rootfs 等分区中
烧写方式 随固件一起烧写
保密

8.6.2 efuse 中密钥

密钥 rotpk
功能 签名根密钥公钥的sha256 值,用于安全启动中根证书的校验。长度256bit。
SDK 路径 tina/out/${BOARD}/keys/rotpk.bin
设备位置 IC 中efuse 中的rotpk 区域
烧写方式 DragonSN 等,参考3.4 小节
保密
密钥 ssk
功能 对称密钥。可用于DragonSN 烧写keybox 时对待烧写的内容进行加密,可用
于TA 加密
SDK 路径 SDK 中没有
设备位置 IC 中efuse 中的rotpk 区域
烧写方式 DragonSN 等,参考3.4 小节
保密
密钥 huk
功能 对称密钥。可用于rotpk_na 烧写keybox 时对待烧写的内容进行加密,可用于
OPTEE Secure Storage 对数据进行加密。
SDK 路径 SDK 中没有
设备位置 IC 中efuse 中的huk 区域
烧写方式 对于MR813/MR813B/R818/R818B/R528,安全固件第一次启动时自动使用
CE 产生的随机数进行烧写。其他方案通过DragonSN 烧写
保密

8.6.3 dm-verity 密钥

密钥 dm-verity 私钥
功能 RSA2048 类型私钥。用于对rootfs 的hash table 进行签名
SDK 路径 位于tina/out/${BOARD}/verity/keys/dm-verity-pri.pem与tina/package/security/dmverity/
files/dm-verity-pri.pem
设备位置 设备上不保存
烧写方式 不烧写
保密
密钥 dm-verity 私钥
功能 RSA2048 类型公钥。用于在initramfs 启动脚本中对rootfs 的hash table 进
行验签
SDK 路径 位于tina/out/ B O A R D / v e r i t y / k e y s / d m − v e r i t y − p u b . p e m 、 < b r / > t i n a / p a c k a g e / s e c u r i t y / d m − v e r i t y / f i l e s / d m − v e r i t y − p u b . p e m 以 < b r / > 及 t i n a / o u t / {BOARD}/verity/keys/dm-verity-pub.pem、<br/>tina/package/security/dm-verity/files/dm-verity-pub.pem以<br/>及tina/out/ BOARD/verity/keys/dmveritypub.pem<br/>tina/package/security/dmverity/files/dmveritypub.pem<br/>tina/out/{BOARD}/compile_dir/target/rootfs_ramfs/verity_key
设备位置 flash 上boot 分区中的initramfs 文件系统中
烧写方式 随固件boot 分区一起烧写
保密

8.6.4 TA 签名密钥

密钥 dm-verity 私钥
功能 RSA2048 类型私钥。用于对TA 进行签名。没有签名或签名错误的TA 将不会
运行
SDK 路径 位于tina/package/security/optee-os-dev-kit/dev_kit/arm-plat-{CHIP}/export-ta_arm32
/keys/default_ta.pem与tina/out/{BOARD}/staging_dir/target/usr/dev_kit/arm-plat-{
CHIP}/export-ta_arm32/keys/default_ta.pem
设备位置 设备上不保存
烧写方式 不烧写
保密
密钥 TA 签名公钥
功能 RSA2048 类型公钥。用于OPTEE 对TA 进行验签。验签失败的TA 将不会运
行。
SDK 路径 tina/device/config/chips/KaTeX parse error: Expected group after '_' at position 17: …CHIP}/bin/optee_̲{IC}.bin与tina/out/${BOARD}/image/
optee.fex二进制文件中包含TA 签名公
设备位置 flash 上TOC1 分区中的optee 内
烧写方式 随固件TOC1 一起烧写
保密

8.6.5 TA 加密密钥

密钥 TA 签名公钥
功能 对称密钥。用于对TA 进行加密。密钥来源可以是ssk 或由rotpk 派生而来。长
度128bit。
SDK 路径 tina/package/security/optee-os-dev-kit/dev_kit/arm-plat-{CHIP}/export-ta_arm32/
keys/ta_aes_key.bin与tina/out/{BOARD}/staging_dir/target/usr/dev_kit/arm-plat-{
CHIP}/export-ta_arm32/keys/ta_aes_key.bin
设备位置 IC 中efuse 中的ssk 或rotpk 区域
烧写方式 DragonSN
保密

8.6.6 dm-crypt 密钥

密钥 dm-crypt 密钥
功能 对称密钥。用于对dm-crypt 分区文件系统数据进行加密。dm-crypt.sh 脚本中
可使用三种类型的key:keyfile、pass 与optee-pass,建议使用
optee-pass。
SDK 路径 SDK 中没有该密钥
设备位置 对于keyfile 类型,位于根文件系统/encrypt-key-file,此文件经过加密,使用
时需要输入passphrase 进行解密,keyfile 最大8192kiB;对于pass 类型,
不保存,使用时实时输入passphrase,passphrase 最大长度512B;对于
optee-pass 类型,保存在flash 上的keybox 中,长度256bit。
烧写方式 对于keyfile 类型,执行dm-crypt.sh 时,写到根文件系统根目录;对于pass
类型,不需要烧写;对于optee-pass 类型,通过DragonSN 或keybox_na
进行烧写。
保密

8.6.7 rpmb 密钥

密钥 rpmb 密钥
功能 对称密钥。用于访问RPMB 时身份认证。长度256bit。
SDK 路径 SDK 中没有该密钥
设备位置 保证在flash 上的keybox 中,同时保存在eMMC 中的OTP 区域中。
烧写方式 通过DragonSN 或keybox_na 进行烧写。
保密

9 参考资料

9.1 TrustZone

[1] PRD29-GENC-009492C_trustzone_security_whitepaper.pdf

9.2 GlobalPlatform

[1] GPD_TEE_SystemArch_v1.1.pdf
[2] GPD_TEE_Client_API_v1.0_EP_v1.0.pdf
[3] GPD_TEE_Internal_Core_API_Specification_v1.1.pdf
[4] GPD_TEE_TA_Debug_Spec_v1.0.pdf

9.3 OP-TEE

[1] https://www.op-tee.org/documentation/optee_os/documentation/secure_storage.md

9.4 Dm-verity

[1] https://source.android.com/security/verifiedboot/?hl=zh-cn
[2] Documentation/device-mapper/verity.txt

9.5 SELinux

[1] https://github.com/SELinuxProject/selinux
[2] https://github.com/TresysTechnology/refpolicy/wiki
保密 | 是 |

8.6.6 dm-crypt 密钥

密钥 dm-crypt 密钥
功能 对称密钥。用于对dm-crypt 分区文件系统数据进行加密。dm-crypt.sh 脚本中
可使用三种类型的key:keyfile、pass 与optee-pass,建议使用
optee-pass。
SDK 路径 SDK 中没有该密钥
设备位置 对于keyfile 类型,位于根文件系统/encrypt-key-file,此文件经过加密,使用
时需要输入passphrase 进行解密,keyfile 最大8192kiB;对于pass 类型,
不保存,使用时实时输入passphrase,passphrase 最大长度512B;对于
optee-pass 类型,保存在flash 上的keybox 中,长度256bit。
烧写方式 对于keyfile 类型,执行dm-crypt.sh 时,写到根文件系统根目录;对于pass
类型,不需要烧写;对于optee-pass 类型,通过DragonSN 或keybox_na
进行烧写。
保密

8.6.7 rpmb 密钥

密钥 rpmb 密钥
功能 对称密钥。用于访问RPMB 时身份认证。长度256bit。
SDK 路径 SDK 中没有该密钥
设备位置 保证在flash 上的keybox 中,同时保存在eMMC 中的OTP 区域中。
烧写方式 通过DragonSN 或keybox_na 进行烧写。
保密

9 参考资料

9.1 TrustZone

[1] PRD29-GENC-009492C_trustzone_security_whitepaper.pdf

9.2 GlobalPlatform

[1] GPD_TEE_SystemArch_v1.1.pdf
[2] GPD_TEE_Client_API_v1.0_EP_v1.0.pdf
[3] GPD_TEE_Internal_Core_API_Specification_v1.1.pdf
[4] GPD_TEE_TA_Debug_Spec_v1.0.pdf

9.3 OP-TEE

[1] https://www.op-tee.org/documentation/optee_os/documentation/secure_storage.md

9.4 Dm-verity

[1] https://source.android.com/security/verifiedboot/?hl=zh-cn
[2] Documentation/device-mapper/verity.txt

9.5 SELinux

[1] https://github.com/SELinuxProject/selinux
[2] https://github.com/TresysTechnology/refpolicy/wiki
[3] https://source.android.com/security/selinux

猜你喜欢

转载自blog.csdn.net/thisway_diy/article/details/129197002