TLK(trust light kernel)是基于LK开发的security OS,印象中是nvidia的安全小组开发的。n年前,曾把TLK作为移植security OS的候选之一,当年做了一些研究。
TLK 分析
1. TLK现状
TLK包括如下6大模块:
TLK CA Library:
- Open session API
- Close session API
- Invoke session API
TLK TA Library:
- 和平台相关操作API,比如cache操作,地址映射操作等
- Memory分配/释放等API
- 加/解密API
- 平台相关的密钥的获取API
- RTC API
- 文件操作API
- Task loader API
- Open session API
- Close session API
- Invoke session API
- Create/ destroy instance API
TLK Linux Driver:
- 提供TLK CA和Monitor之间的数据通道
- Linux向TLK发起电源管理方面的请求
TLK Kernel:
- 内核对象操作,包括event,thread,task,mutex,semaphore,timer
- 平台相关操作,包括CPU,中断,电源管理等等
- 驱动,包括fb,key,net,pmic,usb
- Kernel lib
- Smc handler&disptach
- System call
- Session操作,task操作
- Monitor:用于从REE恰换至TEE
Platform Opreation:和平台相关的操作
- cache操作,地址映射操作等
- 电源管理
模块之间的关系如下图所示:
上图中的TA和CA需要用户自己实现。TLK源生代码中只包含了部分APP用例,例如shell等。
在初始化阶段,TLK会为静态链接进image的每个TA创建task和user thread,然后在Task空间加载TA并运行thread。
对于APP,会为每个APP创建kernel thread并调用APP的入口函数。
2. TLK和GP
TLK和GP的关系简单描述如下图:
TLK当前只是提供了GP框架和相关的lib,实现方式和API源型并没有严格符合GP规范要求。需要在TLK上做二次开发,才能满足GP规范。
2.1 Trust Core Framework(TCF)需求分析
GP的TCF的框架如下图所示:
TA和TLK TA Library的关系如下图:
具体实现如下图:
在编译阶段,TA链接libtlk_service,以其main函数作为entry;在运行阶段,kernel在TA task环境中调用入口函数main。main实现为service方式,即等待请求,接收请求后根据所传参数调用对应的TA实现的session/instance函数。
TLK支持的session/instance回调函数共有5个,和GP的TA interface对应,如下:
TA_CreateEntryPoint <-> te_create_instance_iface
TA_DestroyEntryPoint <-> te_destroy_instance_iface
TA_OpenSessionEntryPoint <-> te_open_session_iface
TA_CloseSessionEntryPoint <-> te_close_session_iface
TA_InvokeCommandEntryPoint <-> te_receive_operation_iface
但是双方的函数参数并不一致。如果需要支持GP规范,则需要在Tlklib中实现te_*函数, te_*将TLK参数转换为GP参数要求,并调用TA_*;而TA_*则由TA实现。
2.2 Internal client API需求分析
TLK在tlklib_service定义并实现了相关函数te_*,和GP对应关系如下:
TEE_OpenTASession <-> te_open_session
TEE_CloseTASession <-> te_close_session
TEE_InvokeTACommand <-> te_launch_operation
但同样,函数的参数类型和返回类型不一致。需要在tlklib_service中实现TEE_*函数,将其实现为te_*函数的封装。
同样,对于CA,已经在tlklib_client中实现te_*,需要实现对应的GP函数,对应关系如下:
TEEC_OpenSession <-> te_open_session
TEEC_CloseSession <-> te_close_session
TEEC_InvokeCommand <-> te_launch_operation
同样,函数的参数类型和返回类型不一致。需要在tlklib_client中实现TEEC_*函数,将其实现为te_*函数的封装。
2.3 Cancellation functions需求分析
TLK没有实现Cancellation相关的函数。需要在tlklib_client、tlklib_service、tlk kernel,linux driver中增加相关功能。
根据GP规范,Cancellation在以下2种场景做不同的处理:
- 操作请求还未传递至TA
如果发起了Cancellation操作,只需将此操作请求从请求队列中去除即可 - 操作请求已至TA
将TA task置为cancelled状态,这会影响一些可以cancellable的函数,比如TEE_Wait。TA可以通过设置自己的属性屏蔽client发起的Cancellation操作。
如果假设操作请求的传递是原子性的,则可以只处理第2种情况。需要在tlklib_client中实现:
TEEC_RequestCancellation
将TA task置为cancelled状态。
在tlklib_service中实现如下API:
TEE_GetCancellationFlag
TEE_UnmaskCancellation
TEE_MaskCancellation
用于设置/读取 TA自己的Cancellation屏蔽属性。
在cancellable函数实现时,需要一并考虑cancelled状态和Cancellation屏蔽属性,以便确认操作请求是否有效。
2.4 Property access functions需求分析
根据GP规范,可以设置/获取当前TA属性、当前CA属性,TEE系统属性,且属性名都有各式要求。TLK当前只有property access功能框架,仅实现了部分property的读取,实现如下:
如需要支持GP规范,需要做如下增强:
当前TA Property set扩展
TLK支持TA的manifest属性读取,当前可配的属性如下:typedef enum { OTE_CONFIG_KEY_MIN_STACK_SIZE = 1, OTE_CONFIG_KEY_MIN_HEAP_SIZE = 2, OTE_CONFIG_KEY_MAP_MEM = 3, OTE_CONFIG_KEY_RESTRICT_ACCESS = 4, OTE_CONFIG_KEY_AUTHORIZE = 5, OTE_CONFIG_KEY_TASK_ISTATE = 6, } ote_config_key_t;
需要在manifest扩展属性。根据GP,需要支持如下的属性:
gpd.ta.appID gpd.ta.singleInstance gpd.ta.multiSession gpd.ta.instanceKeepAlive gpd.ta.dataSize gpd.ta.stackSize gpd.ta.version gpd.ta.description
其中gpd.ta.appID需要从tlk kernel获取,其他直接从TA本身获取。
TEE属性支持
TLK当前te_get_implementation_property的实现是空函数,需要tlk kernel增加对TEE属性的读取功能,属性包括gpd.tee*等。并在tlklib_service中增加对属性读取的系统调用。在tlklib_service中实现GP定义的TEE_*Property*等函数,实现对te_*函数的封装。
由于此部分功能比较独立,也和平台无相关性,可以参考Op-tee在tlklib_service和Tlk kernel中实现property access功能。
2.5 Memory management functions 需求分析
TLK在tlklib_service中实现有te_mem_*等memory分配/释放等函数。可以封装te_mem相关的API,实现GP规范要求的memory API。
TLK实现有ote_set_instance_data/ ote_get_instance_data API,可以利用它们实现GP所需的如下2个接口:
TEE_SetInstanceData
TEE_GetInstanceData
但GP的TEE_CheckMemoryAccessRights需要自己实现,TLK没有提供相关的源型。
3. 功能实现
TLK的CA和TA实现为client/server关系,REE中的CA在TEE中都有对应的TA。TLK中缺失的功能可以通过CA/TA的方式实现。
4. lib
4.1 client lib
Lib包含了client和service这2部分:
- Client是供android CA调用;
- Service是供TLK的TA调用;
Client是通过/dev/tlk_device 接口和Linux交互。包含有如下3个API:
te_open_session:TE_IOCTL_OPEN_CLIENT_SESSION
te_close_session:TE_IOCTL_CLOSE_CLIENT_SESSION
te_launch_operation:TE_IOCTL_LAUNCH_OP
Client被编译为静态库libtlk_common。
4.2 service lib
Service lib的session接口实现在ote_command.c中,service中的其他lib调用session接口实现和TLK kernel的交互。
Service是利用syscall和TLK kernel交互。使用的是bionic\libc\arch-arm\syscalls下的接口。read接口示例如下:
ENTRY(read)
mov ip, r7
ldr r7, =__NR_read
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(read)
可见r7= 服务号
#define __NR_SYSCALL_BASE 0
#define __NR_read (__NR_SYSCALL_BASE+ 3)
Tlk kernel会根据相应的参数服务请求。
Service被编译为静态库libtlk_service。
te_create_thread_session中处理task->props.multi_instance条件时,没有将新创建的session->thread附加到task中,session->thread默认是kernel thread。