From d22705cef6ca5f551fa0ed0ca5e8a42f7d8f136b Mon Sep 17 00:00:00 2001 From: suwanghw Date: Fri, 11 Aug 2023 15:15:47 +0800 Subject: [PATCH] add opentrustee-guidelines baseline Signed-off-by: suwanghw --- docs/opentrustee-guidelines/README-CN.md | 8 + .../develop-ca-and-ta-guidelines.md | 103 +++++ ...able-new-platform-adaptation-guidelines.md | 431 ++++++++++++++++++ .../figures/overview-of-opentrustee.png | Bin 0 -> 25801 bytes .../figures/storage-format-of-ta.png | Bin 0 -> 24491 bytes ...-adaptation-and-construction-guidelines.md | 232 ++++++++++ ...pentrustee-architecture-and-constraints.md | 42 ++ ...pentrustee-debug-mechanism-introduction.md | 113 +++++ .../overview-of-opentrustee.md | 31 ++ .../public_sys-resources/icon-caution.gif | Bin 0 -> 580 bytes .../public_sys-resources/icon-danger.gif | Bin 0 -> 580 bytes .../public_sys-resources/icon-note.gif | Bin 0 -> 394 bytes .../public_sys-resources/icon-notice.gif | Bin 0 -> 406 bytes .../public_sys-resources/icon-tip.gif | Bin 0 -> 253 bytes .../public_sys-resources/icon-warning.gif | Bin 0 -> 580 bytes 15 files changed, 960 insertions(+) create mode 100644 docs/opentrustee-guidelines/README-CN.md create mode 100644 docs/opentrustee-guidelines/develop-ca-and-ta-guidelines.md create mode 100644 docs/opentrustee-guidelines/enable-new-platform-adaptation-guidelines.md create mode 100644 docs/opentrustee-guidelines/figures/overview-of-opentrustee.png create mode 100644 docs/opentrustee-guidelines/figures/storage-format-of-ta.png create mode 100644 docs/opentrustee-guidelines/opentrustee-adaptation-and-construction-guidelines.md create mode 100644 docs/opentrustee-guidelines/opentrustee-architecture-and-constraints.md create mode 100644 docs/opentrustee-guidelines/opentrustee-debug-mechanism-introduction.md create mode 100644 docs/opentrustee-guidelines/overview-of-opentrustee.md create mode 100644 docs/opentrustee-guidelines/public_sys-resources/icon-caution.gif create mode 100644 docs/opentrustee-guidelines/public_sys-resources/icon-danger.gif create mode 100644 docs/opentrustee-guidelines/public_sys-resources/icon-note.gif create mode 100644 docs/opentrustee-guidelines/public_sys-resources/icon-notice.gif create mode 100644 docs/opentrustee-guidelines/public_sys-resources/icon-tip.gif create mode 100644 docs/opentrustee-guidelines/public_sys-resources/icon-warning.gif diff --git a/docs/opentrustee-guidelines/README-CN.md b/docs/opentrustee-guidelines/README-CN.md new file mode 100644 index 0000000..2ecf40b --- /dev/null +++ b/docs/opentrustee-guidelines/README-CN.md @@ -0,0 +1,8 @@ +# OpenTrustee指南 + +- [OpenTrustee系统概述](overview-of-opentrustee.md) +- [OpenTrustee系统架构和约束](opentrustee-architecture-and-constraints.md) +- [OpenTrustee适配和构建指导](opentrustee-adaptation-and-construction-guidelines.md) +- [开发CA和TA指导](develop-ca-and-ta-guidelines.md) +- [OpenTrustee调试机制介绍](opentrustee-debug-mechanism-introduction.md) +- [使能新平台适配指导](enable-new-platform-adaptation-guidelines.md) \ No newline at end of file diff --git a/docs/opentrustee-guidelines/develop-ca-and-ta-guidelines.md b/docs/opentrustee-guidelines/develop-ca-and-ta-guidelines.md new file mode 100644 index 0000000..0a4ecf5 --- /dev/null +++ b/docs/opentrustee-guidelines/develop-ca-and-ta-guidelines.md @@ -0,0 +1,103 @@ +## 开发CA + + + +## 开发TA + +### TA安装包 + +TA安装包不需要跟OpenTrustee镜像打包到一起,可以把TA安装包文件放到到非安全侧文件系统下。在TA被访问时,由TEE Client将TA安装包发送到OpenTrustee系统中加载运行。 + +由于TA安装包放在非安全侧文件系统中,需要对TA安装包做签名,保证安装包的完整性。 + +#### TA安装包路径 + +TA安装包放在非安全侧文件系统下,路径有两种选择。 + +1、将TA安装包命名为UUID.sec,放在/vendor/bin目录或者/system/bin目录,TEE client会在TA被访问时,自动查找该TA对应的UUID.sec,发送到OpenTrustee系统中加载运行。 + +2、TA安装包可以任意命名并自定义路径,在CA调用TEEC_OpenSession时,通过TEEC_Context的ta_path指定该TA安装包的路径,如xxx/xxx.sec,TEE client会在指定路径查找该安装包,并发送到OpenTrustee系统中加载运行。 + +#### TA安装包格式 + +TA安装包是以“.sec”为后缀名的包文件,文件格式如下:包含文件头、签名块、数据区三部分 + + + +![](figures/storage-format-of-ta.png) + + + + + +### TA签名机制 + +TA签名:由于TA安装包放在非安全侧文件系统中,需要对TA安装包做签名,确保加载到OpenTrutee中的TA安装包没有被篡改。OpenTrustee提供的SDK开发套件中,包含了TA的签名工具,支持对TA安装包一键签名。需要在OpenTrustee SDK开发套件中预置TA签名的私钥。 + +TA验签:在TA安装包加载到OpenTrustee系统中时,由OpenTrustee TA管理框架对TA安装包做签名验证,验证通过之后才允许该TA加载运行。需要在OpenTrustee系统中预置TA验签的公钥。 + +**⚠**为了方便社区开发者调试,社区的OpenTrustee SDK开发套件已经预置了TA签名私钥,OpenTrustee系统中预置了验签的公钥。开发者在OpenTrustee商用版本中应自行替换该签名私钥和验签公钥。 + +### SDK开发套件 + +#### 介绍 + +OpenTrustee提供了SDK开发套件支持独立开发TA,该开发套件集成了TA头文件、TA编译框架、TA签名脚本、demo样例等,目录结构如下: + +``` +├── build +│ ├── config_tee_private_sample.ini # sec签名和perm_config签名的python脚本的ini配置文件,需要厂商进行配置 +│ ├── mk # make编译框架 +│ ├── pack-TA # 提供sec签名能力的shell脚本 +│ └── tools # 包含sec文件链接的ld文件(32位和64位)、sec文件二进制检查的shell脚本 +├── include +│ └── TA # 给TA提供的TEE头文件 +├── thirdparty +│ └── open_source +│ ├── import_open_source_header.sh # 导入TA编译依赖的musl头文件和安全函数库头文件 +├── sample +│ ├── CA # CA示例代码 +│ └── TA # TA示例代码 +└── CHANGELOG # SDK包版本发布记录 +├── README.md # SDK包的英文说明文件 +├── README_zh.md # SDK包的中文说明文件 +``` + +- 开发语言:C语言 +- 开发环境:linux操作系统 + +#### 开发套件准备 + +开发者在使用OpenTrustee SDK开发套件开发TA之前,需要进行一些准备工作。 + +##### 配置编译工具链 + +编译工具链获取路径?也可以用OH docker镜像 + +export PATH=/home/peter/code/openharmony/prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/bin:$PATH + +##### 导入第三方头文件 + +执行sdk/thirdparty/open_source/import_open_source_header.sh,将TA编译依赖的musl头文件和安全函数库头文件,从OpenHarmony的thirdparty + +##### 替换签名密钥 + + + +##### 安装python + +SDK中用到了python脚本来完成TA的属性配置文件解析、对TA文件进行签名打包等操作,因此需要在开发环境上安装python相关的功能。可能需要root权限。 + +1、安装python + +2、安装python相关的库, + +pip install pycryptodome + +pip install defusedxml + +### TA开发步骤 + +##### TA属性配置 + +### TA API \ No newline at end of file diff --git a/docs/opentrustee-guidelines/enable-new-platform-adaptation-guidelines.md b/docs/opentrustee-guidelines/enable-new-platform-adaptation-guidelines.md new file mode 100644 index 0000000..dfafc94 --- /dev/null +++ b/docs/opentrustee-guidelines/enable-new-platform-adaptation-guidelines.md @@ -0,0 +1,431 @@ +# 使能新平台的指南 +## TEE 安全镜像Loader适配指导 + +### 概述 + +#### 功能简介 + +TEE Loader主要负责加载安全镜像并将启动参数传递给TEE OS的功能。 + +#### 约束与限制 + +- 芯片架构为ARMv7/ARMv8架构。 +- CPU需支持安全内存和非安全内存的划分,安全和非安全外设的划分。 + +### 开发指导 + +#### 场景介绍 + +由于安全镜像在flash中是以加密形式存储的,因此需要对镜像进行解密处理,随后拷贝到目标执行地址。在TEE OS启动时,需要对其传递启动参数。以上这些都是在Loader中进行的。因此在芯片使能TEE时,需要对Loader进行开发适配。 + +#### 接口说明 + +以下接口说明列表将介绍我们在实际使能TEE过程中对Loader适配将用到的接口。包括: + +- 启动参数配置 +- 镜像加载 + +**表 1** 启动参数配置调用接口表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

