日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OPTEE之安全存储详解

發布時間:2025/3/15 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OPTEE之安全存储详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 安全存儲是什么?
  • 二、安全存儲相關技術點
    • 1.加載dirf.db文件
    • 2. dirf.db文件和安全存儲文件的格式
      • 2.1 安全文件的三個區域
      • 2.2 重要結構體的關系框圖
      • 2.3 FEK和IV介紹
    • 3. 安全的基本操作
      • 3.1 安全文件的創建
      • 3.2 安全文件的讀取
      • 3.3 安全文件的寫入
    • 4. 安全存儲中的加密解密
      • 4.1 數據結構的組成與作用
      • 4.2 元數據的加密
      • 4.3 數據塊數據的加密
    • 總結

安全存儲是什么?

OP-TEE的安全存儲功能是OP-TEE為用戶提供的安全存儲機制。
用戶可使用安全存儲功能來保存敏感數據、密鑰等信息。
使用OP-TEE安全存儲功能保存數據時,OP-TEE會對需要被保存的數據進行加密,且每次更新安全文件時所用的加密密鑰都會使用隨機數重新生成,用戶只要調用GP標準中定義的安全存儲相關接口就能使用OP-TEE的安全存儲功能對私有數據進行保護。

需要被保護的數據被OP-TEE加密后會被保存到REE側的文件系統、EMMC的RPMB分區或數據庫中,至于具體需要將加密后的數據保存到哪里則由芯片提供商決定。

安全存儲功能可提供一個安全的存儲環境,安全文件中數據的加解密過程都在OP-TEE中完成,且加解密密鑰的生成也是在OP-TEE中進行的,這樣就能保證數據的安全性。

二、安全存儲相關技術點

1.加載dirf.db文件

我們以打開安全文件為例,跟蹤學習一下OPTEE安全存儲相關的調用流程。

@tee_ree_fs.c
提供了基本的文件操作接口

const struct tee_file_operations ree_fs_ops = {.open = ree_fs_open,.create = ree_fs_create,.close = ree_fs_close,.read = ree_fs_read,.write = ree_fs_write,.truncate = ree_fs_truncate,.rename = ree_fs_rename,.remove = ree_fs_remove,.opendir = ree_fs_opendir_rpc,.closedir = ree_fs_closedir_rpc,.readdir = ree_fs_readdir_rpc, };

我們看一下其中的open函數ree_fs_open

static TEE_Result ree_fs_open(struct tee_pobj *po, size_t *size,struct tee_file_handle **fh) { ...res = get_dirh(&dirh);res = ree_fs_open_primitive(false, dfh.hash, &po->uuid, &dfh, fh);... }

通過ree_fs_dirh_refcount全局變量 來控制是創建dirf.db文件,還是打開dirf.db文件

static TEE_Result get_dirh(struct tee_fs_dirfile_dirh **dirh) {if (!ree_fs_dirh) {TEE_Result res = open_dirh(&ree_fs_dirh);if (res) {*dirh = NULL;return res;}}ree_fs_dirh_refcount++;assert(ree_fs_dirh);assert(ree_fs_dirh_refcount);*dirh = ree_fs_dirh;return TEE_SUCCESS; }

@fs_dirfile.c

TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash,const struct tee_fs_dirfile_operations *fops,struct tee_fs_dirfile_dirh **dirh_ret) { ...dirh->fops = fops;res = fops->open(create, hash, NULL, NULL, &dirh->fh); ... }static const struct tee_fs_dirfile_operations ree_dirf_ops = {.open = ree_fs_open_primitive,.close = ree_fs_close_primitive,.read = ree_fs_read_primitive,.write = ree_fs_write_primitive,.commit_writes = ree_dirf_commit_writes, };

ree_fs_open_primitive函數

