【OPTEE开发】从TA到PTA的功能设计

一、功能需求

上篇”从TA到安全驱动的功能设计“介绍了TA通过syscall的方式调用到driver的功能,那本篇主要描述一下如何实现TA调用PTA 完成基本功能的通路。
主要包括新增PTA实现几个基本接口功能、新增和封装PTA对应的lib库 便于TA调用这两个环节。

下面以实际例子进行实战介绍,加深一下对TA调用PTA流程的理解。

原创不易,转载请注明出处:https://blog.csdn.net/jackone12347/article/details/122555702

二、TA到PTA的总体设计

1. 软件层总体设计

1.1 总体结构图设计

在这里插入图片描述

1.2 TA调用其他TA的接口设计

API名称API功能
TEE_OpenTASession建立两个TA之间的session
TEE_InvokeTACommand通过已创建的session和command id去调用另一个TA提供的操作接口
TEE_CloseTASession关闭两个TA之间的session
TEE_PARAM_TYPES定义两个TA之间传递的parameter参数

libhandlerot接口lib库中可以只实现这三个接口,但handlerot PTA中需要实现如下五个接口:

pseudo_ta_register(.uuid = PTA_ROT_UUID, .name = TA_NAME,
		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH | TA_FLAG_CONCURRENT,
		   .create_entry_point = create_ta,
		   .destroy_entry_point = destroy_ta,
		   .open_session_entry_point = open_session,
		   .close_session_entry_point = close_session,
		   .invoke_command_entry_point = invoke_command);

关于param参数的使用,这里说明一下
在调用InvokeTACommand函数时需要传入params参数,params可传入四个参数,类型有如下几种,params使用场景大致有这几种情况
1、当进入和返回都不需要携带参数时,使用TEE_PARAM_TYPE_NONE;
2、当只需要传入参数,不需要返回参数时,使用TEE_PARAM_TYPE_VALUE_INPUT;
不需要传入参数,只需要返回参数时,使用TEE_PARAM_TYPE_VALUE_OUTPUT;即需要传入 也需要返回,使用TEE_PARAM_TYPE_VALUE_INOUT;
3、当需要分配buffer内存时,使用TEE_PARAM_TYPE_MEMREF_X,使用区别和第2条相同。

PARAM类型功能
TEE_PARAM_TYPE_NONE无需传入参数和返回参数
TEE_PARAM_TYPE_VALUE_INPUT只需要传入参数
TEE_PARAM_TYPE_VALUE_OUTPUT只需要return返回参数
TEE_PARAM_TYPE_VALUE_INOUT即需要传入也需要返回参数
TEE_PARAM_TYPE_MEMREF_INPUT需要分配buff,只需要传入参数
TEE_PARAM_TYPE_MEMREF_OUTPUT需要分配buff,只需要返回参数
TEE_PARAM_TYPE_MEMREF_INOUT需要分配buff,即需要返回参数 ,也需要返回参数

2. 设计思路

需要先构思一下,如何实现这个功能,把需求分解为两部分。
1)封装libhandlerot lib库,便于TA中直接调用lib接口;
2)新增handle rot的PTA,实现libhandlerot中的几个接口。

三、详细设计

1. 修改代码清单

先看一下总体修改了哪些代码,修改的代码量不是很多。
@optee_os/lib/libhandlerot lib库中增加如下code

├── include
│   └── libhandlerot.h
├── libhandlerot.c
└── sub.mk

handle rot PTA中增加如下实现和对外头文件

core/pta/handle_rot.c
lib/libutee/include/pta_handle_rot.h

2. 子模块设计

2.1 libhanlerot库设计

新增libhandleroot.h头文件,我们这里还是实现两个接口,写入数据handle_write_rot和读取数据handle_read_rot。

/*
 * libhandlerot interface
 */

#ifndef _LIB_HANDLE_ROT_H_
#define _LIB_HANDLE_ROT_H_

#include <tee_internal_api.h>
#include <pta_handle_rot.h>

TEE_Result handle_write_rot(uint8_t* data, uint32_t size);

TEE_Result handle_read_rot(uint8_t* data, uint32_t size);

#endif /* _LIB_HANDLE_ROT_H_ */

这两个接口的实现如下,封装invoke_rot_pta中,通过command不同来区分read和write

TEE_Result handle_write_rot(uint8_t* data, uint32_t size)
{
	TEE_Result res = TEE_ERROR_GENERIC;

    DMSG("[ROT] handle_write_rot entry.");
	res = invoke_rot_pta(PTA_ROT_CMD_WRITE, data, size);
	return res;
}

