嵌入式开发论坛

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

44. TA镜像加载时的验证

[复制链接]

59

主题

62

帖子

249

积分

版主

Rank: 7Rank: 7Rank: 7

积分
249
发表于 2018-11-25 14:41:49 | 显示全部楼层 |阅读模式
当TA镜像文件已经被加载到共享内存之后,OP-TEE会对该份数据进行合法性检查。对TA镜像文件合法性的检查是通过调用检查镜像文件中的hash值,magic值,flag等值是否合法并对镜像文件中的signature部分做Verify操作是否成功来判定读取到共享内存中的TA镜像文件内容是否合法。整个验证过程如下:

1. 验证使用的RSApublic key的产生和获取  编译整个工程的时候会产生一个ta_pub_key.c文件,该文件中存放的就是在验证TA镜像文件合法性的时候使用到的RSA public key的内容,该文件是在编译gensrcs-y目标中的ta_pub_key成员来产生的,该部分的内容定义在optee_os/core/sub.mk文件中,其内容如下:
  1. subdirs-y += kernel
  2. subdirs-y += tee
  3. subdirs-y += drivers
  4. ifeq ($(CFG_WITH_USER_TA)-$(CFG_REE_FS_TA),y-y)
  5. gensrcs-y += ta_pub_key
  6. produce-ta_pub_key = ta_pub_key.c
  7. depends-ta_pub_key = $(TA_SIGN_KEY)
  8. recipe-ta_pub_key = scripts/pem_to_pub_c.py --prefix ta_pub_key \
  9.         --key $(TA_SIGN_KEY) --out $(sub-dir-out)/ta_pub_key.c
  10. cleanfiles += $(sub-dir-out)/ta_pub_key.c
  11. endif
复制代码

  编译是在处理ta_pub_key目标时调用recipe-ta_pub_key来产生ta_pub_key.c文件,该文件将会被保存在optee_os/out/arm/core/目录中。在recipe-ta_pub_key中通过调用pem_to_pub_c.py脚本解析存放在optee_os/keys目录中的rsa key获取public key的相关内容并保存到ta_pub_key.c文件中,pem_to_pub_c.py脚本的内容如下:
  1. #输入参数解析函数
  2. def get_args():
  3.         import argparse
  4.         parser = argparse.ArgumentParser()
  5.         parser.add_argument('--prefix', required=True, \
  6.                 help='Prefix for the public key exponent and modulus in c file')
  7.         parser.add_argument('--out', required=True, \
  8.                 help='Name of c file for the public key')
  9.         parser.add_argument('--key', required=True, help='Name of key file')
  10.         return parser.parse_args()
  11. #生成ta_pub_key.c文件的主要函数
  12. def main():
  13.         import array
  14.         from Crypto.PublicKey import RSA
  15.         from Crypto.Util.number import long_to_bytes
  16.         #解析输入参数
  17.         args = get_args();
  18.         #打开输入的pem格式的RSA key并读取内容
  19.         f = open(args.key, 'r')
  20.         key = RSA.importKey(f.read())
  21.         f.close
  22.         #创建ta_pub_key.c文件
  23.         f = open(args.out, 'w')
  24.         #将include语句的内容写入到ta_pub_key.c文件中
  25.         f.write("#include <stdint.h>\n");
  26.         f.write("#include <stddef.h>\n\n");
  27.         #写入ta_pub_key_exponent变量的内容和值
  28.         f.write("const uint32_t " + args.prefix + "_exponent = " +
  29.                 str(key.publickey().e) + ";\n\n")
  30.         #写入ta_pub_key_modulus变量的内容和值
  31.         f.write("const uint8_t " + args.prefix + "_modulus[] = {\n")
  32.         i = 0;
  33.         for x in array.array("B", long_to_bytes(key.publickey().n)):
  34.                 f.write("0x" + '{0:02x}'.format(x) + ",")
  35.                 i = i + 1;
  36.                 if i % 8 == 0:
  37.                         f.write("\n");
  38.                 else:
  39.                         f.write(" ");
  40.         f.write("};\n");
  41.         #写入ta_pub_key_modulus_size变量的值
  42.         f.write("const size_t " + args.prefix + "_modulus_size = sizeof(" + \
  43.                 args.prefix + "_modulus);\n")
  44.         f.close()
  45. if __name__ == "__main__":
  46.         main()
