xref: /optee_os/core/crypto/signed_hdr.c (revision 062765e4f80b97c90fd62d17859b675797af5de9)
1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2064663e8SJens Wiklander /*
3064663e8SJens Wiklander  * Copyright (c) 2015-2017, Linaro Limited
4064663e8SJens Wiklander  */
5064663e8SJens Wiklander 
6064663e8SJens Wiklander #include <crypto/crypto.h>
7064663e8SJens Wiklander #include <signed_hdr.h>
8064663e8SJens Wiklander #include <stdlib.h>
9064663e8SJens Wiklander #include <string.h>
10064663e8SJens Wiklander #include <ta_pub_key.h>
11064663e8SJens Wiklander #include <tee_api_types.h>
12064663e8SJens Wiklander #include <tee/tee_cryp_utl.h>
13064663e8SJens Wiklander #include <utee_defines.h>
14*062765e4SJerome Forissier #include <util.h>
15064663e8SJens Wiklander 
16064663e8SJens Wiklander struct shdr *shdr_alloc_and_copy(const struct shdr *img, size_t img_size)
17064663e8SJens Wiklander {
18064663e8SJens Wiklander 	size_t shdr_size;
19064663e8SJens Wiklander 	struct shdr *shdr;
20*062765e4SJerome Forissier 	vaddr_t img_va = (vaddr_t)img;
21*062765e4SJerome Forissier 	vaddr_t tmp = 0;
22064663e8SJens Wiklander 
23064663e8SJens Wiklander 	if (img_size < sizeof(struct shdr))
244ca9e426SJoakim Bech 		return NULL;
254ca9e426SJoakim Bech 
26064663e8SJens Wiklander 	shdr_size = SHDR_GET_SIZE(img);
27064663e8SJens Wiklander 	if (img_size < shdr_size)
284ca9e426SJoakim Bech 		return NULL;
29064663e8SJens Wiklander 
30*062765e4SJerome Forissier 	if (ADD_OVERFLOW(img_va, shdr_size, &tmp))
31*062765e4SJerome Forissier 		return NULL;
32*062765e4SJerome Forissier 
33064663e8SJens Wiklander 	shdr = malloc(shdr_size);
34064663e8SJens Wiklander 	if (!shdr)
35064663e8SJens Wiklander 		return NULL;
36064663e8SJens Wiklander 	memcpy(shdr, img, shdr_size);
37064663e8SJens Wiklander 
38064663e8SJens Wiklander 	/* Check that the data wasn't modified before the copy was completed */
39064663e8SJens Wiklander 	if (shdr_size != SHDR_GET_SIZE(shdr)) {
40064663e8SJens Wiklander 		free(shdr);
41064663e8SJens Wiklander 		return NULL;
42064663e8SJens Wiklander 	}
43064663e8SJens Wiklander 
44064663e8SJens Wiklander 	return shdr;
45064663e8SJens Wiklander }
46064663e8SJens Wiklander 
47064663e8SJens Wiklander TEE_Result shdr_verify_signature(const struct shdr *shdr)
48064663e8SJens Wiklander {
49064663e8SJens Wiklander 	struct rsa_public_key key;
50064663e8SJens Wiklander 	TEE_Result res;
51064663e8SJens Wiklander 	uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
52064663e8SJens Wiklander 	size_t hash_size;
53064663e8SJens Wiklander 
54064663e8SJens Wiklander 	if (shdr->magic != SHDR_MAGIC)
55064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
56064663e8SJens Wiklander 
57064663e8SJens Wiklander 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
58064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
59064663e8SJens Wiklander 
60064663e8SJens Wiklander 	res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
61064663e8SJens Wiklander 				       &hash_size);
62064663e8SJens Wiklander 	if (res)
63064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
64064663e8SJens Wiklander 	if (hash_size != shdr->hash_size)
65064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
66064663e8SJens Wiklander 
67064663e8SJens Wiklander 	res = crypto_acipher_alloc_rsa_public_key(&key, shdr->sig_size);
68064663e8SJens Wiklander 	if (res)
69064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
70064663e8SJens Wiklander 
71064663e8SJens Wiklander 	res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
72064663e8SJens Wiklander 	if (res)
73064663e8SJens Wiklander 		goto out;
74064663e8SJens Wiklander 	res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
75064663e8SJens Wiklander 				   key.n);
76064663e8SJens Wiklander 	if (res)
77064663e8SJens Wiklander 		goto out;
78064663e8SJens Wiklander 
79064663e8SJens Wiklander 	res = crypto_acipher_rsassa_verify(shdr->algo, &key, -1,
80064663e8SJens Wiklander 					   SHDR_GET_HASH(shdr), shdr->hash_size,
81064663e8SJens Wiklander 					   SHDR_GET_SIG(shdr), shdr->sig_size);
82064663e8SJens Wiklander out:
83064663e8SJens Wiklander 	crypto_acipher_free_rsa_public_key(&key);
84064663e8SJens Wiklander 	if (res)
85064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
86064663e8SJens Wiklander 	return TEE_SUCCESS;
87064663e8SJens Wiklander }
88