TEE_Result handle_read_rot(uint8_t* data, uint32_t size)
{
	TEE_Result res = TEE_ERROR_GENERIC;
	res = invoke_rot_pta(PTA_ROT_CMD_READ, data, size);
	return res;
}

invoke_rot_pta的实现如下,请注意TEE_PARAM_TYPES中的参数,在前面章节中有介绍过。
主要封装了TEE_OpenTASession、TEE_PARAM_TYPES、TEE_InvokeTACommand、TEE_CloseTASession几个接口,具体的实现需要在PTA中去完成。

/*
* device root of trust handler
*/

#include <string.h>
#include <tee_internal_api_extensions.h>
#include "libhandlerot.h"

static TEE_Result invoke_rot_pta(uint32_t cmd_id, uint8_t* data, uint32_t size)
{
	// Dispatch to PTA
    TEE_Result res = TEE_ERROR_GENERIC;
    TEE_UUID uuid = PTA_ROT_UUID;
    TEE_TASessionHandle session = TEE_HANDLE_NULL;
    uint32_t ret_orig = 0;
    TEE_Param params[TEE_NUM_PARAMS];
    uint32_t param_types = 0;

	//open session
    res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE,
                            0, params, &session, &ret_orig);
    if (res != TEE_SUCCESS) {
        EMSG("[libhandlerot] open pta session failed, res 0x%08x, origin 0x%08x",
             res, ret_orig);
        return res;
    }

	//invoke command
    param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
                                  TEE_PARAM_TYPE_NONE,
                                  TEE_PARAM_TYPE_NONE,
                                  TEE_PARAM_TYPE_NONE);
    // data & size
    params[0].memref.buffer = data;
    params[0].memref.size = size;

    DMSG("[libhandlerot] TEE_InvokeTACommand start.");
    res = TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE, cmd_id,
                              param_types, params, NULL);
    if (res != TEE_SUCCESS) {
        EMSG("[libhandlerot] Invoke command to pta failed, res 0x%08x, origin 0x%08x.",
             res, ret_orig);
        TEE_CloseTASession(session);
        session = TEE_HANDLE_NULL;
        return res;
    }

    //close session
    TEE_CloseTASession(session);
    session = TEE_HANDLE_NULL;
	return res;
}

2.2 PTA模块设计

handlerot PTA的设计,包含头文件和实现文件。
pta_handle_rot.h实现如下:

#ifndef __PTA_HANDLE_ROT_H
#define __PTA_HANDLE_ROT_H

/*
 * Interface to the rot pseudo-TA, which is used for handling
 * device root of trust function
 */
//c7cf25d5-b62a-40bc-8841-2cefabbbf5bb
#define PTA_ROT_UUID \
		{ 0xc7cf25d5, 0xb62a, 0x40bc, \
		{ 0x88, 0x41, 0x2c, 0xef, 0xab, 0xbb, 0xf5, 0xbb } }

#define TA_NAME		"handle_rot.ta"

/*
 * ROT PTA supported commands
 */
#define PTA_ROT_CMD_READ		0
#define PTA_ROT_CMD_WRITE		1

#endif /* __PTA_HANDLE_ROT_H */

头文件中主要定义了UUID和TA_NAME,这个是TA的标识,需要唯一指定。

下面是handle_rot.c的实现

#include <bench.h>
#include <compiler.h>
#include <kernel/misc.h>
#include <kernel/mutex.h>
#include <kernel/pseudo_ta.h>
#include <malloc.h>
#include <mm/core_memprot.h>
#include <mm/mobj.h>
#include <mm/tee_mm.h>
#include <mm/tee_pager.h>
#include <mm/vm.h>
#include <optee_rpc_cmd.h>
#include <pta_handle_rot.h>
#include <stdio.h>
#include <string_ext.h>
#include <string.h>
#include <trace.h>

uint8_t g_rotbuffer[64] = {0};

static TEE_Result create_ta(void)
{
	DMSG("[PTA] create_ta.");
	return TEE_SUCCESS;
}

static void destroy_ta(void)
{
	DMSG("[PTA] destroy_ta.");
}

static TEE_Result open_session(uint32_t nParamTypes __unused,
		TEE_Param pParams[TEE_NUM_PARAMS] __unused,
		void **ppSessionContext __unused)
{
	DMSG("[PTA] open_session.");

	return TEE_SUCCESS;
}

static void close_session(void *pSessionContext __unused)
{
	DMSG("[PTA] close_session.");
}