复制代码

生成的ta_pub_key.c文件中将定义三个全局变量并赋值,这三个变量就是RSA public key的内容,作用和内容分别为:
ta_pub_key_exponent    //RSA public key中的E值
ta_pub_key_modulus     //RSA public key中的N值
ta_pub_key_modulus_size     //RSA key的长度,再次该值为256也即表示该RSA key为RSA2048
这三个变量作为全局变量,在对TA镜像文件进行验签的时候用来做RSA2048的verify操作。
2. TA镜像文件的合法性检查的实现  对TA镜像文件内容合法性的检查是通过调用check_shdr函数来实现的,该函数中除了会对TA镜像文件中的signature内容做verify操作之外,还对校验TA镜像文件中shdr部分中的内容,check_shdr代码内容如下:
  1. static TEE_Result check_shdr(struct shdr *shdr)
  2. {
  3.         struct rsa_public_key key;
  4.         TEE_Result res;
  5.         //将全局变量ta_pub_key_exponent转成成RSA public key的E值
  6.         uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
  7.         size_t hash_size;
  8.         /* 校验shdr中的magic值和img_type值 */
  9.         if (shdr->magic != SHDR_MAGIC || shdr->img_type != SHDR_TA)
  10.                 return TEE_ERROR_SECURITY;
  11.         /* 检查shdr中的algo成员指定的算法类型是否合法 */
  12.         if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
  13.                 return TEE_ERROR_SECURITY;
  14.         /* 获取verify操作时需要使用的digest的大小 */
  15.         res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
  16.                                        &hash_size);
  17.         if (res != TEE_SUCCESS)
  18.                 return res;
  19.         /* 检查shdr中的hash_size是否正确 */
  20.         if (hash_size != shdr->hash_size)
  21.                 return TEE_ERROR_SECURITY;
  22.         /* 检查OP-TEE中提供的算法接口crypto_ops中的成员是否有效 */
  23.         if (!crypto_ops.acipher.alloc_rsa_public_key ||
  24.             !crypto_ops.acipher.free_rsa_public_key ||
  25.             !crypto_ops.acipher.rsassa_verify ||
  26.             !crypto_ops.bignum.bin2bn)
  27.                 return TEE_ERROR_NOT_SUPPORTED;
  28.         /* 分配RSA public key在算法接口中的存储空间 */
  29.         res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size);
  30.         if (res != TEE_SUCCESS)
  31.                 return res;
  32.         /* 将RSA public key中的E值转换成bignumber */
  33.         res = crypto_ops.bignum.bin2bn((uint8_t *)&e, sizeof(e), key.e);
  34.         if (res != TEE_SUCCESS)
  35.                 goto out;
  36.         /* 将ta_pub_key_modulus变量的值作为RSA public key中的N值并转换成bignumber */
  37.         res = crypto_ops.bignum.bin2bn(ta_pub_key_modulus,
  38.                                        ta_pub_key_modulus_size, key.n);
  39.         if (res != TEE_SUCCESS)
  40.                 goto out;
  41.         /* 使用TA镜像文件中的digest部分和signature部分做RSA的verify操作 */
  42.         res = crypto_ops.acipher.rsassa_verify(shdr->algo, &key, -1,
  43.                                 SHDR_GET_HASH(shdr), shdr->hash_size,
  44.                                 SHDR_GET_SIG(shdr), shdr->sig_size);
  45. out:
  46.         crypto_ops.acipher.free_rsa_public_key(&key);
  47.         if (res != TEE_SUCCESS)
  48.                 return TEE_ERROR_SECURITY;
  49.         return TEE_SUCCESS;
  50. }
复制代码
 在进行verify操作时使用的RSA public key的内容就是在编译时生成ta_public_key.c文件中的那两个全局变量ta_pub_key_exponent和ta_pub_key_modulus








回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2019-3-18 23:26 , Processed in 0.068165 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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