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