必选/可选

+

void set_teeos_mem(uintptr_t teeos_base_addr, uint64_t size)

+

设置TEE OS的起始地址size大小。

+

必选,OS需要。

+

void set_teeos_uart(uint64_t uart_addr)

+

设置串口地址。

+

可选,建议配置,启动调试用。

+

void set_gic(struct gic_config_t gic_config)

+

配置gic寄存器。结构体定义见。

+

必选,OS需要。

+

bool copy_extend_datas(void * extend_datas, uint64_t extend_length)

+

保留字段拷贝。

+

可选,根据实际情况。

+

bool copy_teeos_cfg(void)

+

拷贝启动参数到目标位置,配置TEE OS属性后再调用此接口

+

必选,OS需要。

+
+ + +**表 2** 镜像加载调用接口表 + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

uintptr_t read_teeos(const char *part_name, uint32_t part_size)

+

将TEE OS从flash分区读镜像到RAM中。

+

int32_t verify_teeos(uintptr_t buf_addr)

+

TEE OS镜像验签。

+

int32_t decrypt_teeos(uintptr_t buf_addr)

+

TEE OS镜像解密。

+

int32_t copy_teeos(uintptr_t buf_addr)

+

TEE OS镜像拷贝到目标执行地址。

+

uint64_t get_teeos_start(void)

