44. TA镜像加载时的验证

来源:互联网 发布:软件著作权登记申请表 编辑:程序博客网 时间:2024/06/05 03:11

  当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文件中,其内容如下:

subdirs-y += kernelsubdirs-y += teesubdirs-y += driversifeq ($(CFG_WITH_USER_TA)-$(CFG_REE_FS_TA),y-y)gensrcs-y += ta_pub_keyproduce-ta_pub_key = ta_pub_key.cdepends-ta_pub_key = $(TA_SIGN_KEY)recipe-ta_pub_key = scripts/pem_to_pub_c.py --prefix ta_pub_key \--key $(TA_SIGN_KEY) --out $(sub-dir-out)/ta_pub_key.ccleanfiles += $(sub-dir-out)/ta_pub_key.cendif
  编译是在处理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脚本的内容如下:

#输入参数解析函数def get_args():import argparseparser = argparse.ArgumentParser()parser.add_argument('--prefix', required=True, \help='Prefix for the public key exponent and modulus in c file')parser.add_argument('--out', required=True, \help='Name of c file for the public key')parser.add_argument('--key', required=True, help='Name of key file')return parser.parse_args()#生成ta_pub_key.c文件的主要函数def main():import arrayfrom Crypto.PublicKey import RSAfrom Crypto.Util.number import long_to_bytes#解析输入参数args = get_args();#打开输入的pem格式的RSA key并读取内容f = open(args.key, 'r')key = RSA.importKey(f.read())f.close#创建ta_pub_key.c文件f = open(args.out, 'w')#将include语句的内容写入到ta_pub_key.c文件中f.write("#include <stdint.h>\n");f.write("#include <stddef.h>\n\n");#写入ta_pub_key_exponent变量的内容和值f.write("const uint32_t " + args.prefix + "_exponent = " +str(key.publickey().e) + ";\n\n")#写入ta_pub_key_modulus变量的内容和值f.write("const uint8_t " + args.prefix + "_modulus[] = {\n")i = 0;for x in array.array("B", long_to_bytes(key.publickey().n)):f.write("0x" + '{0:02x}'.format(x) + ",")i = i + 1;if i % 8 == 0:f.write("\n");else:f.write(" ");f.write("};\n");#写入ta_pub_key_modulus_size变量的值f.write("const size_t " + args.prefix + "_modulus_size = sizeof(" + \args.prefix + "_modulus);\n")f.close()if __name__ == "__main__":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代码内容如下:

static TEE_Result check_shdr(struct shdr *shdr){struct rsa_public_key key;TEE_Result res;//将全局变量ta_pub_key_exponent转成成RSA public key的E值uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); size_t hash_size;/* 校验shdr中的magic值和img_type值 */if (shdr->magic != SHDR_MAGIC || shdr->img_type != SHDR_TA)return TEE_ERROR_SECURITY;/* 检查shdr中的algo成员指定的算法类型是否合法 */if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)return TEE_ERROR_SECURITY;/* 获取verify操作时需要使用的digest的大小 */res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),       &hash_size);if (res != TEE_SUCCESS)return res;/* 检查shdr中的hash_size是否正确 */if (hash_size != shdr->hash_size)return TEE_ERROR_SECURITY;/* 检查OP-TEE中提供的算法接口crypto_ops中的成员是否有效 */if (!crypto_ops.acipher.alloc_rsa_public_key ||    !crypto_ops.acipher.free_rsa_public_key ||    !crypto_ops.acipher.rsassa_verify ||    !crypto_ops.bignum.bin2bn)return TEE_ERROR_NOT_SUPPORTED;/* 分配RSA public key在算法接口中的存储空间 */res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size);if (res != TEE_SUCCESS)return res;/* 将RSA public key中的E值转换成bignumber */res = crypto_ops.bignum.bin2bn((uint8_t *)&e, sizeof(e), key.e);if (res != TEE_SUCCESS)goto out;/* 将ta_pub_key_modulus变量的值作为RSA public key中的N值并转换成bignumber */res = crypto_ops.bignum.bin2bn(ta_pub_key_modulus,       ta_pub_key_modulus_size, key.n);if (res != TEE_SUCCESS)goto out;/* 使用TA镜像文件中的digest部分和signature部分做RSA的verify操作 */res = crypto_ops.acipher.rsassa_verify(shdr->algo, &key, -1,SHDR_GET_HASH(shdr), shdr->hash_size,SHDR_GET_SIG(shdr), shdr->sig_size);out:crypto_ops.acipher.free_rsa_public_key(&key);if (res != TEE_SUCCESS)return TEE_ERROR_SECURITY;return TEE_SUCCESS;}

 在进行verify操作时使用的RSA public key的内容就是在编译时生成ta_public_key.c文件中的那两个全局变量ta_pub_key_exponent和ta_pub_key_modulus





原创粉丝点击