嵌入式开发论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 68|回复: 0

37. OP-TEE中secure stroage------安全存储使用的key的产生

[复制链接]

59

主题

62

帖子

249

积分

版主

Rank: 7Rank: 7Rank: 7

积分
249
发表于 2018-11-25 14:34:06 | 显示全部楼层 |阅读模式
在OP-TEE中使用secure storage功能保存的数据都是经过AES加密之后被保存在文件系统或者是RPMB中的,使用AES算法进行加密或者解密的时候需要提供加密使用的key和初始化向量IV值。每个TA在使用secure storage功能保存数据的时候都会生成一个随机数作为IV值,使用FEK的值作为AES的key。而FEK的值是由一系列HMAC操作得到的。FEK值的生成牵扯到SSK和TSK,本文将介绍这些key的使用和生成,key之间的关系如下图所示:

1. SSK(Secure Storage Key)  在每台设备中的SSK的值不一样,在OP-TEE启动的时候会使用chip ID和HUK经过HMAC算法计算获取SSK的值,并见SSK的值保存在一般该值在结构体变量tee_fs_ssk的key成员成,以备生成其他key使用。工厂生产的时候会将HUK写入到OTP/efuse中,并且在normal world端是无法读取到HUK的值的,而chip ID在芯片出厂之后就会被写入到芯片中。
  在OP-TEE启动的时候会执行tee_fs_init_key_manager函数,该函数就是用来根据SSK = HMAC(HUK, message)的方式来生成SSK,并保存在tee_fs_ssk的key成员中。该函数的内容如下:
  1. static TEE_Result tee_fs_init_key_manager(void)
  2. {
  3.         int res = TEE_SUCCESS;
  4.         struct tee_hw_unique_key huk;
  5.         uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH];
  6.         uint8_t message[sizeof(chip_id) + sizeof(string_for_ssk_gen)];

  7.         /* Secure Storage Key Generation:
  8.          *
  9.          *     SSK = HMAC(HUK, message)
  10.          *     message := concatenate(chip_id, static string)
  11.          * */
  12. /* 获取HUK的值(该接口的实现与平台有关,不同的芯片具有不同的读取HUK值的方式) */
  13.         tee_otp_get_hw_unique_key(&huk);

  14. /*  获取chip ID的值(不同的芯片具有不同的读取chip id值的方式)*/
  15.         tee_otp_get_die_id(chip_id, sizeof(chip_id));

  16. /* 将chip id + string_for_ssk_gen连接后的值保存到message中,string_for_ssk_gen是一个
  17. 静态的字符串,该值被hard code在代码中 */
  18.         memcpy(message, chip_id, sizeof(chip_id));
  19.         memcpy(message + sizeof(chip_id), string_for_ssk_gen,
  20.                         sizeof(string_for_ssk_gen));

  21. /* 使用huk的值对message的内容做HMAC运算,将获取到数据作为SSK,保存到tee_fs_ssk
  22. 变量的key成员中 */
  23.         res = do_hmac(tee_fs_ssk.key, sizeof(tee_fs_ssk.key),
  24.                         huk.data, sizeof(huk.data),
  25.                         message, sizeof(message));

  26. /* 标记ssk已经生产 */
  27.         if (res == TEE_SUCCESS)
  28.                 tee_fs_ssk.is_init = 1;

  29.         return res;
  30. }
复制代码

2. TSK(Trusted Applicant Storage Key)
  TSK是用来生成FEK使用到的key,TSK的值由TA的UUID使用SSK作为key,经过HMAC计算获得,类似于HMAC(SSK, UUID)的方式得到TSK的值,在调用tee_fs_fek_crypt函数的时候就会去计算TSK的值。TSK最终会被用来生成FEK,FEK将会在使用secure storage功能保存数据的时候被用来加密数据。