static TEE_Result ree_fs_open_primitive(bool create, uint8_t *hash,const TEE_UUID *uuid,struct tee_fs_dirfile_fileh *dfh,struct tee_file_handle **fh) {struct tee_fs_fd *fdp;fdp = calloc(1, sizeof(struct tee_fs_fd));fdp->fd = -1;fdp->uuid = uuid;if (create)res = tee_fs_rpc_create_dfh(OPTEE_RPC_CMD_FS,dfh, &fdp->fd);elseres = tee_fs_rpc_open_dfh(OPTEE_RPC_CMD_FS, dfh, &fdp->fd);res = tee_fs_htree_open(create, hash, uuid, &ree_fs_storage_ops,fdp, &fdp->ht); }

@fs_htree.c
讀文件時,主要是通過如下代碼實現的,其中有校驗的部分,請查看如下代碼注釋部分。

TEE_Result tee_fs_htree_open(bool create, uint8_t *hash, const TEE_UUID *uuid,const struct tee_fs_htree_storage *stor,void *stor_aux, struct tee_fs_htree **ht_ret) {TEE_Result res;struct tee_fs_htree *ht = calloc(1, sizeof(*ht));ht->uuid = uuid;ht->stor = stor;ht->stor_aux = stor_aux;if (create) {const struct tee_fs_htree_image dummy_head = { .counter = 0 };res = crypto_rng_read(ht->fek, sizeof(ht->fek));res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_ENCRYPT, ht->fek,sizeof(ht->fek), ht->head.enc_fek);res = init_root_node(ht);ht->dirty = true;res = tee_fs_htree_sync_to_storage(&ht, hash);res = rpc_write_head(ht, 0, &dummy_head);} else {#讀取dirf.db文件,調用rpc_read_node rpc_read讀取dirf.db中的root node信息#其中函數調用過程:init_head_from_data -> rpc_read_node -> rpc_readres = init_head_from_data(ht, hash);#解密出root node內容并校驗res = verify_root(ht);#讀取dirf.db中所有node信息并創建文件的節點樹res = init_tree_from_data(ht);#計算各節點內容的hash值,并與保存的hash進行比對,來校驗整個hashtree是否合法res = verify_tree(ht);} ... }

其中verify_root函數內容如下:

static TEE_Result verify_root(struct tee_fs_htree *ht) {TEE_Result res;void *ctx;res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_DECRYPT, ht->head.enc_fek,sizeof(ht->fek), ht->fek);if (res != TEE_SUCCESS)return res;res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, NULL, sizeof(ht->imeta));if (res != TEE_SUCCESS)return res;return authenc_decrypt_final(ctx, ht->head.tag, ht->head.imeta,sizeof(ht->imeta), &ht->imeta); }

=============================================================================================

2. dirf.db文件和安全存儲文件的格式

在了解了基本的流程后,我們接下來來扣一下細節,查看一下文件的格式以及結構體的定義等。

2.1 安全文件的三個區域

使用安全存儲功能生成的文件都會使用相同的格式被保存,而且dirf.db文件與安全文件的格式也相同。
安全文件中的內容分為三個區域,分別用于保存文件頭、結點、數據,文件的內容。
描述如下:

有三個重要的結構體:
tee_fs_htree_node_image:用于保存文件的節點node信息,通過節點可找到對應文件的頭部或數據塊信息;tee_fs_htree_image:用于保存安全文件的頭部數據,從頭部數據中可獲取安全文件的加密密鑰和加密頭部時使用的IV值; tee_fs_fd:安全存儲操作時使用的重要結構體,存放對文件操作時使用的fd、dir、TA的UUID等信息。

結構體字段的定義如下:
@core/include/tee/fs_htree.h

struct tee_fs_htree_meta {uint64_t length; };struct tee_fs_htree_imeta {struct tee_fs_htree_meta meta;uint32_t max_node_id; };struct tee_fs_htree_image {uint8_t iv[TEE_FS_HTREE_IV_SIZE];uint8_t tag[TEE_FS_HTREE_TAG_SIZE];uint8_t enc_fek[TEE_FS_HTREE_FEK_SIZE];uint8_t imeta[sizeof(struct tee_fs_htree_imeta)];uint32_t counter; };struct tee_fs_htree_node_image {uint8_t hash[TEE_FS_HTREE_HASH_SIZE];uint8_t iv[TEE_FS_HTREE_IV_SIZE];uint8_t tag[TEE_FS_HTREE_TAG_SIZE];uint16_t flags; };

