Trusty系统基础入门

第10章 - TA开发基础

10.1 开发环境配置(NDK集成)

10.1.1 开发环境概述

Trusted Application (TA)开发需要特定的工具链和环境配置。Android NDK (Native Development Kit) 提供了必要的编译工具和库来构建TA。

所需组件

  • Android NDK (最新稳定版)
  • Trusty TEE SDK
  • 交叉编译工具链
  • TA签名工具
  • 调试工具 (如adb, fastboot)

系统要求

  • Linux或macOS开发环境
  • Python 3.x
  • Git版本控制
  • 至少16GB RAM
  • 支持ARM TrustZone的开发板或模拟器

10.1.2 NDK集成步骤

                # 下载并安装Android NDK
                wget https://dl.google.com/android/repository/android-ndk-r25b-linux.zip
                unzip android-ndk-r25b-linux.zip
                export ANDROID_NDK_HOME=$(pwd)/android-ndk-r25b
                
                # 设置环境变量
                export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
                export ARCH=arm64
                export CROSS_COMPILE=aarch64-linux-android-
            
注意: 确保NDK版本与Trusty TEE SDK兼容。建议使用官方文档推荐的NDK版本。

10.1.3 项目配置

典型的TA项目目录结构:

                ta_project/
                ├── Android.mk          # 构建配置文件
                ├── ta/                 # TA源代码目录
                │   ├── include/       # 头文件
                │   ├── src/           # 源文件
                │   └── manifest.json  # TA描述文件
                ├── host/              # 客户端代码
                └── build/             # 构建输出目录
            

示例Android.mk文件:

                LOCAL_PATH := $(call my-dir)
                include $(CLEAR_VARS)
                
                # TA配置
                LOCAL_MODULE := my_ta
                LOCAL_SRC_FILES := ta/src/main.c ta/src/crypto_ops.c
                LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include
                LOCAL_CFLAGS := -Wall -Werror
                
                # 指定为Trusted Application
                LOCAL_MODULE_CLASS := EXECUTABLES
                LOCAL_MODULE_TAGS := optional
                LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/trusty
                
                include $(BUILD_TRUSTY_APP)
            

10.2 TA生命周期管理

TA生命周期状态图

TA生命周期状态图

图10.1: TA生命周期状态转换

10.2.1 TA加载过程

TA的加载由Trusty内核管理,主要步骤包括:

  1. 验证阶段:检查TA镜像的数字签名和完整性
  2. 内存分配:为TA分配安全内存区域
  3. 重定位:处理地址重定位(如果适用)
  4. 初始化:调用TA的初始化函数
  5. 就绪:TA进入可执行状态

10.2.2 TA初始化

每个TA必须实现以下关键函数:

函数 描述 调用时机
TA_CreateEntryPoint TA创建时的初始化 首次加载时
TA_OpenSessionEntryPoint 新会话创建时的处理 每次客户端连接时
TA_InvokeCommandEntryPoint 命令处理主函数 每次客户端调用命令时
TA_CloseSessionEntryPoint 会话关闭时的清理 会话结束时
TA_DestroyEntryPoint TA销毁前的清理 TA卸载前
警告: 在TA初始化过程中,任何未处理的异常都会导致TA加载失败。确保所有初始化代码都经过充分测试。

