存储密钥与文件加密密钥介绍

描述

可信应用的存储密钥

可信应用的存储密钥(Trusted Applicant Storage Key, TSK)是生成FEK时使用到的密钥。

TSK是使用SSK作为密钥对TA的UUID经HMAC计算获得,类似于HMAC(SSK, UUID)的方式生成TSK。

在调用tee_fs_fek_crypt函数时会计算TSK的值。TSK最终会被用来生成FEK, FEK会在使用安全存储功能保存数据时被用来加密数据。

数据库

文件加密密钥

文件加密密钥(File Encryption Key, FEK)是安全存储功能用于对数据进行加密时使用的AES密钥,该密钥在生成文件时会 使用PRNG算法随机产生 ,产生的 FEK会使用TSK进行加密 ,然后保存到head.enc_fek变量中。

(PRNGPRNG(pseudorandom number generator)伪随机数生成器是指通过特定算法生成一系列的数字,使得这一系列的数字看起来是随机的,但是实际是确定的,所以叫伪随机数。)

TA在每次使用 安全存储功能创建一个安全文件时就会生成一个随机数作为FEK ,即每个TA 中的每个安全文件都有一个FEK用于加密对应文件中的数据 。(安全加倍啊)

关于FEK的产生可简单理解为如下公式,使用的初始化向量IV值为0:

AES_CBC(in_key, TSK)

OP-TEE通过调用tee_fs_fek_crypt函数来生成一个FEK,该函数代码如下:

TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode,
                      const uint8_t *in_key, size_t size,
                      uint8_t *out_key)
        {
            TEE_Result res;
            uint8_t *ctx = NULL;
            size_t ctx_size;
            uint8_t tsk[TEE_FS_KM_TSK_SIZE];
            uint8_t dst_key[size];
            /* 检查输入的用于生成FEK的随机数in_key和用于存放生成的out_key地址是否合法 */
            if (! in_key || ! out_key)
                return TEE_ERROR_BAD_PARAMETERS;
            /* 检查in_key长度 */
            if (size ! = TEE_FS_KM_FEK_SIZE)
                return TEE_ERROR_BAD_PARAMETERS;
            /* 判定SSK是否已经被初始化 */
            if (tee_fs_ssk.is_init == 0)
                return TEE_ERROR_GENERIC;
            /* 如果调用时参数uuid不为0,则调用HMAC算法生成TSK。如果UUID的值为0,则默认生成TSK
            使用的原始数据为0 */
            if (uuid) {
                res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
                          TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid));
                if (res ! = TEE_SUCCESS)
                    return res;
            } else {
                uint8_t dummy[1] = { 0 };
                res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
                          TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy));
                if (res ! = TEE_SUCCESS)
                      return res;
              }
              /* 获取调用AEC_CBC操作需要的context的大小 */
              res = crypto_ops.cipher.get_ctx_size(TEE_FS_KM_ENC_FEK_ALG, &ctx_size);
              if (res ! = TEE_SUCCESS)
                  return res;
              /* 分配一份进行AES_CBC操作时需要的context空间 */
              ctx = malloc(ctx_size);
              if (! ctx)
                  return TEE_ERROR_OUT_OF_MEMORY;
              /* 使用TSK作为进行AES_CBC计算使用的key,而IV值默认为0 */
              res = crypto_ops.cipher.init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk,
                              sizeof(tsk), NULL, 0, NULL, 0);
              if (res ! = TEE_SUCCESS)
                  goto exit;
              /* 将输入的in_key填充到context中,做完AES_CBC操作之后,输出的数据将会被保存到dst_
              key中 */
              res = crypto_ops.cipher.update(ctx, TEE_FS_KM_ENC_FEK_ALG,
                      mode, true, in_key, size, dst_key);
              if (res ! = TEE_SUCCESS)
                  goto exit;
              /* 执行AES_CBC的加密运算,生成FEK */
              crypto_ops.cipher.final(ctx, TEE_FS_KM_ENC_FEK_ALG);
              /* 将生成的FEK的值复制到输出参数中 */
              memcpy(out_key, dst_key, sizeof(dst_key));
          exit:
              free(ctx);
              return res;
          }
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分