2.2 重要結構體的關系框圖

這些重要的結構體的關系框圖如下:

其中tee_fs_htree_storage 結構體定義如下,包含了讀寫RPC調用的函數指針。

struct tee_fs_htree_storage {size_t block_size;TEE_Result (*rpc_read_init)(void *aux, struct tee_fs_rpc_operation *op,enum tee_fs_htree_type type, size_t idx,uint8_t vers, void **data);TEE_Result (*rpc_read_final)(struct tee_fs_rpc_operation *op,size_t *bytes);TEE_Result (*rpc_write_init)(void *aux, struct tee_fs_rpc_operation *op,enum tee_fs_htree_type type, size_t idx,uint8_t vers, void **data);TEE_Result (*rpc_write_final)(struct tee_fs_rpc_operation *op); };

2.3 FEK和IV介紹

有幾個重要的概念 要先介紹一下:

1. SSKSecure Storage Key 安全存儲密鑰,在每臺設備中都不一樣(一般和chipID進行綁定)。2. TSKTrustedApplication Storage Key 可信應用的存儲密鑰,TSK是使用SSK作為密鑰對TA的UUID經HMAC運算得到的。3. FEKFile Encryption Key 是安全存儲功能用于對數據進行加密時使用的AES密鑰。

使用場景:
FEK + IV值 ==》加密密文數據

這幾個KEY的的使用關系:

ChipID + HUK ==》 HMAC運算 ==》 SSK SSK + UUID ==》 HMAC運算 ==》 TSK TSK + RANDOM ==》 AES_CBC ==》 Encryption_FEK

小結:總的來說OPTEE這么設計,主要是想利用兩個文件來完成校驗功能,一個是加密的安全文件,一個是全局的dirf.db文件。
每次想操作安全文件時,會先從dirf.db中找關鍵信息,同時做加解密和校驗工作,來保證數據的安全性。

=============================================================================================

3. 安全的基本操作

了解了以上基本概述后,我們接下來看一下詳細的安全文件的操作,看下是如何處理安全文件的數據的。
因為OPTEE中沒有文件系統的功能,需要借助tee_supplicant守護進程來完成訪問文件系統的工作。
讀寫安全文件也是類似的過程,TA發送RPC請求給tee_supplicant,tee_supplicant完成參數的解析和數據操作。

3.1 安全文件的創建

dirf.db文件的創建
在創建dirf.db文件過程中會產生一個隨機數作為FEK,且在調用update_root函數時會產生另外一個隨機數作為加密FEK的IV值并保存到head.iv中。每次文件的更新時,該IV值都會被新的隨機數替代。

安全文件的創建
在TA中調用TEE_CreatePersistentObject接口時會創建安全文件。在創建安全文件時會初始化安全文件的數據區域。
安全文件創建完成之后,會將初始化數據加密后寫入到安全文件中,然后更新整個安全文件的tee_fs_htree_node_image區域以及保存在文件頭的tee_fs_htree_image區域,到此安全文件創建就已完畢。
為后續能夠通過dirf.db文件找到該安全文件,則還需要更新dirf. db文件的內容,主要是更新dirf.db文件數據區域中的dirfile_entry數據。

3.2 安全文件的讀取

TA對安全文件進行讀寫操作是通過調用TEE_ReadObjectData和TEE_WriteObjectData函數來實現的。這兩個函數的執行最終會進入OP-TEE的內核空間中。
在OP-TEE內核空間調用對應的讀寫接口syscall_storage_obj_read和syscall_storage_obj_write函數來完成對安全文件中數據的讀寫操作。