10.2.3 示例TA框架代码

                #include <trusty_app_manifest.h>
                #include <trusty_std.h>
                
                // TA UUID - 必须全局唯一
                TA_UUID(my_ta_uuid, 0x12345678, 0x9abc, 0xdef0, 
                       0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
                
                // TA属性定义
                TA_APP_MANIFEST(my_ta_manifest,
                    TA_UUID_REF(my_ta_uuid),
                    TA_STACK_SIZE(0x2000),  // 8KB栈空间
                    TA_FLAGS(TA_FLAG_EXEC_DDR),
                    TA_VERSION(1, 0, 0),
                    TA_PERMISSIONS(TA_PERM_READ | TA_PERM_WRITE),
                );
                
                // TA创建入口点
                TEE_Result TA_CreateEntryPoint(void) {
                    LOG_I("TA创建中...");
                    // 初始化资源
                    return TEE_SUCCESS;
                }
                
                // TA销毁入口点
                void TA_DestroyEntryPoint(void) {
                    LOG_I("TA销毁中...");
                    // 释放资源
                }
                
                // 会话打开入口点
                TEE_Result TA_OpenSessionEntryPoint(uint32_t paramTypes,
                                                  TEE_Param params[4],
                                                  void** sessionContext) {
                    LOG_I("新会话创建");
                    return TEE_SUCCESS;
                }
                
                // 会话关闭入口点
                void TA_CloseSessionEntryPoint(void* sessionContext) {
                    LOG_I("会话关闭");
                }
            

10.3 实现简单的密码学服务TA

10.3.1 密码学服务设计

我们将实现一个提供以下功能的TA:

最佳实践: 在TA中实现密码学操作比在普通世界(Rich OS)更安全,因为TA运行在安全世界,可以防止侧信道攻击。

10.3.2 命令定义

命令ID 功能 输入参数 输出参数
0 AES加密 密钥(16B), 明文(变长) 密文(变长)
1 AES解密 密钥(16B), 密文(变长) 明文(变长)
2 SHA-256哈希 输入数据(变长) 哈希值(32B)
3 生成随机数 长度(4B) 随机数据(变长)

10.3.3 示例实现

#include <tee_internal_api.h> #include <tee_internal_api_extensions.h> #include <utee_defines.h> // 命令ID定义 #define CMD_AES_ENCRYPT 0 #define CMD_AES_DECRYPT 1 #define CMD_SHA256_HASH 2 #define CMD_GEN_RANDOM 3 // 命令处理入口点 TEE_Result TA_InvokeCommandEntryPoint(void* sessionContext, uint32_t commandID, uint32_t paramTypes, TEE_Param params[4]) { switch (commandID) { case CMD_AES_ENCRYPT: return aes_encrypt(paramTypes, params); case CMD_AES_DECRYPT: return aes_decrypt(paramTypes, params); case CMD_SHA256_HASH: return sha256_hash(paramTypes, params); case CMD_GEN_RANDOM: return generate_random(paramTypes, params); default: return TEE_ERROR_NOT_SUPPORTED; } } // AES加密实现 static TEE_Result aes_encrypt(uint32_t paramTypes, TEE_Param params[4]) { if (paramTypes != TEE_PARAM_TYPES( TEE_PARAM_TYPE_MEMREF_INPUT, // 密钥 TEE_PARAM_TYPE_MEMREF_INPUT, // 明文 TEE_PARAM_TYPE_MEMREF_OUTPUT, // 密文 TEE_PARAM_TYPE_NONE)) { return TEE_ERROR_BAD_PARAMETERS; } // 参数检查 if (params[0].memref.size != 16) { // AES-128密钥长度 return TEE_ERROR_BAD_PARAMETERS; } if (params[1].memref.size == 0 || params[2].memref.size < params[1].memref.size) { return TEE_ERROR_BAD_PARAMETERS; } // 实际加密操作 TEE_Result res; TEE_OperationHandle opHandle = TEE_HANDLE_NULL; // 创建加密操作 res = TEE_AllocateOperation(&opHandle, TEE_ALG_AES_ECB_NOPAD, TEE_MODE_ENCRYPT, params[1].memref.size); if (res != TEE_SUCCESS) { return res; } // 设置密钥 res = TEE_SetOperationKey(opHandle, params[0].memref.buffer, 16); if (res != TEE_SUCCESS) { TEE_FreeOperation(opHandle); return res; } // 执行加密 res = TEE_CipherUpdate(opHandle, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, ¶ms[2].memref.size); TEE_FreeOperation(opHandle); return res; } // SHA-256哈希实现 static TEE_Result sha256_hash(uint32_t paramTypes, TEE_Param params[