static TEE_Result handle_rot_read_impl(uint8_t* buffer, uint32_t size)
{
	TEE_Result ret = TEE_SUCCESS;

	DMSG("[PTA] handle_rot_read_impl pta entry.");
	memcpy(buffer, &(g_rotbuffer[0]), size);

	size_t i = 0;
	for(; i < size; i++)
	{
		DMSG("[PTA] handle_rot_read_impl data:0x%x\n", buffer[i]);
	}

	return ret;
}

static TEE_Result handle_rot_write_impl(uint8_t* buffer, uint32_t size)
{
	TEE_Result ret = TEE_SUCCESS;

	memset(g_rotbuffer, 0, 64);
    memcpy(&(g_rotbuffer[0]), buffer, size);

	size_t j = 0;
	for(; j < size; j++)
	{
		DMSG("[PTA] handle_rot_write_impl data:0x%x\n", g_rotbuffer[j]);
	}

	return ret;
}

static TEE_Result invoke_command(void *session_ctx __unused,
		uint32_t cmd_id, uint32_t param_types,
		TEE_Param params[TEE_NUM_PARAMS])
{
	DMSG("[PTA] invoke_command pta entry.");

	//check input param whether is invalid
	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
                                       TEE_PARAM_TYPE_NONE,
                                       TEE_PARAM_TYPE_NONE,
                                       TEE_PARAM_TYPE_NONE)) 
    {
        FMSG("[PTA] invalid params \"%s\"", TA_NAME);
        return TEE_ERROR_BAD_PARAMETERS;
    }

	//get input data buffer and size
	uint8_t* buffer = params[0].memref.buffer;
	uint32_t size = params[0].memref.size;

	switch (cmd_id) {
	case PTA_ROT_CMD_READ:
		DMSG("[PTA] invoke_command pta read data.");
		return handle_rot_read_impl(buffer, size);
	case PTA_ROT_CMD_WRITE:
		DMSG("[PTA] invoke_command pta write data.");
		return handle_rot_write_impl(buffer, size);
	default:
		break;
	}

	return TEE_ERROR_BAD_PARAMETERS;
}

pseudo_ta_register(.uuid = PTA_ROT_UUID, .name = TA_NAME,
		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH | TA_FLAG_CONCURRENT,
		   .create_entry_point = create_ta,
		   .destroy_entry_point = destroy_ta,
		   .open_session_entry_point = open_session,
		   .close_session_entry_point = close_session,
		   .invoke_command_entry_point = invoke_command);

我这里把PTA中会用的的接口全添加了,包括create_ta、destroy_ta;代码逻辑也比较简单。

2.3 TA模块设计

普通TA中调用libhandlerot库,去调用PTA中的实现,demo代码如下:

#include <libhandlerot.h>

TEE_Result get_rot_data()
{
	TEE_Result res = TEE_SUCCESS;

	DMSG("[TA] get_rot_data entry. \n");

	uint8_t data[64] = "aaaabbbbccccdddd1111222233334444aaaabbbbccccdddd1111222233334444";
	res = handle_write_rot((uint8_t *)data, 64);


	uint8_t *temp = NULL;
	temp = malloc(65);

	res = handle_read_rot(temp, 64);
	DMSG ("[TA] handle_read_rot result:%d", res);
	int i = 0;
	for(; i < 64; i++) {
		DMSG ("[TA] handle_read_rot content:0x%x", temp[i]);
	}
	free(temp);

	DMSG("[TA] get_rot_data done. \n");

	return res;
}

运行结果:

D/TA:  get_rot_data:1516 [TA] get_rot_data entry.
D/TA:  handle_write_rot:60 [ROT] handle_write_rot entry.
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #5 (syscall_open_ta_session)
D/TC:? 0 tee_ta_init_pseudo_ta_session:299 Lookup pseudo TA c7cf25d5-b62a-40bc-8841-2cefabbbf5bb
D/TC:? 0 tee_ta_init_pseudo_ta_session:312 Open handle_rot.ta
D/TC:? 0 tee_ta_init_pseudo_ta_session:329 handle_rot.ta : c7cf25d5-b62a-40bc-8841-2cefabbbf5bb
D/TC:? 0 create_ta:29 [PTA] create_ta.
D/TC:? 0 open_session:42 [PTA] open_session.
D/TA:  invoke_rot_pta:39 [ROT] TEE_InvokeTACommand start.
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #7 (syscall_invoke_ta_command)
F/TC:? 0 trace_syscall:155 syscall #7 (syscall_invoke_ta_command)
D/TC:? 0 invoke_command:88 [PTA] invoke_command pta entry.
D/TC:? 0 invoke_command:109 [PTA] invoke_command pta write data.
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x61
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x61
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x61
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x61
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x62
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x62
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x62
...省略
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x34
D/TC:? 0 handle_rot_write_impl:78 [PTA] handle_rot_write_impl data:0x34
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #7 (syscall_invoke_ta_command)
F/TC:? 0 trace_syscall:155 syscall #6 (syscall_close_ta_session)
D/TC:? 0 tee_ta_close_session:513 csess 0x902ebe80 id 3
D/TC:? 0 tee_ta_close_session:531 Destroy session
D/TC:? 0 close_session:49 [PTA] close_session.
D/TC:? 0 destroy_ta:35 [PTA] destroy_ta.
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #5 (syscall_open_ta_session)
D/TC:? 0 tee_ta_init_session_with_context:607 Re-open TA c7cf25d5-b62a-40bc-8841-2cefabbbf5bb
D/TC:? 0 create_ta:29 [PTA] create_ta.
D/TC:? 0 open_session:42 [PTA] open_session.
D/TA:  invoke_rot_pta:39 [ROT] TEE_InvokeTACommand start.
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #7 (syscall_invoke_ta_command)
F/TC:? 0 trace_syscall:155 syscall #7 (syscall_invoke_ta_command)
D/TC:? 0 invoke_command:88 [PTA] invoke_command pta entry.
D/TC:? 0 invoke_command:106 [PTA] invoke_command pta read data.
D/TC:? 0 handle_rot_read_impl:56 [PTA] handle_rot_read_impl pta entry.
D/TC:? 0 handle_rot_read_impl:62 [PTA] handle_rot_read_impl data:0x61
...省略
D/TC:? 0 handle_rot_read_impl:62 [PTA] handle_rot_read_impl data:0x34
F/TC:? 0 trace_syscall:155 syscall #8 (syscall_check_access_rights)
F/TC:? 0 trace_syscall:155 syscall #7 (syscall_invoke_ta_command)
F/TC:? 0 trace_syscall:155 syscall #6 (syscall_close_ta_session)
D/TC:? 0 tee_ta_close_session:513 csess 0x902ebc90 id 3
D/TC:? 0 tee_ta_close_session:531 Destroy session
D/TC:? 0 close_session:49 [PTA] close_session.
D/TC:? 0 destroy_ta:35 [PTA] destroy_ta.
D/TA:  get_rot_data:1526 [TA] handle_read_rot result:0
D/TA:  get_rot_data:1529 [TA] handle_read_rot content:0x61
D/TA:  get_rot_data:1529 [TA] handle_read_rot content:0x61
D/TA:  get_rot_data:1529 [TA] handle_read_rot content:0x61
D/TA:  get_rot_data:1529 [TA] handle_read_rot content:0x61
D/TA:  get_rot_data:1529 [TA] handle_read_rot content:0x62
...省略
D/TA:  get_rot_data:1529 [TA] handle_read_rot content:0x34
D/TA:  get_rot_data:1533 [TA] get_rot_data done.
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
#### 收益: 学习《optee系统开发精讲 》套餐的收益如下:1、全体系的掌握optee的核心知识点(多核多线程、启动流程、各类API、TA/PTA/STA、driver、service、各类设计思想、内存管理、中断管理...);2、掌握TEE OS的设计核心思想(不限与optee,对其它TEE也是如此),能够进入软件架构层次的各项设计;3、快速熟悉大系统软件的各项组件,能够进行大系统软件之间的设计或排查问题4、学习和理解理解Armv8/Armv9架构、Trustzone架构5、技术水平提升N个level, 掌握快速的学习方法;#### 课程简介和大纲 该课程包含但不限与以下章节:optee的组件介绍optee os启动流程optee os的初始化流程optee os线程向量表及其作用进入optee os的八种方式optee os的异常向量表和设计模型optee os对irq中断的处理optee os对fiq中断的处理optee os的内存管理optee os的MMU的使用optee os的根密钥(信任根)optee os的RPC机制optee os的存储系统optee os的SFS系统optee os的RPMB机制的实现optee os的Timer实现optee os中实现的GP APIoptee os中的系统调度optee os中密码学函数的支持optee os中的线程调度CA/TA开发模型optee os中的serviceoptee os中的 PTAoptee os中的 secure driveroptee os中的 Early TAoptee中spinlock的实现原理详解optee中mutex的实现方式optee的栈指针和栈内存的介绍optee中使用虚函数(平台客制化)的设计模型共享内存的介绍optee os的标准错误码TA的签名和验签TA链接静态库的方法
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值