看一下相關的代碼:
@tee/tee_svc_storage.c
檢查訪問權限,調用

TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len,uint64_t *count) { ... res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE,(uaddr_t)data, len); res = o->pobj->fops->read(o->fh, pos_tmp, data, &bytes); res = copy_to_user_private(count, &u_count, sizeof(*count)); }

@tee_ree_fs.c

static TEE_Result ree_fs_read(struct tee_file_handle *fh, size_t pos,void *buf, size_t *len) {TEE_Result res;mutex_lock(&ree_fs_mutex);res = ree_fs_read_primitive(fh, pos, buf, len);mutex_unlock(&ree_fs_mutex);return res; }static TEE_Result ree_fs_read_primitive(struct tee_file_handle *fh, size_t pos,void *buf, size_t *len) { ...struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);#計算安全文件數據區域中的blockstart_block_num = pos_to_block_num(pos);end_block_num = pos_to_block_num(pos + remain_bytes - 1);block = get_tmp_block();#循環讀取數據while (start_block_num <= end_block_num) {size_t offset = pos % BLOCK_SIZE;size_t size_to_read = MIN(remain_bytes, (size_t)BLOCK_SIZE);if (size_to_read + offset > BLOCK_SIZE)size_to_read = BLOCK_SIZE - offset;#使用IV和FEK解密數據res = tee_fs_htree_read_block(&fdp->ht, start_block_num, block);if (res != TEE_SUCCESS)goto exit;memcpy(data_ptr, block + offset, size_to_read);data_ptr += size_to_read;remain_bytes -= size_to_read;pos += size_to_read;start_block_num++;}res = TEE_SUCCESS;

3.3 安全文件的寫入

寫數據和讀數據流程是類似的
@tee_fs_fs.c

static TEE_Result ree_fs_write(struct tee_file_handle *fh, size_t pos,const void *buf, size_t len) { ...res = get_dirh(&dirh);res = ree_fs_write_primitive(fh, pos, buf, len); ... }static TEE_Result ree_fs_write_primitive(struct tee_file_handle *fh, size_t pos,const void *buf, size_t len) { ...file_size = tee_fs_htree_get_meta(fdp->ht)->length;if ((pos + len) < len)return TEE_ERROR_BAD_PARAMETERS;if (file_size < pos) {res = ree_fs_ftruncate_internal(fdp, pos);if (res != TEE_SUCCESS)return res;}return out_of_place_write(fdp, pos, buf, len); }static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, size_t pos,const void *buf, size_t len) {size_t start_block_num = pos_to_block_num(pos);size_t end_block_num = pos_to_block_num(pos + len - 1);struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);block = get_tmp_block();while (start_block_num <= end_block_num) {size_t offset = pos % BLOCK_SIZE;size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE);if (size_to_write + offset > BLOCK_SIZE)size_to_write = BLOCK_SIZE - offset;if (start_block_num * BLOCK_SIZE <ROUNDUP(meta->length, BLOCK_SIZE)) {res = tee_fs_htree_read_block(&fdp->ht,start_block_num, block);if (res != TEE_SUCCESS)goto exit;} else {memset(block, 0, BLOCK_SIZE);}...memset(block + offset, 0, size_to_write);res = tee_fs_htree_write_block(&fdp->ht, start_block_num,block); ...}if (pos > meta->length) {meta->length = pos;tee_fs_htree_meta_set_dirty(fdp->ht);}... }

@fs_htree.c

TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht_arg,size_t block_num, const void *block) { ...res = get_block_node(ht, true, block_num, &node);res = ht->stor->rpc_write_init(ht->stor_aux, &op,TEE_FS_HTREE_TYPE_BLOCK, block_num,block_vers, &enc_block);res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, &node->node,ht->stor->block_size);res = authenc_encrypt_final(ctx, node->node.tag, block,ht->stor->block_size, enc_block);res = ht->stor->rpc_write_final(&op); ... }

=============================================================================================

