嵌入式开发论坛

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

43. TA镜像文件的签名

[复制链接]

59

主题

62

帖子

249

积分

版主

Rank: 7Rank: 7Rank: 7

积分
249
发表于 2018-11-25 14:40:36 | 显示全部楼层 |阅读模式
TA镜像文件的是在OP-TEE工程编译过程中被编译生成,也可以通过单独调用AT目录下的脚本来进行编译,但是前提是OP-TEE工程被完整编译过。编译后会生成原始的TA镜像文件然后使用签名脚本对该文件进行电子签名生成.ta文件,这也就是最终的TA镜像文件。
1. TA镜像文件的编译  编译TA镜像文件是通过对TA源代码目录中的Makefile文件执行make指令开始,该Makefile文件将会包含optee_os/ta/mk/ta_dev_kit.mk文件,在该文件中会定义各种目标依赖关系和Object,编译完需要的目标和object之后,编译器将会按照optee_os/ta/arch/arm/link.mk文件中的依赖关系链接成xxx.ta文件,其中xxx是该TA的UUID的值,在link.mk中的连接依赖关系如下:
  1. $(link-script-pp): $(link-script) $(MAKEFILE_LIST)
  2.         @$(cmd-echo-silent) '  CPP     $@'
  3.         $(q)mkdir -p $(dir $@)
  4.         $(q)$(CPP$(sm)) -Wp,-P,-MT,$@,-MD,$(link-script-dep) \
  5.                 $(link-script-cppflags-$(sm)) [        DISCUZ_CODE_8        ]lt; > $@

  6. $(link-out-dir)/$(binary).elf: $(objs) $(libdeps) $(link-script-pp)
  7.         @$(cmd-echo-silent) '  LD      $@'
  8.         $(q)$(LD$(sm)) $(ldargs-$(binary).elf) -o $@

  9. $(link-out-dir)/$(binary).dmp: $(link-out-dir)/$(binary).elf
  10.         @$(cmd-echo-silent) '  OBJDUMP $@'
  11.         $(q)$(OBJDUMP$(sm)) -l -x -d [        DISCUZ_CODE_8        ]lt; > $@

  12. $(link-out-dir)/$(binary).stripped.elf: $(link-out-dir)/$(binary).elf
  13.         @$(cmd-echo-silent) '  OBJCOPY $@'
  14.         $(q)$(OBJCOPY$(sm)) --strip-unneeded [        DISCUZ_CODE_8        ]lt; $@

  15. $(link-out-dir)/$(binary).ta: $(link-out-dir)/$(binary).stripped.elf \
  16.                                 $(TA_SIGN_KEY)
  17.         @echo '  SIGN    $@'
  18.         $(q)$(SIGN) --key $(TA_SIGN_KEY) --in [        DISCUZ_CODE_8        ]lt; --out $@
复制代码

  $(link-out-dir)/$(binary).stripped.elf目标会将TA镜像文件中的调试信息给删除然后再次使用,在原始的TA镜像文件的头部有一个ta_head的段,该段中存放的就是该TA的基本信息以及被调用到的入口地址,该段中的内容将会在加载TA进行到OP-TEE时和调用TA执行特定command的时候被使用到。存放在该段中的内容定义在optee_os/ta/arch/arm/user_ta_header.c文件中,其内容如下:
  1. const struct ta_head ta_head __section(".ta_head") = {
  2.         .uuid = TA_UUID,        //TA的UUID值
  3.         .stack_size = TA_STACK_SIZE + TA_FRAMEWORK_STACK_SIZE,        //TA运行栈大小
  4.         .flags = TA_FLAG_USER_MODE | TA_FLAGS,        //该TA运行flag表示该TA将运行在用户红箭
  5. #ifdef __ILP32__
  6.         /*
  7.          * This workaround is neded on 32-bit because it seems we can't
  8.          * initialize a 64-bit integer from the address of a function.
  9.          */
  10.         .entry.ptr32 = { .lo = (uint32_t)__utee_entry },
  11. #else
  12.         .entry.ptr64 = (uint64_t)__utee_entry,        //定义该TA的入口函数
  13. #endif
  14. };
复制代码

2. 对TA镜像文件的签名
  生成原始的TA镜像文件之后将会对该进行文件进行签名生成最终的xxx.ta文件,该文件会被保存在REE的文件系统中。对原始TA镜像文件的签名是通过调用调用optee_os/scripts/sign.py文件使用optee_os/keys目录下的RSA2048的 私钥default_ta.pem来完成,当该TA需要被正式release的时候需要使用自有的私钥替换掉该。sign.py文件的内容如下
  1. #!/usr/bin/env python
  2. #解析输入参数的函数
  3. def get_args():
  4. from argparse import ArgumentParser
  5. parser = ArgumentParser()
  6. parser.add_argument('--key', required=True, help='Name of key file')
  7. parser.add_argument('--in', required=True, dest='inf', \
  8.                 help='Name of in file')
  9. parser.add_argument('--out', required=True, help='Name of out file')
  10. return parser.parse_args()
  11. #脚本的入口函数
  12. def main():
  13.         #导入各种依赖python库
  14. from Crypto.Signature import PKCS1_v1_5
  15. from Crypto.Hash import SHA256
  16. from Crypto.PublicKey import RSA
  17. import struct
  18. #解析输入参数
  19. args = get_args()
  20. #打开输入的RSA key并读取该key的内容存放到key变量中
  21. f = open(args.key, 'rb')
  22. key = RSA.importKey(f.read())
  23. f.close()
  24. #打开原始的TA镜像文件并读取该文件中的内容保存到img变量中
  25. f = open(args.inf, 'rb')
  26. img = f.read()
  27. f.close()
  28. #创建爱你RSA签名结构体和sha256运算结构体
  29. signer = PKCS1_v1_5.new(key)
  30. h = SHA256.new()
  31. digest_len = h.digest_size        #设定SHA256计算的输出结果长度
  32. sig_len = len(signer.sign(h))        #设定签名长度
  33. img_size = len(img)        #获取原始进行文件内容的长度
  34. magic = 0x4f545348        # magic值
  35. img_type = 0                # TA类型代号
  36. algo = 0x70004830        # TEE_ALG_RSASSA_PKCS1_V1_5_SHA256(TA中验签对应的算法ID)
  37. #将magic, img_type, img_size, algo, digese等信息按照一定的格式转成后存放在shdr变量中
  38. shdr = struct.pack('<IIIIHH', \
  39.                 magic, img_type, img_size, algo, digest_len, sig_len)
  40.         #将shdr变量和TA原始镜像文件的内容填充到SH256结构体数据区域中
  41. h.update(shdr)
  42. h.update(img)
  43. #对h的摘要使用输入的私钥做RSA2048签名生成signature
  44. sig = signer.sign(h)
  45. #并将shdr, shdr+img的SHA结果,signature,原始TA镜像文件内容写入到输出文件
  46. f = open(args.out, 'wb')
  47. f.write(shdr)
  48. f.write(h.digest())
  49. f.write(sig)
  50. f.write(img)
  51. f.close()
  52. if __name__ == "__main__":
  53. main()
复制代码

签名完成之后TA镜像文件中的内容示意图如下:

签名后的TA镜像文件在被加载到OP-TEE的内存中之前OP-TEE会使用signature对该镜像文件进行合法性检查,而TA中的ta_head段中的内容将会在open session操作的时候被使用到,主要告知系统如何调用到TA中的open session, invoke command, closesession等操作




回复

使用道具 举报

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

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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