+

获取TEE OS启动地址。

+
+ + +#### 接口参数结构体定义 + +``` +struct gic_config_t { + char version; + union { + struct v2_t { + p_region_t dist; + p_region_t contr; + } v2; + struct v3_t { + p_region_t dist; + uint32_t redist_num; + uint32_t redist_stride; + p_region_t redist[GICR_MAX_NUM]; + } v3; + }; +}; +``` + +#### 开发步骤 + +1. 启动参数配置 + + 启动参数包含TEE OS用到的安全内存地址和大小,串口的地址,gic寄存器配置,其它拓展参数。 + + loader中启动参数的适配方法可以按照产品的习惯要求采用不同的方法,例如结构体中直接填写相应的参数,或者增加配置文件的方法。 + + **表 3** 启动参数列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

含义

+

备注

+

plat_cfg_size

+

启动参数大小,包含extend_paras部分

+

整个启动参数的buffer大小,值为sizeof(struct platform_info) + extend _length。

+

phys_region_size

+

TEE OS内存大小

+

2MB的整数倍。

+

phys_region_start

+

TEE OS内存起始物理地址

+

2MB的整数倍。

+

uart_addr

+

串口寄存器的基地址

+

-

+

struct gic_config_t

+

gic寄存器参数

+

-

+

extend_datas

+

其它参数

+

格式需要和TEE OS核对。