4. 安全存儲中的加密解密

安全存儲中的安全文件和dirf.db文件中的數據內容都是按照一定的格式保存的,
主要由三部分組成:tee_fs_htree_image、tee_fs_htree_node_image和數據區域塊。

tee_fs_htree_image和tee_fs_htree_node_image結構體中保存的是安全文件操作時使用到的重要數據的密文數據;tee_fs_htree_image區域中的數據是對元數據經加密重要數據后生成的,而數據區域塊和tee_fs_htree_node_image中的數據則是對數據塊數據經加密后獲得的。

4.1 數據結構的組成與作用

tee_fs_htree_image主要保存加密頭部的IV值、加密安全文件的FEK使用的enc_fek以及加密之后生成的tag、imeta及標記兩個tee_fs_htree_image哪個為最新的counter值。

tee_fs_htree_node_image保存節點的哈希值、加密數據塊區域使用的IV值、標記使用哪個data block的ver的flag值以及加密需要被保存的數據時生成的tag數據。數據塊區域保存的是需要被保存的數據的密文數據。

tee_fs_htree_image中的imeta是按照元數據的方式經加密對應的數據獲得,tee_fs_htree_node_imaget中的tag跟數據塊中的數據則是按照數據塊加密策略經加密后獲得。

4.2 元數據的加密

tee_fs_htree_image區域中的數據是按照元數據方式經加密生成的,該加密過程如圖:

FEK:安全文件和dirf.db文件在執行加密操作時使用的密鑰,該值在文件創建時使用隨機數的方式生成。對已經創建好的文件進行操作時,該值會從tee_fs_htree_image的enc_fek成員中使用TSK解密獲得; TSK:使用SSK和UUID執行HMAC計算得到; AES_ECB:將FEK使用TSK經AES的ECB模式加密操作后生成enc_fek; Encrypted FEK:使用TSK加密FEK得到,保存在tee_fs_htree_image的enc_fek中,最終會被寫入安全文件或者dirf.db文件頭的頭部中; Meta IV:使用安全存儲創建文件或將tee_fs_htree_image寫入文件中都會被隨機生成,最終會被寫入安全文件或dirf.db文件頭的頭部中; Meta Data:/data/tee目錄下每個文件中存放的tee_fs_htree_node_image的個數相關的數據; AES_GCM:將enc_fek+meta iv+meta data使用FEK和meta IV進行AES的GCM模式加密操作生成tag和Encryption Meta Data數據; Tag:加密enc_fek+meta iv+meta data時生成的tag值,數據會被保存在tee_fs_htree_image中的tag成員中;Encryptoed Meta Data:加密enc_fek+meta iv+meta data時生成的imeta值,數據會被保存在tee_fs_htree_image中的imeta成員中。

4.3 數據塊數據的加密

數據塊區域和tee_fs_htree_node_image中的數據是按照數據塊區域的加密策略經加密明文數據生成的,數據塊區域加密策略的加密過程如圖:

Encrypted FEK:使用TSK加密FEK得到,保存在tee_fs_htree_image的enc_fek中,最終會被寫入安全文件或者dirf.db文件頭的頭部中; TSK:使用SSK和UUID執行HMAC計算得到;AES_ECB:將Encrypted FEK使用TSK進行ECB模式的AES解密操作生成FEK;FEK:解密Encrypted FEK之后生成的FEK,用于加密需要被保存的數據塊; Block IV:每次加密數據區域中每個數據塊是都會隨機生成,然后被保存到tee_fs_htree_node_image變量的IV成員中; Block Data:將需要被保存的數據更新到對應的數據塊區域,然后重新加密后生成新的數據塊的密文數據; AES_GCM:將Block IV+Block data使用FEK和塊IV進行GCM模式的AES加密操作生成tag和Encryption Block Data數據; Tag:加密Block IV+Block data時生成的tag值,數據會被保存在tee_fs_htree_node_image中的tag成員中; Encryption Block Data:加密Block IV+Block data時生成的Encryption BlockData值,數據會被保存在文件中數據區域對應的block中。