3. FEK(File Encryption Key)  FEK是secure storage用来对数据进行加密使用的AES key,该key在生成文件的时候会使用PRNG来随机产生,产生的FEK会使用TSK进行加密,然后保存到head.enc_fek变量中,一个TA每次在使用secure storage创建一个安全文件时就生成一个随机数作为FEK,也即是每个TA中的每个安全文件都有一个FEK用于加密对应的文件数据。关于FEK值的产生可以简单理解为如下公式,使用的初始化向量IV值为0:
AES_CBC(in_key, TSK)
  通过调用tee_fs_fek_crypt函数就能生成一个FEK的值,该函数代码如下:
  1. TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode,
  2.                             const uint8_t *in_key, size_t size,
  3.                             uint8_t *out_key)
  4. {
  5.         TEE_Result res;
  6.         uint8_t *ctx = NULL;
  7.         size_t ctx_size;
  8.         uint8_t tsk[TEE_FS_KM_TSK_SIZE];
  9.         uint8_t dst_key[size];

  10. /* 检查输入的用于生成FEK的随机数in_key和用于存放生成的out_key地址是否合法 */
  11.         if (!in_key || !out_key)
  12.                 return TEE_ERROR_BAD_PARAMETERS;

  13. /* 检查in_key长度 */
  14.         if (size != TEE_FS_KM_FEK_SIZE)
  15.                 return TEE_ERROR_BAD_PARAMETERS;

  16. /* 判定SSK是否已经被初始化 */
  17.         if (tee_fs_ssk.is_init == 0)
  18.                 return TEE_ERROR_GENERIC;

  19. /* 如果调用的时候参数uuid不为0,则调用HMAC算法生成TSK。如果UUID的值为0,则
  20. 默认生成TSK使用的原始数据为0 */
  21.         if (uuid) {
  22.                 res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
  23.                               TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid));
  24.                 if (res != TEE_SUCCESS)
  25.                         return res;
  26.         } else {
  27.                 /*
  28.                  * Pick something of a different size than TEE_UUID to
  29.                  * guarantee that there's never a conflict.
  30.                  */
  31.                 uint8_t dummy[1] = { 0 };

  32.                 res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key,
  33.                               TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy));
  34.                 if (res != TEE_SUCCESS)
  35.                         return res;
  36.         }

  37. /* 获取调用AEC_CBC操作需要的context的大小 */
  38.         res = crypto_ops.cipher.get_ctx_size(TEE_FS_KM_ENC_FEK_ALG, &ctx_size);
  39.         if (res != TEE_SUCCESS)
  40.                 return res;

  41. /* 分配一份进行AES_CBC操作时需要的context空间 */
  42.         ctx = malloc(ctx_size);
  43.         if (!ctx)
  44.                 return TEE_ERROR_OUT_OF_MEMORY;

  45. /* 使用TSK作为进行AES_CBC计算使用的key,而IV值默认为0 */
  46.         res = crypto_ops.cipher.init(ctx, TEE_FS_KM_ENC_FEK_ALG, mode, tsk,
  47.                                      sizeof(tsk), NULL, 0, NULL, 0);
  48.         if (res != TEE_SUCCESS)
  49.                 goto exit;

  50. /* 将输入的in_key填充到context中,做完AES_CBC操作之后,输出的数据将会被保存到
  51. dst_key中 */
  52.         res = crypto_ops.cipher.update(ctx, TEE_FS_KM_ENC_FEK_ALG,
  53.                         mode, true, in_key, size, dst_key);
  54.         if (res != TEE_SUCCESS)
  55.                 goto exit;

  56. /* 执行AES_CBC的加密运算,生成FEK */
  57.         crypto_ops.cipher.final(ctx, TEE_FS_KM_ENC_FEK_ALG);

  58. /* 将生成的FEK的值拷贝到输出参数中 */
  59.         memcpy(out_key, dst_key, sizeof(dst_key));

  60. exit:
  61.         free(ctx);

  62.         return res;
  63. }
复制代码










回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|TEE and Virtualization

GMT+8, 2019-3-19 00:46 , Processed in 0.079071 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表