+
+ +2. 镜像加载 + + tee loader适配在芯片平台的bios或者fastboot、preloader中,主要完成的功能有配置并传递TEE OS的启动参数、将TEE OS镜像加载到目标内存位置、传递共享内存信息给TEE OS。loader中启动参数的适配方法可以按照产品的习惯和要求采用不同的方法,例如结构体中直接填写相应的参数,或者增加配置文件。以下为镜像加载步骤: + + 1. 从flash分区读镜像到RAM中。 + 2. TEE OS镜像验签。 + 3. TEE OS镜像解密。 + 4. TEE OS镜像拷贝到目标执行地址。 + 5. TEE OS启动地址传递。获取TEE OS的启动地址,一般情况下需要将这个值传给atf, 作为ATF初始化TEE OS的入口地址。 + +相关配置接口见[接口说明](#section125843344514)。 + +#### 开发实例 + +- 使用 TEE Loader,在芯片使能TEE时,配置启动参数的开发实例。详细示例代码位于 `base/tee/tee_os_framework/sample/teeloader` 目录。 + +```C +#define TEEOS_TEXT_OFFSET (0x8000) +#define ALIGN_SIZE_2M (0x200000) +struct platform_info { + uint64_t plat_cfg_size; + uint64_t phys_region_size; + paddr_t phys_region_start; + paddr_t uart_addr; + struct gic_config_t gic_config; + struct extend_datas_t { + uint64_t extend_length; + char extend_paras[0]; + } extend_datas; +}; +static struct platform_info g_teeos_cfg; + +static uintptr_t g_teeos_base_addr = 0; + +/* 设置TEE OS的起始地址size的大小 */ +int32_t set_teeos_mem(uintptr_t teeos_base_addr, uint64_t size) +{ + g_teeos_base_addr = teeos_base_addr; + g_teeos_cfg.phys_region_size = size; + if ((uint64_t)teeos_base_addr % ALIGN_SIZE_2M != 0) + return -1; + + g_teeos_cfg.phys_region_start = (uint64_t)teeos_base_addr; + + return 0; +} + +/* 设置TEE OS的串口地址和类型 */ +void set_teeos_uart(uint64_t uart_addr) +{ + g_teeos_cfg.uart_addr = uart_addr; +} + +/* 配置gic寄存器 */ +void set_gic(struct gic_config_t gic_config) +{ + g_teeos_cfg.gic_config = gic_config; +} + +bool copy_extend_datas(void *extend_datas, uint64_t extend_length) +{ + if (extend_datas == NULL) + return false; + + if (sizeof(struct platform_info) + extend_length > MAX_CONFIG_LENGTH) + return false; + + g_teeos_cfg.extend_datas.extend_length = extend_length; + char *dst = (char *)(uintptr_t)(g_teeos_cfg.phys_region_start + sizeof(g_teeos_cfg)); + + if (memcpy_s(dst, MAX_CONFIG_LENGTH - sizeof(g_teeos_cfg), + extend_datas, extend_length) != EOK) + return false; + return true; +} + +/* 拷贝启动参数到目标位置,配置TEE OS属性后调用此接口 */ +bool copy_teeos_cfg(void) +{ + if (g_teeos_cfg.phys_region_start == 0) + return false; + + g_teeos_cfg.plat_cfg_size = sizeof(struct platform_info) + g_teeos_cfg.extend_datas.extend_length; + char *dst = (void *)(uintptr_t)g_teeos_cfg.phys_region_start; + + if (memcpy_s(dst, sizeof(g_teeos_cfg), + (char *)&g_teeos_cfg, g_teeos_cfg.plat_cfg_size - sizeof(uint64_t)) != EOK) + return false; + + return true; +} + +uint64_t get_teeos_start(void) +{ + return g_teeos_cfg.phys_region_start; +} + +uint64_t get_teeos_code_start(void) +{ + return g_teeos_cfg.phys_region_start + TEEOS_TEXT_OFFSET; +} + +uint64_t get_teeos_size(void) +{ + return g_teeos_cfg.phys_region_size; +} +``` + +- 不使用 TEE Loader(如 ATF 闭源等原因),需要在 TEE OS 中配置平台相关参数,以 RK3568 平台为例(详见 `base/tee/tee_os_kernel/kernel/arch/aarch64/plat/rk3568/machine.c`)。 + +- 若需要使能新平台,需要在 `base/tee/tee_os_kernel/kernel/arch/aarch64/plat` 目录下添加新平台的适配代码,并且在 `base/tee/tee_os_kernel/config.mk` 中更新 CHCORE_PLAT 配置 + + ```makefile + CHCORE_PLAT=new_plat + ``` + + +## TEE ATF适配指导 + +### 概述 + +#### 功能简介 + +ATF提供了安全世界的参考实现软件\[ARMv8-A\],包括执行的\[Secure Monitor\] \[TEE-SMC\]异常级别 3\(EL3\)。它实现了各种 ARM 接口标准,如电源状态协调接口\(\[PSCI\]\),可信板启动要求\(TBBR,ARM DEN0006C-1\)和\[SMC 呼叫公约\] \[SMCCC\]。 + +#### 约束与限制 + +- 芯片架构为ARMv7/ARMv8架构。 +- CPU需支持安全内存和非安全内存的划分,安全和非安全外设的划分。 + +### 开发指导 + +#### 场景介绍 + +芯片使能TEE时,需要对ATF进行适配,以下将相关内容做介绍。 + +#### 接口说明 + +**表 4** teed smc id管理列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

smc

+

smc id

+

处理的内容

+

来自安全/非安全侧

+

TEE_HANDLED_S_EL1_INTR

+

0xf2000006

+

FIQ中断

+

安全侧

+

TEE_ENTRY_DONE

+

0xf2000000

+

TEE完成smc命令返回

+

安全侧

+

TEE_ON_DONE

+

TEE_RESUME_DONE)

+

TEE_SUSPEND_DONE

+

0xf2000001

+

0xf2000004

+

0xf2000003

+

TEE启动完成,resume, suspend完成

+

安全侧

+

TEE_STD_REQUEST

+

0xb2000008

+

REE(tzdriver)侧的标准命令请求

+

非安全侧