總結

安全存儲功能是OP-TEE中的一個重要功能,為用戶提供一個安全存取數據的方式。由于每次在對安全文件進行寫入操作時都會使用隨機數重新生成加密時使用的IV值,且加密時使用的密鑰也在創建安全文件時使用隨機數生成,并被加密保存到安全文件的頭部中,所以很難非法獲取到安全存儲中保存的明文數據。
內部實現的數據操作比較復雜,原理和RPMB的存儲有點類似,讀寫數據采用動態變化的參數如IV值或者Counter計數器值,防止重放或者暴力嘗試破解。

參考資料
《手機安全和可信應用開發指南》

總結

以上是生活随笔為你收集整理的OPTEE之安全存储详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 色视频在线免费观看 | 一本—道久久a久久精品蜜桃 | 成人午夜视频精品一区 | 动漫裸体无遮挡 | 人人搞人人爱 | 精久久久久| 久久99国产精品一区 | 日韩久久久久久久久久久 | 美女无遮挡免费网站 | 精品国产午夜 | 久久久性视频 | 精品www久久久久久奶水 | 欲涩漫入口免费网站 | 深夜在线视频 | 色黄网站在线观看 | 中文字幕人妻一区二区在线视频 | 第一av在线 | 亚洲熟悉妇女xxx妇女av | 国产成人无码精品久久久久 | av免费福利 | 婷婷伊人五月天 | 亚洲免费视频一区二区三区 | 日韩欧美一区二区一幕 | 你懂的国产 | 国产精品色综合 | 中文字幕日韩精品在线观看 | 有声小说 成人专区 | 播播成人网 | 青青草娱乐在线 | 国产精品一区二区入口九绯色 | 激情综合网五月激情 | 裸体女人a级一片 | 九九热免费 | 欧美v日韩 | 亚洲欧美日韩第一页 | 国产又粗又长又硬免费视频 | 激情av在线 | 欧美黑人一区二区三区 | 日韩视频免费在线观看 | 欧美精品一区二区蜜臀亚洲 | 少妇福利视频 | 欧美刺激性大交 | 亚洲女同一区二区 | 色爱AV综合网国产精品 | 日韩欧美亚洲一区二区 | 天天干网址 | 久久岛国 | 久久一区二区三区视频 | 国产性精品| 欧美一级性视频 | 在线播放波多野结衣 | 天堂综合网久久 | 国产精品久久久久久久久动漫 | 香蕉色网| 麻豆视屏| 日韩精品一 | 末路1997全集免费观看完整版 | 五月婷婷基地 | 99re视频在线观看 | 双乳被四个男人吃奶h文 | 欧美77777| 国产三区在线成人av | 亚洲人人插 | 99久久精品一区二区三区 | 男人天堂2024 | 亚洲人在线播放 | 在线色导航 | 中文字幕人妻熟女在线 | 亚洲一区二区三区免费看 | 黄色网址在线免费观看 | 丝袜av电影 | 亚洲精品久 | 修仙淫交(高h)h文 | 国产91视频在线观看 | 成年人免费观看视频网站 | 6080亚洲精品一区二区 | 又污又黄又爽的网站 | 国产精品视频999 | 欧美日韩视频 | 亚洲免费视 | 国产中出视频 | 国产欧美一区二区三区在线看 | 国产三级精品三级在线观看 | 日韩激情在线播放 | 一二三区在线 | 欧美一级片在线 | 国内三级视频 | 欧美性受xxx黑人xyx性爽 | 91资源站| 在线免费观看一区二区 | 成人国产av一区二区三区 | 色噜噜狠狠一区二区三区牛牛影视 | 国产毛片91 | 免费a网| 亚洲色图 一区二区 | 日日躁狠狠躁 | 欧美黑人狂野猛交老妇 | 亚洲大片在线观看 | 在线观看国产视频 |