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
shdr_alloc_and_copy(const struct shdr * img,size_t img_size)16 struct shdr *shdr_alloc_and_copy(const struct shdr *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
23 if (img_size < sizeof(struct shdr))
24 return NULL;
25
26 shdr_size = SHDR_GET_SIZE(img);
27 if (img_size < shdr_size)
28 return NULL;
29
30 if (ADD_OVERFLOW(img_va, shdr_size, &tmp))
31 return NULL;
32
33 shdr = malloc(shdr_size);
34 if (!shdr)
35 return NULL;
36 memcpy(shdr, img, shdr_size);
37
38 /* Check that the data wasn't modified before the copy was completed */
39 if (shdr_size != SHDR_GET_SIZE(shdr)) {
40 free(shdr);
41 return NULL;
42 }
43
44 return shdr;
45 }
46
shdr_verify_signature(const struct shdr * shdr)47 TEE_Result shdr_verify_signature(const struct shdr *shdr)
48 {
49 struct rsa_public_key key;
50 TEE_Result res;
51 uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
52 size_t hash_size;
53
54 if (shdr->magic != SHDR_MAGIC)
55 return TEE_ERROR_SECURITY;
56
57 if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
58 return TEE_ERROR_SECURITY;
59
60 res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
61 &hash_size);
62 if (res)
63 return TEE_ERROR_SECURITY;
64 if (hash_size != shdr->hash_size)
65 return TEE_ERROR_SECURITY;
66
67 res = crypto_acipher_alloc_rsa_public_key(&key, shdr->sig_size);
68 if (res)
69 return TEE_ERROR_SECURITY;
70
71 res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
72 if (res)
73 goto out;
74 res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
75 key.n);
76 if (res)
77 goto out;
78
79 res = crypto_acipher_rsassa_verify(shdr->algo, &key, shdr->hash_size,
80 SHDR_GET_HASH(shdr), shdr->hash_size,
81 SHDR_GET_SIG(shdr), shdr->sig_size);
82 out:
83 crypto_acipher_free_rsa_public_key(&key);
84 if (res)
85 return TEE_ERROR_SECURITY;
86 return TEE_SUCCESS;
87 }
88