+

TEE_STD_REE_SIQ

+

0xb200000a

+

SIQ线程处理请求

+

非安全侧

+

TEE_STD_RESPONSE

+

0xb2000009

+

安全侧完成smc命令返回

+

安全侧

+

TEE_STD_CRASH

+

0xb200000b

+

安全侧出现crash,告知ATF,此时ATF不会再处理任何非安全侧的请求

+

安全侧

+
+ +#### 开发实例 + +- 在芯片使能TEE ATF时,需要修改teed,适配示例代码位于 `base/tee/tee_os_framework/sample/teed` +- TEE OS 需要适配 ATF 中的 TEED,目前 TEE OS 支持 teed 和 opteed 两种,分别位于 `base/tee/tee_os_kernel/kernel/arch/aarch64/trustzone/spd` 下的 teed 和 opteed 两个目录中。 +- 若需要使能新的 TEED,需要在该目录下添加相应 TEED 的适配代码,并且在 `base/tee/tee_os_kernel/tee_tee_os_kernel/config.mk` 中更新 CHCORE_SPD 配置 + + ```makefile + CHCORE_SPD=new_teed + ``` \ No newline at end of file diff --git a/docs/opentrustee-guidelines/figures/overview-of-opentrustee.png b/docs/opentrustee-guidelines/figures/overview-of-opentrustee.png new file mode 100644 index 0000000000000000000000000000000000000000..9dcf53e012a0bd1cf098aa8119cb8b58bcf498a5 GIT binary patch literal 25801 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�R&G#PX^ZLC!K4 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 z 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 OxD{%@r!xylxcGlZkqB}C literal 0 HcmV?d00001 diff --git a/docs/opentrustee-guidelines/figures/storage-format-of-ta.png b/docs/opentrustee-guidelines/figures/storage-format-of-ta.png new file mode 100644 index 0000000000000000000000000000000000000000..1fa6dbdfc278629bb3f94cddf711c9ceada6ea5b GIT binary patch literal 24491 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 literal 0 HcmV?d00001 diff --git a/docs/opentrustee-guidelines/opentrustee-adaptation-and-construction-guidelines.md b/docs/opentrustee-guidelines/opentrustee-adaptation-and-construction-guidelines.md new file mode 100644 index 0000000..dff76f7 --- /dev/null +++ b/docs/opentrustee-guidelines/opentrustee-adaptation-and-construction-guidelines.md @@ -0,0 +1,232 @@ +# OpenTrustee 适配和构建指导 + +## Tee Client的适配和构建 + +### Tee Client使能实例 + +本章节讲述如何针对一款芯片适配TEE Client,在相应配置json文件中增加tee_client部件即可。 + +以RK3568芯片为例,在vendor/hihope/rk3568/config.json中增加以下内容: + +```c +{ + "subsystem": "tee", + "components": [ + { + "component": "tee_client", + "features": [] + } + ] +} +``` + +### Tee Client编译命令 + +Tee Client代码位置:`base/tee/tee_client` + +以RK3568芯片为例,运行以下命令编译TEE Client部件,产物路径:out/rk3568/tee/tee_client + +```shell +./build.sh --product-name rk3568 --ccache --build-target tee_client +``` + +## Tzdriver的适配和构建 + +### 概述 + +tzdriver是TEE的内核驱动,主要功能是在整个TEE子系统中起连接作用,是使用TEE OS服务的桥梁,tzdriver处理来自于tee\_client的ioctl命令,并通过smc指令从REE切换到TEE。 + +>![](public_sys-resources/icon-caution.gif) **注意:** +>单独适配tzdriver,系统并不能正常启动,必须同时适配TEE OS。 + +### 适配指导以及适配实例 + +本章节中会讲述如何针对一款芯片适配tzdriver,此章节中以RK3568芯片为例。 + +第一小节介绍tzdriver入口和tzdriver代码位置,本章下面几个小节,每小节都是一个适配步骤。(这几个适配步骤顺序无关,但推荐将配置选项放到最后) + +#### tzdriver入口 + +- Linux内核tzdriver代码位置:base/tee/tee\_tee\_tzdriver/linux。 + +tzdriver是内核中的一个字符设备驱动。 + +tzdriver初始化时会创建一个字符设备文件,一般为/dev/tc\_ns\_client,用户态进程可以打开此节点,以及通过ioctl接口调用tzdriver相关功能。 + +tzdriver总入口在core/tc\_client\_driver.c中的tc\_client\_ioctl函数。 + +设备节点函数接口: + +```c +static const struct file_operations_vfs g_tc_ns_client_fops = { + .open = tc_client_open, + .close = tc_client_close, + .ioctl = tc_client_ioctl, + .mmap = tc_client_mmap, +}; +``` + +#### 工程编译适配 + +tzdriver需要被编译到内核中作为内核驱动。 + +- Linux内核tzdriver编译适配 + + 在Linux内核可以通过defconfig文件中的CONFIG\_TZDRIVER选项控制tzdriver的编译使能。 + + 1. defconfig文件修改 + + defconfig文件在kernel/linux/config仓,每个芯片应当创建自己的defconfig文件,后面会介绍tzdriver中的所有defconfig配置项。 + + 2. kernel补丁 + + 其他内核相关修改在kernel/linux/patches仓,以补丁方式提供。 + + RK3568芯片的patch在kernel/linux/patches/linux-5.10/rk3568_patch/kernel.patch,其他芯片平台也可以参考这个patch,每个芯片应该创建自己的patch文件。此patch补丁中应当包含以下内容: + + - 对于内核的根Makefile的修改(在其中引用tzdriver仓的子Makefile,其中tzdriver path需要修改为实际的相对路径,注意Linux kernel的编译是会将kernel仓代码拷贝到out目录打patch,因此这个相对路径是相对于out下的临时kernel仓的路径)。 + + ``` + obj-y += {tzdriver path} + ``` + + - 对于内核的根Kconfig的需改(在其中引用tzdriver仓的子Kconfig,其中tzdriver path需要修改为实际的相对路径,同上需要注意这个相对路径应当是在out目录下的临时kernel仓路径)。 + + ``` + source "{tzdriver path}/Kconfig" + ``` + + - dtsi的修改:需要在相应芯片的disi文件中包含trusted\_core节点,对于RK3568芯片,需要修改patch中的/arch/arm64/boot/dts/rockchip/rk3568-toybrick-x0.dtsi文件,新增以下内容 + + ``` + /{ + trusted_core { + compatible = "trusted_core"; + interrupts = <0 73 4>; + }; + }; + ``` + 其中,Linux内核中tzdriver支持中断号的动态配置,上面的73为spi中断号 + >![](public_sys-resources/icon-caution.gif) **注意:** + >注意dtsi里面的spi中断号应该比实际的中断号小32,且需要保证不与其他组件的中断号冲突。 + + +#### 驱动初始化 + +- Linux内核中tzdriver驱动初始化方式 + + 自动初始化,无需适配修改。 + +### 配置选项 + +#### 内核配置选项 + +tzdriver有一些特性或者选项,可以选择配置,控制这些选项的地方如下: + +- Linux内核tzdriver配置选项 + + tzdriver选项应该写在kernel/linux/config仓,修改芯片的defconfig文件: + + ``` + # + # TEE OS + # + CONFIG_TZDRIVER=y + CONFIG_CPU_AFF_NR=1 + CONFIG_KERNEL_CLIENT=y + CONFIG_TEELOG=y + CONFIG_PAGES_MEM=y + CONFIG_THIRDPARTY_COMPATIBLE=y + + ``` + + 各选项其含义如下表所示: + + **表 1** 配置选项说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

