xref: /optee_os/core/crypto/signed_hdr.c (revision ec1aa4fa2038cc9e1db49873b723a58d9979f5f7)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015-2017, Linaro Limited
4  */
5 
6 #include <crypto/crypto.h>
7 #include <signed_hdr.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ta_pub_key.h>
11 #include <tee_api_types.h>
12 #include <tee/tee_cryp_utl.h>
13 #include <utee_defines.h>
14 #include <util.h>
15 
16 struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size)
17 {
18 	size_t shdr_size;
19 	struct shdr *shdr;
20 	vaddr_t img_va = (vaddr_t)img;
21 	vaddr_t tmp = 0;
22 	size_t end = 0;
23 
24 	if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size)
25 		return NULL;
26 
27 	shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs));
28 	if (ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size)
29 		return NULL;
30 
31 	if (ADD_OVERFLOW(img_va, shdr_size, &tmp))
32 		return NULL;
33 
34 	shdr = malloc(shdr_size);
35 	if (!shdr)
36 		return NULL;
37 	memcpy(shdr, (const uint8_t *)img + offs, shdr_size);
38 
39 	/* Check that the data wasn't modified before the copy was completed */
40 	if (shdr_size != SHDR_GET_SIZE(shdr)) {
41 		free(shdr);
42 		return NULL;
43 	}
44 
45 	return shdr;
46 }
47 
48 TEE_Result shdr_verify_signature(const struct shdr *shdr)
49 {
50 	struct rsa_public_key key;
51 	TEE_Result res;
52 	uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
53 	size_t hash_size;
54 
55 	if (shdr->magic != SHDR_MAGIC)
56 		return TEE_ERROR_SECURITY;
57 
58 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
59 		return TEE_ERROR_SECURITY;
60 
61 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
62 				      &hash_size);
63 	if (res)
64 		return TEE_ERROR_SECURITY;
65 	if (hash_size != shdr->hash_size)
66 		return TEE_ERROR_SECURITY;
67 
68 	res = crypto_acipher_alloc_rsa_public_key(&key,
69 						  ta_pub_key_modulus_size * 8);
70 	if (res)
71 		return TEE_ERROR_SECURITY;
72 
73 	res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
74 	if (res)
75 		goto out;
76 	res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
77 				   key.n);
78 	if (res)
79 		goto out;
80 
81 	res = crypto_acipher_rsassa_verify(shdr->algo, &key, shdr->hash_size,
82 					   SHDR_GET_HASH(shdr), shdr->hash_size,
83 					   SHDR_GET_SIG(shdr), shdr->sig_size);
84 out:
85 	crypto_acipher_free_rsa_public_key(&key);
86 	if (res)
87 		return TEE_ERROR_SECURITY;
88 	return TEE_SUCCESS;
89 }
90