存储技术
1、安全存储简介
安全存储是TEEOS重要特性之一,安全存储主要用来为用户保存敏感数据如密钥等信息。用户在使用安全存储功能保存数据时会在TEE内对数据进行加密,然后保存到REE侧的相关存储区域中。根据对数据存储的安全性要求和使用场景TEE常见的安全存储一般分为RPMB安全存储、SFS安全存储。RPMB安全存储是eMMC中的一个具有安全特性的分区,其特点是非安全世界不可见,可以防止重放和回滚攻击,但是其容量较小所以一般对于安全性要求高的数据会使用RPMB存储。SFS安全存储是利用了REE侧文件系统进行存储服务,TEE加密后的数据会利用非安全侧的文件系统存放到REE侧的存储介质中,因此其容量很大可以存放较多的文件,但是由于其利用了非安全侧的文件系统,因此存放的文件是REE侧可见的,安全性相比RPMB较低。
本文将对OPTEE3.18版本中的SFS安全存储基本实现来进行分析,后文中的安全存储均指SFS安全存储,安全存储的整体框架如图1.1所示:
图1.1 安全存储框架
OPTEE在用户态提供了GP安全存储API,TA调用GP API来对需要保存的数据进行操作,具体的功能实现在OPTEE内核态的File system模块中实现,内核态的File system模块主要实现了数据加解密相关功能以及对应密文数据RPC消息发送功能。REE侧的守护进程tee_supplicant主要完成的是RPC消息接收以及安全存储文件在REE侧的操作功能。
OPTEE 安全存储所涉及到的主要文件如图1.2所示:
图1.2安全存储文件目录
2、安全存储文件操作
图2.1列出了安全存储文件操作的GP接口及相关系统调用关系图,syscall开头的函数是安全存储GP API功能在OPTEE内核中的具体实现。接下来我们对安全存储中的文件格式、基本数据结构以及文件的创建过程进行分析。
图2.1 安全存储api
2.1 安全存储文件格式及主要数据结构
安全存储的文件格式如图2.2所示,主要分为三个部分,分别是文件头信息,文件节点描述信息,以及数据体信息,其中数据体data block是以4K大小粒度存储的。OPTEE使用哈希二叉树方式管理安全存储的文件数据,树中的每个节点tee_fs_htree_node_image保护其两个子节点和一个数据块。元数据存储在头节点tee_fs_htree_image中,它也保护顶层节点。安全存储的文件格式所有字段都使用两个版本ver0 ver1进行复制管理从而确保了原子更新。
图2.2 文件格式
头节点tee_fs_htree_ image结构体具体定义如下,其中iv是加密head时使用的,tag是加密head后生成的,enc_fek是加密数据文件的密钥fek的密文数据,imeta是加密head后生成的,counter是ver信息,标识存储到ver0还是ver1中。
节点tee_fs_htree_node_image结构体具体定义如下,hash是保存节点的hash值,该值主要作用是在文件操作时找到该文件head,iv是加密data bloc使用的,不同的data block对应的iv值不同,tag是加密数据块后生成的,flags标识data block的版本号信息。
另一个主要的结构体tee_fs_fd具体定义如下,主要存放对文件操作时使用的fd、dir、uuid等信息。
2.2 安全文件操作
本节主要对OPTEE安全存储文件基本操作过程安全存储文件的创建、打开、读写过程进行分析。
(1)安全存储文件创建:安全存储文件创建流程是整个文件操作最复杂的流程,安全存储文件创建流程如图2.3所示。当第一次使用安全存储功能保存用户文件时,将会在/data/tee目录中生成两类文件分别是dirf.db文件和以数字命名的文件,数字命名的文件会根据创建的不同文件名称进行累加。dirf.db文件保存的是整个安全存储功能管理的所有文件的目录信息和节点信息,该文件只会被创建一次,后续对文件的操作将会更新dirf.db内容,以数字命名的文件保存的是用户文件信息。OPTEE对用户文件进行基本操作都需要通过对dirf.db文件进行索引来找到所需要的具体用户文件。syscall_storage_obj_create是安全存储创建文件功能在内核空间的主入口。下面对创建过程主要流程进行分析。
权限检查:在创建安全文件之前会通过vm_check_access_rights函数对TA调用安全存储操作的object权限进行校验,只有当权限校验通过后才会执行后续操作。
dirt.db文件创建:get_dirh是创建dirt.db主要实现,tee_fs_rpc_create_dfh函数在首次创建dirt.db文件时,通知ree侧tee_supplicant创建该文件,tee_fs_htree_open建立文件节点信息。tee_fs_htree_sync_to_storage主要是将tee_fs_htree_node_image及tee_fs_htree_ image信息存放到dirt.db中。
安全文件创建:安全文件创建通过ree_fs_open_primitive实现的,该流程会通知ree侧tee_supplicant创建以数字命名的文件,此时该文件中还没有写入具体的数据信息。
安全文件写入:安全文件head及data block写入通过ree_fs_write_primitive实现的,最终完成文件的创建过程,将初始化的数据写入到ree侧。
图2.3安全文件创建流程
(2)安全存储文件打开:当需要打开某个安全存储文件时,需要先从全局目录文件dirt.db中找到对应的以数字命名的文件编号,打开dirf.db是通过调用get_dirt函数实现的,最终调用到REE侧的tee_supplicant打开/data/tee/dirf.db文件并返回该文件的fd值,读取dirt.db中最新的文件头部数据,解密获取文件加解密使用的FEK,并建立文件节点树,打开dirf.db文件并建立了文件节点树后,通过读取dirf.db文件的数据区域中安全文件对应的dirf_entry来找到该安全文件的存储编号。在获取安全存储文件编号前需要进行一系列校验检查,检查通过后则为正确的文件编号。得到安全文件编号后就可打开该文件,读取该安全文件的头部分,获取根节点信息,并建立该安全文件的节点树,然后就可开始对该安全文件进行读写操作。
(3)安全存储文件读写操作:安全存储读写操作依赖打开操作,只有在执行完打开操作之后才能进行。安全文件读操作首先会获取TA的会话ID和运行上下文并检查权限。然后调用ree_fs_read函数来实现读取数据的操作,调用ree_fs_write函数来实现写入数据操作。
3、安全存储文件加密流程
3.1安全存储中的密钥
在OPTEE的安全存储中主要涉及三种类型密钥分别是SSK安全存储密钥、TSK TA的存储密钥、FEK文件加密密钥三者关系如图3.1所示。其中huk是芯片唯一密钥,其通过chipid及其他相关参数派生出安全存储的基础密钥SSK。针对不同的TA,根据uuid值及SSK派生出每个TA自己的存储密钥TSK。这样能够保证不同的TA加密存储的文件不能被其他文件解密,在一定程度上保证了安全性。TSK并不是最终对文件加密的密钥,而是对随机派生出的文件加密密钥FEK进行加解密的key。三种类型密钥中SSK TSK无论明文密文都不出TEE,FEK密文与数据密文封装到一起存储到REE侧文件系统中。
图3.1密钥关系图
3.2 安全存储文件加密流程
安全存储中的核心操作是对安全文件进行加解密操作,需要加密操作的数据分别为元数据加密,以及具体的数据区块进行加密。元数据及区块数据加密流程如图3.2所示,元数据是tee_fs_hreee_node_image中的数据,加密过程中会首先生成随机的AES密钥FEK,该值一般以enc_fek的形式保存,在使用时通过TSK解密后使用。数据块区域是具体需要保存的用户数据信息和tee_fs_htree_node_image中的数据。元数据和区块数据的加密算法在OPTEE中都采用AES GCM算法,采用的KEY都是FEK,不同的是在加密过程中有各自不同的IV值。
图3.2 元数据 区块数据加密流程
4、总结
安全存储功能是TEEOS中的重要功能,不同TEE产品有不同实现。本文对OPTEE安全存储SFS部分进行了简单的分析,我们发现安全存储操作涉及到的流程是比较复杂的,其中涉及到了加解密密钥派生方式,数据加解密算法的选择,数据文件管理的方式,TEE主动与REE交互方式等功能。这些部分均影响着安全存储的安全性稳定性和性能。OPTEE安全存储虽然对各个数据文件是分开存储的,但是对文件操作的索引信息又是集中存储到了dirt.db中,因此当dirt.db文件损坏时将会导致所有的文件无法读取的风险。因此在实际使用OPTEE时可以考虑定制化修改,对该文件在REE侧不同分区进行备份操作。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !