xref: /optee_os/core/crypto/signed_hdr.c (revision bef7d11d34fef262e0d3d4c71a2c1e7f92e83289)
1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2064663e8SJens Wiklander /*
3c34d0d91SJens Wiklander  * Copyright (c) 2015-2022, Linaro Limited
4064663e8SJens Wiklander  */
5064663e8SJens Wiklander 
6064663e8SJens Wiklander #include <crypto/crypto.h>
7c34d0d91SJens Wiklander #include <kernel/panic.h>
8c34d0d91SJens Wiklander #include <mempool.h>
9064663e8SJens Wiklander #include <signed_hdr.h>
10064663e8SJens Wiklander #include <stdlib.h>
11064663e8SJens Wiklander #include <string.h>
12064663e8SJens Wiklander #include <ta_pub_key.h>
13064663e8SJens Wiklander #include <tee_api_types.h>
14064663e8SJens Wiklander #include <tee/tee_cryp_utl.h>
15c34d0d91SJens Wiklander #include <tee/uuid.h>
16064663e8SJens Wiklander #include <utee_defines.h>
17062765e4SJerome Forissier #include <util.h>
18064663e8SJens Wiklander 
19ec1aa4faSJens Wiklander struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size)
20064663e8SJens Wiklander {
21064663e8SJens Wiklander 	size_t shdr_size;
22064663e8SJens Wiklander 	struct shdr *shdr;
23062765e4SJerome Forissier 	vaddr_t img_va = (vaddr_t)img;
24062765e4SJerome Forissier 	vaddr_t tmp = 0;
25ec1aa4faSJens Wiklander 	size_t end = 0;
26064663e8SJens Wiklander 
27ec1aa4faSJens Wiklander 	if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size)
284ca9e426SJoakim Bech 		return NULL;
294ca9e426SJoakim Bech 
30ec1aa4faSJens Wiklander 	shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs));
31ec1aa4faSJens Wiklander 	if (ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size)
324ca9e426SJoakim Bech 		return NULL;
33064663e8SJens Wiklander 
34062765e4SJerome Forissier 	if (ADD_OVERFLOW(img_va, shdr_size, &tmp))
35062765e4SJerome Forissier 		return NULL;
36062765e4SJerome Forissier 
37064663e8SJens Wiklander 	shdr = malloc(shdr_size);
38064663e8SJens Wiklander 	if (!shdr)
39064663e8SJens Wiklander 		return NULL;
40ec1aa4faSJens Wiklander 	memcpy(shdr, (const uint8_t *)img + offs, shdr_size);
41064663e8SJens Wiklander 
42064663e8SJens Wiklander 	/* Check that the data wasn't modified before the copy was completed */
43064663e8SJens Wiklander 	if (shdr_size != SHDR_GET_SIZE(shdr)) {
44064663e8SJens Wiklander 		free(shdr);
45064663e8SJens Wiklander 		return NULL;
46064663e8SJens Wiklander 	}
47064663e8SJens Wiklander 
48064663e8SJens Wiklander 	return shdr;
49064663e8SJens Wiklander }
50064663e8SJens Wiklander 
51*bef7d11dSJens Wiklander static bool is_weak_hash_algo(uint32_t algo)
52*bef7d11dSJens Wiklander {
53*bef7d11dSJens Wiklander 	return algo == TEE_ALG_MD5 || algo == TEE_ALG_SHA1 ||
54*bef7d11dSJens Wiklander 	       algo == TEE_ALG_MD5SHA1;
55*bef7d11dSJens Wiklander }
56*bef7d11dSJens Wiklander 
57064663e8SJens Wiklander TEE_Result shdr_verify_signature(const struct shdr *shdr)
58064663e8SJens Wiklander {
59*bef7d11dSJens Wiklander 	struct rsa_public_key key = { };
60*bef7d11dSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
61064663e8SJens Wiklander 	uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
62*bef7d11dSJens Wiklander 	size_t hash_size = 0;
63*bef7d11dSJens Wiklander 	size_t hash_algo = 0;
64064663e8SJens Wiklander 
65064663e8SJens Wiklander 	if (shdr->magic != SHDR_MAGIC)
66064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
67064663e8SJens Wiklander 
68064663e8SJens Wiklander 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
69064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
70064663e8SJens Wiklander 
71*bef7d11dSJens Wiklander 	hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
72*bef7d11dSJens Wiklander 	if (is_weak_hash_algo(hash_algo))
73*bef7d11dSJens Wiklander 		return TEE_ERROR_SECURITY;
74*bef7d11dSJens Wiklander 
75*bef7d11dSJens Wiklander 	res = tee_alg_get_digest_size(hash_algo, &hash_size);
76064663e8SJens Wiklander 	if (res)
77064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
78064663e8SJens Wiklander 	if (hash_size != shdr->hash_size)
79064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
80064663e8SJens Wiklander 
8144c8e3cbSCedric Neveux 	res = crypto_acipher_alloc_rsa_public_key(&key,
8244c8e3cbSCedric Neveux 						  ta_pub_key_modulus_size * 8);
83064663e8SJens Wiklander 	if (res)
84064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
85064663e8SJens Wiklander 
86064663e8SJens Wiklander 	res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
87064663e8SJens Wiklander 	if (res)
88064663e8SJens Wiklander 		goto out;
89064663e8SJens Wiklander 	res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
90064663e8SJens Wiklander 				   key.n);
91064663e8SJens Wiklander 	if (res)
92064663e8SJens Wiklander 		goto out;
93064663e8SJens Wiklander 
942139aa8cSJens Wiklander 	res = crypto_acipher_rsassa_verify(shdr->algo, &key, shdr->hash_size,
95064663e8SJens Wiklander 					   SHDR_GET_HASH(shdr), shdr->hash_size,
96064663e8SJens Wiklander 					   SHDR_GET_SIG(shdr), shdr->sig_size);
97064663e8SJens Wiklander out:
98064663e8SJens Wiklander 	crypto_acipher_free_rsa_public_key(&key);
99064663e8SJens Wiklander 	if (res)
100064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
101064663e8SJens Wiklander 	return TEE_SUCCESS;
102064663e8SJens Wiklander }
103c34d0d91SJens Wiklander 
104c34d0d91SJens Wiklander static const struct shdr_subkey_attr *
105c34d0d91SJens Wiklander find_attr(const struct shdr_subkey *subkey, uint32_t id)
106c34d0d91SJens Wiklander {
107c34d0d91SJens Wiklander 	size_t n = 0;
108c34d0d91SJens Wiklander 
109c34d0d91SJens Wiklander 	for (n = 0; n < subkey->attr_count; n++)
110c34d0d91SJens Wiklander 		if (subkey->attrs[n].id == id)
111c34d0d91SJens Wiklander 			return subkey->attrs + n;
112c34d0d91SJens Wiklander 
113c34d0d91SJens Wiklander 	return NULL;
114c34d0d91SJens Wiklander }
115c34d0d91SJens Wiklander 
116c34d0d91SJens Wiklander static TEE_Result load_rsa_key(const struct shdr_subkey *subkey,
117c34d0d91SJens Wiklander 			       struct rsa_public_key **key_pp)
118c34d0d91SJens Wiklander {
119c34d0d91SJens Wiklander 	const uint8_t *base = (const uint8_t *)subkey;
120c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *pub_exp = NULL;
121c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *modulus = NULL;
122c34d0d91SJens Wiklander 	struct rsa_public_key *key = NULL;
123c34d0d91SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
124c34d0d91SJens Wiklander 
125c34d0d91SJens Wiklander 	pub_exp = find_attr(subkey, TEE_ATTR_RSA_PUBLIC_EXPONENT);
126c34d0d91SJens Wiklander 	if (!pub_exp)
127c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
128c34d0d91SJens Wiklander 	modulus = find_attr(subkey, TEE_ATTR_RSA_MODULUS);
129c34d0d91SJens Wiklander 	if (!modulus)
130c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
131c34d0d91SJens Wiklander 
132c34d0d91SJens Wiklander 	key = calloc(1, sizeof(*key));
133c34d0d91SJens Wiklander 	if (!key)
134c34d0d91SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
135c34d0d91SJens Wiklander 	res = crypto_acipher_alloc_rsa_public_key(key, modulus->size * 8);
136c34d0d91SJens Wiklander 	if (res)
137c34d0d91SJens Wiklander 		goto err_key;
138c34d0d91SJens Wiklander 
139c34d0d91SJens Wiklander 	res = crypto_bignum_bin2bn(base + pub_exp->offs, pub_exp->size, key->e);
140c34d0d91SJens Wiklander 	if (res)
141c34d0d91SJens Wiklander 		goto err;
142c34d0d91SJens Wiklander 	res = crypto_bignum_bin2bn(base + modulus->offs, modulus->size, key->n);
143c34d0d91SJens Wiklander 	if (res)
144c34d0d91SJens Wiklander 		goto err;
145c34d0d91SJens Wiklander 
146c34d0d91SJens Wiklander 	*key_pp = key;
147c34d0d91SJens Wiklander 	return TEE_SUCCESS;
148c34d0d91SJens Wiklander err:
149c34d0d91SJens Wiklander 	crypto_acipher_free_rsa_public_key(key);
150c34d0d91SJens Wiklander err_key:
151c34d0d91SJens Wiklander 	free(key);
152c34d0d91SJens Wiklander 	return TEE_ERROR_SECURITY;
153c34d0d91SJens Wiklander }
154c34d0d91SJens Wiklander 
155c34d0d91SJens Wiklander static TEE_Result check_attrs(const struct shdr_subkey *subkey, size_t img_size)
156c34d0d91SJens Wiklander {
157c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *attrs = subkey->attrs;
158c34d0d91SJens Wiklander 	size_t end = 0;
159c34d0d91SJens Wiklander 	size_t n = 0;
160c34d0d91SJens Wiklander 
161c34d0d91SJens Wiklander 	if (MUL_OVERFLOW(subkey->attr_count, sizeof(*attrs), &end) ||
162c34d0d91SJens Wiklander 	    ADD_OVERFLOW(end, sizeof(*subkey), &end) ||
163c34d0d91SJens Wiklander 	    end > img_size)
164c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
165c34d0d91SJens Wiklander 
166c34d0d91SJens Wiklander 	for (n = 0; n < subkey->attr_count; n++)
167c34d0d91SJens Wiklander 		if (ADD_OVERFLOW(attrs[n].offs, attrs[n].size, &end) ||
168c34d0d91SJens Wiklander 		    end > img_size)
169c34d0d91SJens Wiklander 			return TEE_ERROR_SECURITY;
170c34d0d91SJens Wiklander 
171c34d0d91SJens Wiklander 	return TEE_SUCCESS;
172c34d0d91SJens Wiklander }
173c34d0d91SJens Wiklander 
174c34d0d91SJens Wiklander static TEE_Result calc_next_uuid(uint8_t uuid[sizeof(TEE_UUID)],
175c34d0d91SJens Wiklander 				 const uint8_t my_uuid[sizeof(TEE_UUID)],
176c34d0d91SJens Wiklander 				 const void *ns_name, size_t name_size)
177c34d0d91SJens Wiklander {
178c34d0d91SJens Wiklander 	TEE_Result res = TEE_ERROR_SECURITY;
179c34d0d91SJens Wiklander 	void *ctx = NULL;
180c34d0d91SJens Wiklander 	struct {
181c34d0d91SJens Wiklander 		uint8_t digest[TEE_SHA1_HASH_SIZE];
182c34d0d91SJens Wiklander 		TEE_UUID uuid;
183c34d0d91SJens Wiklander 		char name_str[];
184c34d0d91SJens Wiklander 	} *tmp = NULL;
185c34d0d91SJens Wiklander 
186c34d0d91SJens Wiklander 	if (!name_size) {
187c34d0d91SJens Wiklander 		memcpy(uuid, my_uuid, sizeof(TEE_UUID));
188c34d0d91SJens Wiklander 		return TEE_SUCCESS;
189c34d0d91SJens Wiklander 	}
190c34d0d91SJens Wiklander 
191c34d0d91SJens Wiklander 	/*
192c34d0d91SJens Wiklander 	 * RFC 4122 requires a SHA-1 digest for UUID v5. Use SHA-512
193c34d0d91SJens Wiklander 	 * instead for better collision resistance.
194c34d0d91SJens Wiklander 	 */
195c34d0d91SJens Wiklander 	if (crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA512))
196c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
197c34d0d91SJens Wiklander 
198c34d0d91SJens Wiklander 	tmp = mempool_alloc(mempool_default, sizeof(*tmp) + name_size);
199c34d0d91SJens Wiklander 	if (!tmp)
200c34d0d91SJens Wiklander 		goto out_ctx;
201c34d0d91SJens Wiklander 	memcpy(tmp->name_str, ns_name, name_size);
202c34d0d91SJens Wiklander 
203c34d0d91SJens Wiklander 	if (crypto_hash_init(ctx) ||
204c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, my_uuid, sizeof(TEE_UUID)) ||
205c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)tmp->name_str,
206c34d0d91SJens Wiklander 			       strnlen(tmp->name_str, name_size)) ||
207c34d0d91SJens Wiklander 	    crypto_hash_final(ctx, tmp->digest, sizeof(tmp->digest)))
208c34d0d91SJens Wiklander 		goto out_mempool;
209c34d0d91SJens Wiklander 
210c34d0d91SJens Wiklander 	tee_uuid_from_octets(&tmp->uuid, tmp->digest);
211c34d0d91SJens Wiklander 	/*
212c34d0d91SJens Wiklander 	 * Set the four most significant bits (bits 12 through 15) of the
213c34d0d91SJens Wiklander 	 * time_hi_and_version field to 5.
214c34d0d91SJens Wiklander 	 */
215c34d0d91SJens Wiklander 	tmp->uuid.timeHiAndVersion &= ~SHIFT_U32(0xf, 12);
216c34d0d91SJens Wiklander 	tmp->uuid.timeHiAndVersion |= SHIFT_U32(5, 12);
217c34d0d91SJens Wiklander 	/*
218c34d0d91SJens Wiklander 	 * Set the two most significant bits (bits 6 and 7) of the
219c34d0d91SJens Wiklander 	 * clock_seq_hi_and_reserved to zero and one, respectively.
220c34d0d91SJens Wiklander 	 */
221c34d0d91SJens Wiklander 	tmp->uuid.clockSeqAndNode[0] &= ~BIT(6);
222c34d0d91SJens Wiklander 	tmp->uuid.clockSeqAndNode[0] |= BIT(7);
223c34d0d91SJens Wiklander 
224c34d0d91SJens Wiklander 	tee_uuid_to_octets(uuid, &tmp->uuid);
225c34d0d91SJens Wiklander 	res = TEE_SUCCESS;
226c34d0d91SJens Wiklander 
227c34d0d91SJens Wiklander out_mempool:
228c34d0d91SJens Wiklander 	mempool_free(mempool_default, tmp);
229c34d0d91SJens Wiklander out_ctx:
230c34d0d91SJens Wiklander 	crypto_hash_free_ctx(ctx);
231c34d0d91SJens Wiklander 
232c34d0d91SJens Wiklander 	return res;
233c34d0d91SJens Wiklander }
234c34d0d91SJens Wiklander 
235c34d0d91SJens Wiklander TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs,
236c34d0d91SJens Wiklander 			     const uint8_t *ns_img, size_t ns_img_size,
237c34d0d91SJens Wiklander 			     const uint8_t next_uuid[sizeof(TEE_UUID)],
238c34d0d91SJens Wiklander 			     uint32_t max_depth, struct shdr_pub_key *key)
239c34d0d91SJens Wiklander {
240c34d0d91SJens Wiklander 	struct shdr_subkey *subkey = NULL;
241c34d0d91SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
242c34d0d91SJens Wiklander 	void *digest = NULL;
243c34d0d91SJens Wiklander 	uint8_t *img = NULL;
244c34d0d91SJens Wiklander 	void *ctx = NULL;
245c34d0d91SJens Wiklander 	size_t end = 0;
246c34d0d91SJens Wiklander 
247c34d0d91SJens Wiklander 	if (shdr->img_type != SHDR_SUBKEY)
248c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
249c34d0d91SJens Wiklander 
250c34d0d91SJens Wiklander 	if (shdr->img_size < sizeof(*subkey))
251c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
252c34d0d91SJens Wiklander 
253c34d0d91SJens Wiklander 	if (ADD_OVERFLOW(shdr->img_size, offs, &end) || end > ns_img_size)
254c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
255c34d0d91SJens Wiklander 
256c34d0d91SJens Wiklander 	img = mempool_alloc(mempool_default, shdr->img_size + shdr->hash_size);
257c34d0d91SJens Wiklander 	if (!img)
258c34d0d91SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
259c34d0d91SJens Wiklander 	memcpy(img + shdr->hash_size, ns_img + offs, shdr->img_size);
260c34d0d91SJens Wiklander 	subkey = (void *)(img + shdr->hash_size);
261c34d0d91SJens Wiklander 	digest = img;
262c34d0d91SJens Wiklander 
263c34d0d91SJens Wiklander 	if (crypto_hash_alloc_ctx(&ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo))) {
264c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
265c34d0d91SJens Wiklander 		goto out_mempool;
266c34d0d91SJens Wiklander 	}
267c34d0d91SJens Wiklander 
268c34d0d91SJens Wiklander 	if (crypto_hash_init(ctx) ||
269c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)shdr, sizeof(*shdr)) ||
270c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)subkey, shdr->img_size) ||
271c34d0d91SJens Wiklander 	    crypto_hash_final(ctx, digest, shdr->hash_size) ||
272c34d0d91SJens Wiklander 	    memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size)) {
273c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
274c34d0d91SJens Wiklander 		goto out_ctx;
275c34d0d91SJens Wiklander 	}
276c34d0d91SJens Wiklander 
277c34d0d91SJens Wiklander 	res = check_attrs(subkey, shdr->img_size);
278c34d0d91SJens Wiklander 	if (res)
279c34d0d91SJens Wiklander 		goto out_ctx;
280c34d0d91SJens Wiklander 
281c34d0d91SJens Wiklander 	if (subkey->max_depth >= max_depth) {
282c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
283c34d0d91SJens Wiklander 		goto out_ctx;
284c34d0d91SJens Wiklander 	}
285c34d0d91SJens Wiklander 	if (next_uuid && memcmp(next_uuid, subkey->uuid, sizeof(TEE_UUID))) {
286c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
287c34d0d91SJens Wiklander 		goto out_ctx;
288c34d0d91SJens Wiklander 	}
289c34d0d91SJens Wiklander 
290c34d0d91SJens Wiklander 	key->max_depth = subkey->max_depth;
291c34d0d91SJens Wiklander 	key->name_size = subkey->name_size;
292c34d0d91SJens Wiklander 	memcpy(key->uuid, subkey->uuid, sizeof(TEE_UUID));
293c34d0d91SJens Wiklander 	if (ADD_OVERFLOW(key->name_size, offs + shdr->img_size, &end) ||
294c34d0d91SJens Wiklander 	    end > ns_img_size) {
295c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
296c34d0d91SJens Wiklander 		goto out_ctx;
297c34d0d91SJens Wiklander 	}
298c34d0d91SJens Wiklander 	res = calc_next_uuid(key->next_uuid, key->uuid,
299c34d0d91SJens Wiklander 			     ns_img + offs + shdr->img_size, key->name_size);
300c34d0d91SJens Wiklander 	if (res)
301c34d0d91SJens Wiklander 		goto out_ctx;
302c34d0d91SJens Wiklander 
303c34d0d91SJens Wiklander 	key->main_algo = TEE_ALG_GET_MAIN_ALG(subkey->algo);
304c34d0d91SJens Wiklander 	switch (key->main_algo) {
305c34d0d91SJens Wiklander 	case TEE_MAIN_ALGO_RSA:
306c34d0d91SJens Wiklander 		res = load_rsa_key(subkey, &key->pub_key.rsa);
307c34d0d91SJens Wiklander 		break;
308c34d0d91SJens Wiklander 	default:
309c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
310c34d0d91SJens Wiklander 		break;
311c34d0d91SJens Wiklander 	}
312c34d0d91SJens Wiklander 
313c34d0d91SJens Wiklander out_ctx:
314c34d0d91SJens Wiklander 	crypto_hash_free_ctx(ctx);
315c34d0d91SJens Wiklander out_mempool:
316c34d0d91SJens Wiklander 	mempool_free(mempool_default, img);
317c34d0d91SJens Wiklander 	return res;
318c34d0d91SJens Wiklander }
319c34d0d91SJens Wiklander 
320c34d0d91SJens Wiklander void shdr_free_pub_key(struct shdr_pub_key *key)
321c34d0d91SJens Wiklander {
322c34d0d91SJens Wiklander 	if (key) {
323c34d0d91SJens Wiklander 		switch (key->main_algo) {
324c34d0d91SJens Wiklander 		case TEE_MAIN_ALGO_RSA:
325c34d0d91SJens Wiklander 			crypto_acipher_free_rsa_public_key(key->pub_key.rsa);
326c34d0d91SJens Wiklander 			free(key->pub_key.rsa);
327c34d0d91SJens Wiklander 			break;
328c34d0d91SJens Wiklander 		default:
329c34d0d91SJens Wiklander 			panic();
330c34d0d91SJens Wiklander 		}
331c34d0d91SJens Wiklander 	}
332c34d0d91SJens Wiklander }
333c34d0d91SJens Wiklander 
334c34d0d91SJens Wiklander TEE_Result shdr_verify_signature2(struct shdr_pub_key *key,
335c34d0d91SJens Wiklander 				  const struct shdr *shdr)
336c34d0d91SJens Wiklander {
337c34d0d91SJens Wiklander 	size_t hash_size = 0;
338*bef7d11dSJens Wiklander 	size_t hash_algo = 0;
339c34d0d91SJens Wiklander 
340c34d0d91SJens Wiklander 	if (shdr->magic != SHDR_MAGIC)
341c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
342c34d0d91SJens Wiklander 
343c34d0d91SJens Wiklander 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo)
344c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
345c34d0d91SJens Wiklander 
346*bef7d11dSJens Wiklander 	hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
347*bef7d11dSJens Wiklander 	if (is_weak_hash_algo(hash_algo))
348*bef7d11dSJens Wiklander 		return TEE_ERROR_SECURITY;
349*bef7d11dSJens Wiklander 
350*bef7d11dSJens Wiklander 	if (tee_alg_get_digest_size(hash_algo, &hash_size) ||
351c34d0d91SJens Wiklander 	    hash_size != shdr->hash_size)
352c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
353c34d0d91SJens Wiklander 
354c34d0d91SJens Wiklander 	switch (key->main_algo) {
355c34d0d91SJens Wiklander 	case TEE_MAIN_ALGO_RSA:
356c34d0d91SJens Wiklander 		if (crypto_acipher_rsassa_verify(shdr->algo, key->pub_key.rsa,
357c34d0d91SJens Wiklander 						 shdr->hash_size,
358c34d0d91SJens Wiklander 						 SHDR_GET_HASH(shdr),
359c34d0d91SJens Wiklander 						 shdr->hash_size,
360c34d0d91SJens Wiklander 						 SHDR_GET_SIG(shdr),
361c34d0d91SJens Wiklander 						 shdr->sig_size))
362c34d0d91SJens Wiklander 			return TEE_ERROR_SECURITY;
363c34d0d91SJens Wiklander 		break;
364c34d0d91SJens Wiklander 	default:
365c34d0d91SJens Wiklander 		panic();
366c34d0d91SJens Wiklander 	}
367c34d0d91SJens Wiklander 
368c34d0d91SJens Wiklander 	return TEE_SUCCESS;
369c34d0d91SJens Wiklander }
370