说明

+

CONFIG_TZDRIVER

+

模块开关,使能tzdriver必须打开

+

CONFIG_CPU_AFF_NR

+

CA绑核功能,非零值代表限制仅cpuid小于CONFIG_CPU_AFF_NR的CPU可以进入TEE,0代表无限制,当前只支持在0核运行,所以值为1

+

CONFIG_KERNEL_CLIENT

+

内核CA支持,默认建议开启

+

CONFIG_TEELOG

+

TEE日志开关,默认建议开启

+

CONFIG_PAGES_MEM

+

tlogger使用的内存类型,开发者无需修改

+

CONFIG_THIRDPARTY_COMPATIBLE

+

兼容第三方opteed的适配,例如适配RK3568芯片需要开启此选项

+
+ +### TEE Tzdriver编译命令 +tzdriver部件跟随kernel一起编译,编译命令如下 +```Bash +./build.sh --product-name rk3568 --ccache --build-target kernel --gn-args linux_kernel_version=\"linux-5.10\" +``` + +## TEE OS镜像的构建指导 + +以RK3568芯片为例,TEEOS的二进制文件(bl32.bin)被打包在uboot.img中,以下是构建TEEOS镜像的指导。 + +### 编译TEEOS + +TEEOS内核代码位置:`base/tee/tee_os_kernel` + +TEEOS框架代码位置:`base/tee/tee_os_framework` + +切换目录至OpenHarmony源码根目录, 输入以下指令编译TEEOS镜像 + +```Bash +./build.sh --product-name rk3568 --build-target tee --ccache +``` +构建产物为TEEOS镜像,路径如下:`base/tee/tee_os_kernel/kernel/bl32.bin` + +### 编译uboot.img +根据以下步骤编译uboot.img +- 克隆`https://github.com/rockchip-linux/rkbin`,其中包含bl31.elf +- 克隆`https://github.com/rockchip-linux/u-boot`,其中包含u-boot +- 将rkbin和u-boot放在同一目录下, 修改rkbin/RKTRUST/RK3568TRUST.ini中BL32_OPTION下的PATH指向bl32.bin +- 其中,u-boot/make.sh中有以下内容,搜索RK3568TRUST.ini中包含_bl32_的文件名,如果BL32的文件名是bl32.bin的话,需要修改下匹配规则 +```Bash +BL32_BIN=`sed -n '/_bl32_/s/PATH=//p' ${INI} | tr -d '\r'` +``` +- 修改u-boot/configs/rk3568_defconfig,关闭OPTEE驱动,增大镜像大小到6M。 +```Bash +- CONFIG_OPTEE_CLIENT=y ++ CONFIG_SPL_FIT_IMAGE_KB=6144 ++ CONFIG_SPL_FIT_IMAGE_MULTIPLE=1 +``` +>![](public_sys-resources/icon-caution.gif) **注意:** +>烧录的时候需要修改分区表parameter.txt,和uboot.img的镜像大小一致 +- 修改make.sh中编译工具链路径,使其指向正确的路径(可以使用openharmony工程prebuilts目录下的工具链) +```Bash +-CROSS_COMPILE_ARM32=../prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +-CROSS_COMPILE_ARM64=../prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +``` +- 在u-boot目录下执行./make.sh rk3568,最终会在u-boot目录中生成uboot.img \ No newline at end of file diff --git a/docs/opentrustee-guidelines/opentrustee-architecture-and-constraints.md b/docs/opentrustee-guidelines/opentrustee-architecture-and-constraints.md new file mode 100644 index 0000000..6ca028f --- /dev/null +++ b/docs/opentrustee-guidelines/opentrustee-architecture-and-constraints.md @@ -0,0 +1,42 @@ +## 系统架构 + +OpenTrustee是一套完整的TEE解决方案,包含多个部件,系统架构如同所示: + +![](figures/overview-of-opentrustee.png) + +各部件基本功能介绍如下: + +**TEE Client** + +- 部署在REE侧用户态,为CA提供符合GP TEE标准的TEE Client API; +- 内置TEE的代理服务:如日志代理服务,支持获取TEE侧日志并落盘到REE侧文件系统;如安全存储服务,支持获取TEE侧加密的数据并落盘到REE侧文件系统。 + +**Tzdriver** + +- 部署在REE侧内核中的驱动,支持REE和TEE进行通信。 + +**OpenTrustee 操作系统框架** + +- 为TA提供符合GP TEE标准的TEE Internal API; +- 提供TA运行管理、驱动运行管理等框架基础服务; +- 提供安全存储、加解密等安全能力。 + +**OpenTrustee 操作系统内核** + +- ChCore微内核,提供IPC/进程管理/内存管理/调度/中断管理/REE和TEE切换等基础内核功能。 + +**OpenTrustee 开发套件** + +- 包括TA开发套件和驱动开发套件两部分,提供API头文件、编译框架、签名脚本、demo样例等,支持高效开发TA和驱动。 + +**OpenTrustee Dispatcher** + +- 部署在ATF中,在REE和TEE之间交互时完成两个世界上下文的切换。 + +## 贡献 + +### 编码规范 + +### license + +遵循Mulan PSL V2协议; \ No newline at end of file diff --git a/docs/opentrustee-guidelines/opentrustee-debug-mechanism-introduction.md b/docs/opentrustee-guidelines/opentrustee-debug-mechanism-introduction.md new file mode 100644 index 0000000..7708ad4 --- /dev/null +++ b/docs/opentrustee-guidelines/opentrustee-debug-mechanism-introduction.md @@ -0,0 +1,113 @@ +# OpenTrustee调试机制介绍 + +## TEE侧日志查看 + +当前OpenTrustee支持TEE侧日志系统,在TEE中提供LIB接口供TA和OpenTrustee Framework调用记录日志。使用维测接口获取TEE侧信息的说明如下: +通过`hdc shell`打开命令行窗口,输入tlogcat即可查看日志。 + +## 日志级别 + +当前TEE中日志分为以下5个级别。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

