xref: /optee_os/core/crypto/signed_hdr.c (revision c5a0587f480d0eaa2d0fe1dde74d888a76f0da22)
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>
78a697013SJens Wiklander #include <fault_mitigation.h>
8c34d0d91SJens Wiklander #include <kernel/panic.h>
9c34d0d91SJens Wiklander #include <mempool.h>
10064663e8SJens Wiklander #include <signed_hdr.h>
11064663e8SJens Wiklander #include <stdlib.h>
12064663e8SJens Wiklander #include <string.h>
13064663e8SJens Wiklander #include <ta_pub_key.h>
14064663e8SJens Wiklander #include <tee_api_types.h>
15064663e8SJens Wiklander #include <tee/tee_cryp_utl.h>
16c34d0d91SJens Wiklander #include <tee/uuid.h>
17064663e8SJens Wiklander #include <utee_defines.h>
18062765e4SJerome Forissier #include <util.h>
19064663e8SJens Wiklander 
20ec1aa4faSJens Wiklander struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size)
21064663e8SJens Wiklander {
22064663e8SJens Wiklander 	size_t shdr_size;
23064663e8SJens Wiklander 	struct shdr *shdr;
24062765e4SJerome Forissier 	vaddr_t img_va = (vaddr_t)img;
25062765e4SJerome Forissier 	vaddr_t tmp = 0;
26ec1aa4faSJens Wiklander 	size_t end = 0;
27064663e8SJens Wiklander 
28ec1aa4faSJens Wiklander 	if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size)
294ca9e426SJoakim Bech 		return NULL;
304ca9e426SJoakim Bech 
31ec1aa4faSJens Wiklander 	shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs));
326b5d1120SJens Wiklander 	if (!shdr_size || ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size)
334ca9e426SJoakim Bech 		return NULL;
34064663e8SJens Wiklander 
35062765e4SJerome Forissier 	if (ADD_OVERFLOW(img_va, shdr_size, &tmp))
36062765e4SJerome Forissier 		return NULL;
37062765e4SJerome Forissier 
38064663e8SJens Wiklander 	shdr = malloc(shdr_size);
39064663e8SJens Wiklander 	if (!shdr)
40064663e8SJens Wiklander 		return NULL;
41ec1aa4faSJens Wiklander 	memcpy(shdr, (const uint8_t *)img + offs, shdr_size);
42064663e8SJens Wiklander 
43064663e8SJens Wiklander 	/* Check that the data wasn't modified before the copy was completed */
44064663e8SJens Wiklander 	if (shdr_size != SHDR_GET_SIZE(shdr)) {
45064663e8SJens Wiklander 		free(shdr);
46064663e8SJens Wiklander 		return NULL;
47064663e8SJens Wiklander 	}
48064663e8SJens Wiklander 
49064663e8SJens Wiklander 	return shdr;
50064663e8SJens Wiklander }
51064663e8SJens Wiklander 
52bef7d11dSJens Wiklander static bool is_weak_hash_algo(uint32_t algo)
53bef7d11dSJens Wiklander {
54bef7d11dSJens Wiklander 	return algo == TEE_ALG_MD5 || algo == TEE_ALG_SHA1 ||
55*c5a0587fSJoakim Bech 	       algo == TEE_ALG_MD5SHA1 || algo == TEE_ALG_SHA224;
56bef7d11dSJens Wiklander }
57bef7d11dSJens Wiklander 
58064663e8SJens Wiklander TEE_Result shdr_verify_signature(const struct shdr *shdr)
59064663e8SJens Wiklander {
60bef7d11dSJens Wiklander 	struct rsa_public_key key = { };
61bef7d11dSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
62064663e8SJens Wiklander 	uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
638a697013SJens Wiklander 	struct ftmn ftmn = { };
648a697013SJens Wiklander 	unsigned int err_incr = 2;
65bef7d11dSJens Wiklander 	size_t hash_size = 0;
66bef7d11dSJens Wiklander 	size_t hash_algo = 0;
67064663e8SJens Wiklander 
68064663e8SJens Wiklander 	if (shdr->magic != SHDR_MAGIC)
698a697013SJens Wiklander 		goto err;
70064663e8SJens Wiklander 
71064663e8SJens Wiklander 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
728a697013SJens Wiklander 		goto err;
73064663e8SJens Wiklander 
74bef7d11dSJens Wiklander 	hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
75bef7d11dSJens Wiklander 	if (is_weak_hash_algo(hash_algo))
768a697013SJens Wiklander 		goto err;
77bef7d11dSJens Wiklander 
78bef7d11dSJens Wiklander 	res = tee_alg_get_digest_size(hash_algo, &hash_size);
79064663e8SJens Wiklander 	if (res)
808a697013SJens Wiklander 		goto err;
81064663e8SJens Wiklander 	if (hash_size != shdr->hash_size)
828a697013SJens Wiklander 		goto err;
83064663e8SJens Wiklander 
8444c8e3cbSCedric Neveux 	res = crypto_acipher_alloc_rsa_public_key(&key,
8544c8e3cbSCedric Neveux 						  ta_pub_key_modulus_size * 8);
86064663e8SJens Wiklander 	if (res)
878a697013SJens Wiklander 		goto err;
88064663e8SJens Wiklander 
89064663e8SJens Wiklander 	res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
90064663e8SJens Wiklander 	if (res)
918a697013SJens Wiklander 		goto err;
92064663e8SJens Wiklander 	res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
93064663e8SJens Wiklander 				   key.n);
94064663e8SJens Wiklander 	if (res)
958a697013SJens Wiklander 		goto err;
96064663e8SJens Wiklander 
978a697013SJens Wiklander 	FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0,
988a697013SJens Wiklander 		       crypto_acipher_rsassa_verify, shdr->algo, &key,
998a697013SJens Wiklander 		       shdr->hash_size, SHDR_GET_HASH(shdr), shdr->hash_size,
100064663e8SJens Wiklander 		       SHDR_GET_SIG(shdr), shdr->sig_size);
1018a697013SJens Wiklander 	if (!res) {
1028a697013SJens Wiklander 		ftmn_checkpoint(&ftmn, FTMN_INCR0);
1038a697013SJens Wiklander 		goto out;
1048a697013SJens Wiklander 	}
1058a697013SJens Wiklander 	err_incr = 1;
1068a697013SJens Wiklander err:
1078a697013SJens Wiklander 	res = TEE_ERROR_SECURITY;
1088a697013SJens Wiklander 	FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res);
109064663e8SJens Wiklander out:
1108a697013SJens Wiklander 	FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res);
111064663e8SJens Wiklander 	crypto_acipher_free_rsa_public_key(&key);
1128a697013SJens Wiklander 	return res;
113064663e8SJens Wiklander }
114c34d0d91SJens Wiklander 
115c34d0d91SJens Wiklander static const struct shdr_subkey_attr *
116c34d0d91SJens Wiklander find_attr(const struct shdr_subkey *subkey, uint32_t id)
117c34d0d91SJens Wiklander {
118c34d0d91SJens Wiklander 	size_t n = 0;
119c34d0d91SJens Wiklander 
120c34d0d91SJens Wiklander 	for (n = 0; n < subkey->attr_count; n++)
121c34d0d91SJens Wiklander 		if (subkey->attrs[n].id == id)
122c34d0d91SJens Wiklander 			return subkey->attrs + n;
123c34d0d91SJens Wiklander 
124c34d0d91SJens Wiklander 	return NULL;
125c34d0d91SJens Wiklander }
126c34d0d91SJens Wiklander 
127c34d0d91SJens Wiklander static TEE_Result load_rsa_key(const struct shdr_subkey *subkey,
128c34d0d91SJens Wiklander 			       struct rsa_public_key **key_pp)
129c34d0d91SJens Wiklander {
130c34d0d91SJens Wiklander 	const uint8_t *base = (const uint8_t *)subkey;
131c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *pub_exp = NULL;
132c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *modulus = NULL;
133c34d0d91SJens Wiklander 	struct rsa_public_key *key = NULL;
134c34d0d91SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
135c34d0d91SJens Wiklander 
136c34d0d91SJens Wiklander 	pub_exp = find_attr(subkey, TEE_ATTR_RSA_PUBLIC_EXPONENT);
137c34d0d91SJens Wiklander 	if (!pub_exp)
138c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
139c34d0d91SJens Wiklander 	modulus = find_attr(subkey, TEE_ATTR_RSA_MODULUS);
140c34d0d91SJens Wiklander 	if (!modulus)
141c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
142c34d0d91SJens Wiklander 
143c34d0d91SJens Wiklander 	key = calloc(1, sizeof(*key));
144c34d0d91SJens Wiklander 	if (!key)
145c34d0d91SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
146c34d0d91SJens Wiklander 	res = crypto_acipher_alloc_rsa_public_key(key, modulus->size * 8);
147c34d0d91SJens Wiklander 	if (res)
148c34d0d91SJens Wiklander 		goto err_key;
149c34d0d91SJens Wiklander 
150c34d0d91SJens Wiklander 	res = crypto_bignum_bin2bn(base + pub_exp->offs, pub_exp->size, key->e);
151c34d0d91SJens Wiklander 	if (res)
152c34d0d91SJens Wiklander 		goto err;
153c34d0d91SJens Wiklander 	res = crypto_bignum_bin2bn(base + modulus->offs, modulus->size, key->n);
154c34d0d91SJens Wiklander 	if (res)
155c34d0d91SJens Wiklander 		goto err;
156c34d0d91SJens Wiklander 
157c34d0d91SJens Wiklander 	*key_pp = key;
158c34d0d91SJens Wiklander 	return TEE_SUCCESS;
159c34d0d91SJens Wiklander err:
160c34d0d91SJens Wiklander 	crypto_acipher_free_rsa_public_key(key);
161c34d0d91SJens Wiklander err_key:
162c34d0d91SJens Wiklander 	free(key);
163c34d0d91SJens Wiklander 	return TEE_ERROR_SECURITY;
164c34d0d91SJens Wiklander }
165c34d0d91SJens Wiklander 
166c34d0d91SJens Wiklander static TEE_Result check_attrs(const struct shdr_subkey *subkey, size_t img_size)
167c34d0d91SJens Wiklander {
168c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *attrs = subkey->attrs;
169c34d0d91SJens Wiklander 	size_t end = 0;
170c34d0d91SJens Wiklander 	size_t n = 0;
171c34d0d91SJens Wiklander 
172c34d0d91SJens Wiklander 	if (MUL_OVERFLOW(subkey->attr_count, sizeof(*attrs), &end) ||
173c34d0d91SJens Wiklander 	    ADD_OVERFLOW(end, sizeof(*subkey), &end) ||
174c34d0d91SJens Wiklander 	    end > img_size)
175c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
176c34d0d91SJens Wiklander 
177c34d0d91SJens Wiklander 	for (n = 0; n < subkey->attr_count; n++)
178c34d0d91SJens Wiklander 		if (ADD_OVERFLOW(attrs[n].offs, attrs[n].size, &end) ||
179c34d0d91SJens Wiklander 		    end > img_size)
180c34d0d91SJens Wiklander 			return TEE_ERROR_SECURITY;
181c34d0d91SJens Wiklander 
182c34d0d91SJens Wiklander 	return TEE_SUCCESS;
183c34d0d91SJens Wiklander }
184c34d0d91SJens Wiklander 
185c34d0d91SJens Wiklander static TEE_Result calc_next_uuid(uint8_t uuid[sizeof(TEE_UUID)],
186c34d0d91SJens Wiklander 				 const uint8_t my_uuid[sizeof(TEE_UUID)],
187c34d0d91SJens Wiklander 				 const void *ns_name, size_t name_size)
188c34d0d91SJens Wiklander {
189c34d0d91SJens Wiklander 	TEE_Result res = TEE_ERROR_SECURITY;
190c34d0d91SJens Wiklander 	void *ctx = NULL;
191c34d0d91SJens Wiklander 	struct {
192c34d0d91SJens Wiklander 		uint8_t digest[TEE_SHA1_HASH_SIZE];
193c34d0d91SJens Wiklander 		TEE_UUID uuid;
194c34d0d91SJens Wiklander 		char name_str[];
195c34d0d91SJens Wiklander 	} *tmp = NULL;
196c34d0d91SJens Wiklander 
197c34d0d91SJens Wiklander 	if (!name_size) {
198c34d0d91SJens Wiklander 		memcpy(uuid, my_uuid, sizeof(TEE_UUID));
199c34d0d91SJens Wiklander 		return TEE_SUCCESS;
200c34d0d91SJens Wiklander 	}
201c34d0d91SJens Wiklander 
202c34d0d91SJens Wiklander 	/*
203c34d0d91SJens Wiklander 	 * RFC 4122 requires a SHA-1 digest for UUID v5. Use SHA-512
204c34d0d91SJens Wiklander 	 * instead for better collision resistance.
205c34d0d91SJens Wiklander 	 */
206c34d0d91SJens Wiklander 	if (crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA512))
207c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
208c34d0d91SJens Wiklander 
209c34d0d91SJens Wiklander 	tmp = mempool_alloc(mempool_default, sizeof(*tmp) + name_size);
210c34d0d91SJens Wiklander 	if (!tmp)
211c34d0d91SJens Wiklander 		goto out_ctx;
212c34d0d91SJens Wiklander 	memcpy(tmp->name_str, ns_name, name_size);
213c34d0d91SJens Wiklander 
214c34d0d91SJens Wiklander 	if (crypto_hash_init(ctx) ||
215c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, my_uuid, sizeof(TEE_UUID)) ||
216c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)tmp->name_str,
217c34d0d91SJens Wiklander 			       strnlen(tmp->name_str, name_size)) ||
218c34d0d91SJens Wiklander 	    crypto_hash_final(ctx, tmp->digest, sizeof(tmp->digest)))
219c34d0d91SJens Wiklander 		goto out_mempool;
220c34d0d91SJens Wiklander 
221c34d0d91SJens Wiklander 	tee_uuid_from_octets(&tmp->uuid, tmp->digest);
222c34d0d91SJens Wiklander 	/*
223c34d0d91SJens Wiklander 	 * Set the four most significant bits (bits 12 through 15) of the
224c34d0d91SJens Wiklander 	 * time_hi_and_version field to 5.
225c34d0d91SJens Wiklander 	 */
226c34d0d91SJens Wiklander 	tmp->uuid.timeHiAndVersion &= ~SHIFT_U32(0xf, 12);
227c34d0d91SJens Wiklander 	tmp->uuid.timeHiAndVersion |= SHIFT_U32(5, 12);
228c34d0d91SJens Wiklander 	/*
229c34d0d91SJens Wiklander 	 * Set the two most significant bits (bits 6 and 7) of the
230c34d0d91SJens Wiklander 	 * clock_seq_hi_and_reserved to zero and one, respectively.
231c34d0d91SJens Wiklander 	 */
232c34d0d91SJens Wiklander 	tmp->uuid.clockSeqAndNode[0] &= ~BIT(6);
233c34d0d91SJens Wiklander 	tmp->uuid.clockSeqAndNode[0] |= BIT(7);
234c34d0d91SJens Wiklander 
235c34d0d91SJens Wiklander 	tee_uuid_to_octets(uuid, &tmp->uuid);
236c34d0d91SJens Wiklander 	res = TEE_SUCCESS;
237c34d0d91SJens Wiklander 
238c34d0d91SJens Wiklander out_mempool:
239c34d0d91SJens Wiklander 	mempool_free(mempool_default, tmp);
240c34d0d91SJens Wiklander out_ctx:
241c34d0d91SJens Wiklander 	crypto_hash_free_ctx(ctx);
242c34d0d91SJens Wiklander 
243c34d0d91SJens Wiklander 	return res;
244c34d0d91SJens Wiklander }
245c34d0d91SJens Wiklander 
246c34d0d91SJens Wiklander TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs,
247c34d0d91SJens Wiklander 			     const uint8_t *ns_img, size_t ns_img_size,
248c34d0d91SJens Wiklander 			     const uint8_t next_uuid[sizeof(TEE_UUID)],
249c34d0d91SJens Wiklander 			     uint32_t max_depth, struct shdr_pub_key *key)
250c34d0d91SJens Wiklander {
251c34d0d91SJens Wiklander 	struct shdr_subkey *subkey = NULL;
252c34d0d91SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
253c34d0d91SJens Wiklander 	void *digest = NULL;
254c34d0d91SJens Wiklander 	uint8_t *img = NULL;
255c34d0d91SJens Wiklander 	void *ctx = NULL;
256c34d0d91SJens Wiklander 	size_t end = 0;
257c34d0d91SJens Wiklander 
258c34d0d91SJens Wiklander 	if (shdr->img_type != SHDR_SUBKEY)
259c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
260c34d0d91SJens Wiklander 
261c34d0d91SJens Wiklander 	if (shdr->img_size < sizeof(*subkey))
262c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
263c34d0d91SJens Wiklander 
264c34d0d91SJens Wiklander 	if (ADD_OVERFLOW(shdr->img_size, offs, &end) || end > ns_img_size)
265c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
266c34d0d91SJens Wiklander 
267c34d0d91SJens Wiklander 	img = mempool_alloc(mempool_default, shdr->img_size + shdr->hash_size);
268c34d0d91SJens Wiklander 	if (!img)
269c34d0d91SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
270c34d0d91SJens Wiklander 	memcpy(img + shdr->hash_size, ns_img + offs, shdr->img_size);
271c34d0d91SJens Wiklander 	subkey = (void *)(img + shdr->hash_size);
272c34d0d91SJens Wiklander 	digest = img;
273c34d0d91SJens Wiklander 
274c34d0d91SJens Wiklander 	if (crypto_hash_alloc_ctx(&ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo))) {
275c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
276c34d0d91SJens Wiklander 		goto out_mempool;
277c34d0d91SJens Wiklander 	}
278c34d0d91SJens Wiklander 
279c34d0d91SJens Wiklander 	if (crypto_hash_init(ctx) ||
280c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)shdr, sizeof(*shdr)) ||
281c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)subkey, shdr->img_size) ||
282c34d0d91SJens Wiklander 	    crypto_hash_final(ctx, digest, shdr->hash_size) ||
283c34d0d91SJens Wiklander 	    memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size)) {
284c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
285c34d0d91SJens Wiklander 		goto out_ctx;
286c34d0d91SJens Wiklander 	}
287c34d0d91SJens Wiklander 
288c34d0d91SJens Wiklander 	res = check_attrs(subkey, shdr->img_size);
289c34d0d91SJens Wiklander 	if (res)
290c34d0d91SJens Wiklander 		goto out_ctx;
291c34d0d91SJens Wiklander 
292c34d0d91SJens Wiklander 	if (subkey->max_depth >= max_depth) {
293c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
294c34d0d91SJens Wiklander 		goto out_ctx;
295c34d0d91SJens Wiklander 	}
296c34d0d91SJens Wiklander 	if (next_uuid && memcmp(next_uuid, subkey->uuid, sizeof(TEE_UUID))) {
297c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
298c34d0d91SJens Wiklander 		goto out_ctx;
299c34d0d91SJens Wiklander 	}
300c34d0d91SJens Wiklander 
301c34d0d91SJens Wiklander 	key->max_depth = subkey->max_depth;
302c34d0d91SJens Wiklander 	key->name_size = subkey->name_size;
303c34d0d91SJens Wiklander 	memcpy(key->uuid, subkey->uuid, sizeof(TEE_UUID));
304c34d0d91SJens Wiklander 	if (ADD_OVERFLOW(key->name_size, offs + shdr->img_size, &end) ||
305c34d0d91SJens Wiklander 	    end > ns_img_size) {
306c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
307c34d0d91SJens Wiklander 		goto out_ctx;
308c34d0d91SJens Wiklander 	}
309c34d0d91SJens Wiklander 	res = calc_next_uuid(key->next_uuid, key->uuid,
310c34d0d91SJens Wiklander 			     ns_img + offs + shdr->img_size, key->name_size);
311c34d0d91SJens Wiklander 	if (res)
312c34d0d91SJens Wiklander 		goto out_ctx;
313c34d0d91SJens Wiklander 
314c34d0d91SJens Wiklander 	key->main_algo = TEE_ALG_GET_MAIN_ALG(subkey->algo);
315c34d0d91SJens Wiklander 	switch (key->main_algo) {
316c34d0d91SJens Wiklander 	case TEE_MAIN_ALGO_RSA:
317c34d0d91SJens Wiklander 		res = load_rsa_key(subkey, &key->pub_key.rsa);
318c34d0d91SJens Wiklander 		break;
319c34d0d91SJens Wiklander 	default:
320c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
321c34d0d91SJens Wiklander 		break;
322c34d0d91SJens Wiklander 	}
323c34d0d91SJens Wiklander 
324c34d0d91SJens Wiklander out_ctx:
325c34d0d91SJens Wiklander 	crypto_hash_free_ctx(ctx);
326c34d0d91SJens Wiklander out_mempool:
327c34d0d91SJens Wiklander 	mempool_free(mempool_default, img);
328c34d0d91SJens Wiklander 	return res;
329c34d0d91SJens Wiklander }
330c34d0d91SJens Wiklander 
331c34d0d91SJens Wiklander void shdr_free_pub_key(struct shdr_pub_key *key)
332c34d0d91SJens Wiklander {
333c34d0d91SJens Wiklander 	if (key) {
334c34d0d91SJens Wiklander 		switch (key->main_algo) {
335c34d0d91SJens Wiklander 		case TEE_MAIN_ALGO_RSA:
336c34d0d91SJens Wiklander 			crypto_acipher_free_rsa_public_key(key->pub_key.rsa);
337c34d0d91SJens Wiklander 			free(key->pub_key.rsa);
338c34d0d91SJens Wiklander 			break;
339c34d0d91SJens Wiklander 		default:
340c34d0d91SJens Wiklander 			panic();
341c34d0d91SJens Wiklander 		}
342c34d0d91SJens Wiklander 	}
343c34d0d91SJens Wiklander }
344c34d0d91SJens Wiklander 
345c34d0d91SJens Wiklander TEE_Result shdr_verify_signature2(struct shdr_pub_key *key,
346c34d0d91SJens Wiklander 				  const struct shdr *shdr)
347c34d0d91SJens Wiklander {
3488a697013SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
3498a697013SJens Wiklander 	unsigned int err_incr = 2;
3508a697013SJens Wiklander 	struct ftmn ftmn = { };
351c34d0d91SJens Wiklander 	size_t hash_size = 0;
352bef7d11dSJens Wiklander 	size_t hash_algo = 0;
353c34d0d91SJens Wiklander 
354c34d0d91SJens Wiklander 	if (shdr->magic != SHDR_MAGIC)
3558a697013SJens Wiklander 		goto err;
356c34d0d91SJens Wiklander 
357c34d0d91SJens Wiklander 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo)
3588a697013SJens Wiklander 		goto err;
359c34d0d91SJens Wiklander 
360bef7d11dSJens Wiklander 	hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
361bef7d11dSJens Wiklander 	if (is_weak_hash_algo(hash_algo))
3628a697013SJens Wiklander 		goto err;
363bef7d11dSJens Wiklander 
364bef7d11dSJens Wiklander 	if (tee_alg_get_digest_size(hash_algo, &hash_size) ||
365c34d0d91SJens Wiklander 	    hash_size != shdr->hash_size)
3668a697013SJens Wiklander 		goto err;
367c34d0d91SJens Wiklander 
368c34d0d91SJens Wiklander 	switch (key->main_algo) {
369c34d0d91SJens Wiklander 	case TEE_MAIN_ALGO_RSA:
3708a697013SJens Wiklander 		FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0,
3718a697013SJens Wiklander 			       crypto_acipher_rsassa_verify, shdr->algo,
3728a697013SJens Wiklander 			       key->pub_key.rsa, shdr->hash_size,
3738a697013SJens Wiklander 			       SHDR_GET_HASH(shdr), shdr->hash_size,
3748a697013SJens Wiklander 			       SHDR_GET_SIG(shdr), shdr->sig_size);
375c34d0d91SJens Wiklander 		break;
376c34d0d91SJens Wiklander 	default:
377c34d0d91SJens Wiklander 		panic();
378c34d0d91SJens Wiklander 	}
379c34d0d91SJens Wiklander 
3808a697013SJens Wiklander 	if (!res) {
3818a697013SJens Wiklander 		ftmn_checkpoint(&ftmn, FTMN_INCR0);
3828a697013SJens Wiklander 		goto out;
3838a697013SJens Wiklander 	}
3848a697013SJens Wiklander 	err_incr = 1;
3858a697013SJens Wiklander err:
3868a697013SJens Wiklander 	res = TEE_ERROR_SECURITY;
3878a697013SJens Wiklander 	FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res);
3888a697013SJens Wiklander out:
3898a697013SJens Wiklander 	FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res);
3908a697013SJens Wiklander 	return res;
391c34d0d91SJens Wiklander }
392