日志级别

+

说明

+

对应的日志打印接口

+

VERBOSE

+

细粒度信息事件,详细地记录程序的运行过程。

+

tlogv

+

DEBUG

+

细粒度信息事件,用于开发调试。

+

tlogd

+

INFO

+

突出强调应用程序的运行过程。

+

tlogi

+

WARNING

+

潜在的错误事件,不影响系统的继续运行。

+

tlogw

+

ERROR

+

发生错误事件,影响系统的继续运行。

+

tloge

+
+ +>![](public_sys-resources/icon-note.gif) **说明:** +>新开发TA推荐用上述日志接口,不建议使用其他接口。 + +### 日志使用限制 + +1. 日志内存大小是有限的,当日志写入比较快时,会出现日志被覆盖的情况,日志内存采用的是内核申请的PAGES内存,大小是256K。 +2. 增加TA日志时,要符合安全规范,不能打印用户隐私信息、内存地址等,不打印调试日志,且一条日志内容要做到字符精简。 + +### 使用方法 + +在源代码文件中包含tee\_log.h,使用与日志级别对应的日志打印接口打印日志。 + +日志级别和相应的接口如上面描述,其使用与标准C中的printf类似。 + +tee\_log.h中默认使用的日志级别为INFO,即默认打印使用tloge、tlogw、tlogi接口的信息。如调试过程中希望打印其他级别,可选择下面方式中的一种进行修改,建议使用方式1: + +1. 在Makefile文件中动态修改日志级别TA\_LOG\_LEVEL,具体值和对应的显示级别为: + + + + + + + + + + + + + + + + + + + + + + +

TA_LOG_LEVEL值

+

日志显示级别

+

0

+

Error

+

1

+

Error、Warn

+

2--默认值

+

Error、Warn、Info

+

3

+

Error、Warn、Info、Debug

+

>=4

+

Error、Warn、Info、Debug、Verbo

+
+ +2. 直接修改tee\_log.h中定义的TA\_LOG\_LEVEL\_DEFAULT为期望的级别。多个TA共用同一个tee\_log.h文件且期望打印的日志级别不一致时,不能选用此方式。 +3. 直接修改tee\_log.h中定义的TA\_LOG\_LEVEL为期望的级别。多个TA共用同一个tee\_log.h文件且期望打印的日志级别不一致时,不能选用此方式。 \ No newline at end of file diff --git a/docs/opentrustee-guidelines/overview-of-opentrustee.md b/docs/opentrustee-guidelines/overview-of-opentrustee.md new file mode 100644 index 0000000..b1fd24f --- /dev/null +++ b/docs/opentrustee-guidelines/overview-of-opentrustee.md @@ -0,0 +1,31 @@ +# OpenTrustee概述 + +OpenTrustee是一个部署在可信执行环境(TEE)中的安全操作系统。ARM架构中的TrustZone技术通过CPU层面的硬件设计,支持创建安全的可信执行环境。基于ARM TrustZone技术,我们可以在设备上同时运行OpenHarmony和OpenTrustee两个系统,这两个系统彼此隔离。基于这种系统隔离带来的安全性,OpenTrustee可以为用户的机密数据提供保护。 + +## **安全能力** + +OpenTrustee支持安全计算、安全存储、安全密钥、安全外设、安全时钟等安全能力。 + +备注:应该展开介绍,是否放到单独章节 + +## **应用场景** + +在终端设备越来越智能化的今天,人们正在把越来越多的个人应用和数据放到设备上,安全性成为一个很重要的命题。可信执行环境(TEE)已逐渐成为终端设备必备的安全技术。OpenTrustee具备丰富的安全特性,可以支持开发者灵活部署安全应用,应用场景也非常广泛,例如:移动支付、生物认证、版权保护等,也可以为系统安全提供保护,如安全启动、系统完整性检测等。 + +## **约束** + +- 支持OpenHarmony定义的标准系统,暂不支持轻量系统和小型系统; +- CPU需要支持ARM TrustZone机制; + +## **术语** + +| 缩略语 | 英文 | 中文 | +| ------ | ---- | ---- | +| | | | +| | | | +| | | | +| | | | +| | | | +| | | | +| | | | +| | | | \ No newline at end of file diff --git a/docs/opentrustee-guidelines/public_sys-resources/icon-caution.gif b/docs/opentrustee-guidelines/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 GIT binary patch literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/opentrustee-guidelines/public_sys-resources/icon-danger.gif b/docs/opentrustee-guidelines/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 GIT binary patch literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/opentrustee-guidelines/public_sys-resources/icon-note.gif b/docs/opentrustee-guidelines/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda GIT binary patch literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> literal 0 HcmV?d00001 diff --git a/docs/opentrustee-guidelines/public_sys-resources/icon-notice.gif b/docs/opentrustee-guidelines/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 GIT binary patch literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001