xref: /optee_os/core/crypto/signed_hdr.c (revision c34d0d917ff5f71c2f7c10d677c769c428ee90bc)
1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2064663e8SJens Wiklander /*
3*c34d0d91SJens Wiklander  * Copyright (c) 2015-2022, Linaro Limited
4064663e8SJens Wiklander  */
5064663e8SJens Wiklander 
6064663e8SJens Wiklander #include <crypto/crypto.h>
7*c34d0d91SJens Wiklander #include <kernel/panic.h>
8*c34d0d91SJens 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>
15*c34d0d91SJens 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 
51064663e8SJens Wiklander TEE_Result shdr_verify_signature(const struct shdr *shdr)
52064663e8SJens Wiklander {
53064663e8SJens Wiklander 	struct rsa_public_key key;
54064663e8SJens Wiklander 	TEE_Result res;
55064663e8SJens Wiklander 	uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
56064663e8SJens Wiklander 	size_t hash_size;
57064663e8SJens Wiklander 
58064663e8SJens Wiklander 	if (shdr->magic != SHDR_MAGIC)
59064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
60064663e8SJens Wiklander 
61064663e8SJens Wiklander 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
62064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
63064663e8SJens Wiklander 
647c767434SAlbert Schwarzkopf 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
65064663e8SJens Wiklander 				      &hash_size);
66064663e8SJens Wiklander 	if (res)
67064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
68064663e8SJens Wiklander 	if (hash_size != shdr->hash_size)
69064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
70064663e8SJens Wiklander 
7144c8e3cbSCedric Neveux 	res = crypto_acipher_alloc_rsa_public_key(&key,
7244c8e3cbSCedric Neveux 						  ta_pub_key_modulus_size * 8);
73064663e8SJens Wiklander 	if (res)
74064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
75064663e8SJens Wiklander 
76064663e8SJens Wiklander 	res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
77064663e8SJens Wiklander 	if (res)
78064663e8SJens Wiklander 		goto out;
79064663e8SJens Wiklander 	res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
80064663e8SJens Wiklander 				   key.n);
81064663e8SJens Wiklander 	if (res)
82064663e8SJens Wiklander 		goto out;
83064663e8SJens Wiklander 
842139aa8cSJens Wiklander 	res = crypto_acipher_rsassa_verify(shdr->algo, &key, shdr->hash_size,
85064663e8SJens Wiklander 					   SHDR_GET_HASH(shdr), shdr->hash_size,
86064663e8SJens Wiklander 					   SHDR_GET_SIG(shdr), shdr->sig_size);
87064663e8SJens Wiklander out:
88064663e8SJens Wiklander 	crypto_acipher_free_rsa_public_key(&key);
89064663e8SJens Wiklander 	if (res)
90064663e8SJens Wiklander 		return TEE_ERROR_SECURITY;
91064663e8SJens Wiklander 	return TEE_SUCCESS;
92064663e8SJens Wiklander }
93*c34d0d91SJens Wiklander 
94*c34d0d91SJens Wiklander static const struct shdr_subkey_attr *
95*c34d0d91SJens Wiklander find_attr(const struct shdr_subkey *subkey, uint32_t id)
96*c34d0d91SJens Wiklander {
97*c34d0d91SJens Wiklander 	size_t n = 0;
98*c34d0d91SJens Wiklander 
99*c34d0d91SJens Wiklander 	for (n = 0; n < subkey->attr_count; n++)
100*c34d0d91SJens Wiklander 		if (subkey->attrs[n].id == id)
101*c34d0d91SJens Wiklander 			return subkey->attrs + n;
102*c34d0d91SJens Wiklander 
103*c34d0d91SJens Wiklander 	return NULL;
104*c34d0d91SJens Wiklander }
105*c34d0d91SJens Wiklander 
106*c34d0d91SJens Wiklander static TEE_Result load_rsa_key(const struct shdr_subkey *subkey,
107*c34d0d91SJens Wiklander 			       struct rsa_public_key **key_pp)
108*c34d0d91SJens Wiklander {
109*c34d0d91SJens Wiklander 	const uint8_t *base = (const uint8_t *)subkey;
110*c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *pub_exp = NULL;
111*c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *modulus = NULL;
112*c34d0d91SJens Wiklander 	struct rsa_public_key *key = NULL;
113*c34d0d91SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
114*c34d0d91SJens Wiklander 
115*c34d0d91SJens Wiklander 	pub_exp = find_attr(subkey, TEE_ATTR_RSA_PUBLIC_EXPONENT);
116*c34d0d91SJens Wiklander 	if (!pub_exp)
117*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
118*c34d0d91SJens Wiklander 	modulus = find_attr(subkey, TEE_ATTR_RSA_MODULUS);
119*c34d0d91SJens Wiklander 	if (!modulus)
120*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
121*c34d0d91SJens Wiklander 
122*c34d0d91SJens Wiklander 	key = calloc(1, sizeof(*key));
123*c34d0d91SJens Wiklander 	if (!key)
124*c34d0d91SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
125*c34d0d91SJens Wiklander 	res = crypto_acipher_alloc_rsa_public_key(key, modulus->size * 8);
126*c34d0d91SJens Wiklander 	if (res)
127*c34d0d91SJens Wiklander 		goto err_key;
128*c34d0d91SJens Wiklander 
129*c34d0d91SJens Wiklander 	res = crypto_bignum_bin2bn(base + pub_exp->offs, pub_exp->size, key->e);
130*c34d0d91SJens Wiklander 	if (res)
131*c34d0d91SJens Wiklander 		goto err;
132*c34d0d91SJens Wiklander 	res = crypto_bignum_bin2bn(base + modulus->offs, modulus->size, key->n);
133*c34d0d91SJens Wiklander 	if (res)
134*c34d0d91SJens Wiklander 		goto err;
135*c34d0d91SJens Wiklander 
136*c34d0d91SJens Wiklander 	*key_pp = key;
137*c34d0d91SJens Wiklander 	return TEE_SUCCESS;
138*c34d0d91SJens Wiklander err:
139*c34d0d91SJens Wiklander 	crypto_acipher_free_rsa_public_key(key);
140*c34d0d91SJens Wiklander err_key:
141*c34d0d91SJens Wiklander 	free(key);
142*c34d0d91SJens Wiklander 	return TEE_ERROR_SECURITY;
143*c34d0d91SJens Wiklander }
144*c34d0d91SJens Wiklander 
145*c34d0d91SJens Wiklander static TEE_Result check_attrs(const struct shdr_subkey *subkey, size_t img_size)
146*c34d0d91SJens Wiklander {
147*c34d0d91SJens Wiklander 	const struct shdr_subkey_attr *attrs = subkey->attrs;
148*c34d0d91SJens Wiklander 	size_t end = 0;
149*c34d0d91SJens Wiklander 	size_t n = 0;
150*c34d0d91SJens Wiklander 
151*c34d0d91SJens Wiklander 	if (MUL_OVERFLOW(subkey->attr_count, sizeof(*attrs), &end) ||
152*c34d0d91SJens Wiklander 	    ADD_OVERFLOW(end, sizeof(*subkey), &end) ||
153*c34d0d91SJens Wiklander 	    end > img_size)
154*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
155*c34d0d91SJens Wiklander 
156*c34d0d91SJens Wiklander 	for (n = 0; n < subkey->attr_count; n++)
157*c34d0d91SJens Wiklander 		if (ADD_OVERFLOW(attrs[n].offs, attrs[n].size, &end) ||
158*c34d0d91SJens Wiklander 		    end > img_size)
159*c34d0d91SJens Wiklander 			return TEE_ERROR_SECURITY;
160*c34d0d91SJens Wiklander 
161*c34d0d91SJens Wiklander 	return TEE_SUCCESS;
162*c34d0d91SJens Wiklander }
163*c34d0d91SJens Wiklander 
164*c34d0d91SJens Wiklander static TEE_Result calc_next_uuid(uint8_t uuid[sizeof(TEE_UUID)],
165*c34d0d91SJens Wiklander 				 const uint8_t my_uuid[sizeof(TEE_UUID)],
166*c34d0d91SJens Wiklander 				 const void *ns_name, size_t name_size)
167*c34d0d91SJens Wiklander {
168*c34d0d91SJens Wiklander 	TEE_Result res = TEE_ERROR_SECURITY;
169*c34d0d91SJens Wiklander 	void *ctx = NULL;
170*c34d0d91SJens Wiklander 	struct {
171*c34d0d91SJens Wiklander 		uint8_t digest[TEE_SHA1_HASH_SIZE];
172*c34d0d91SJens Wiklander 		TEE_UUID uuid;
173*c34d0d91SJens Wiklander 		char name_str[];
174*c34d0d91SJens Wiklander 	} *tmp = NULL;
175*c34d0d91SJens Wiklander 
176*c34d0d91SJens Wiklander 	if (!name_size) {
177*c34d0d91SJens Wiklander 		memcpy(uuid, my_uuid, sizeof(TEE_UUID));
178*c34d0d91SJens Wiklander 		return TEE_SUCCESS;
179*c34d0d91SJens Wiklander 	}
180*c34d0d91SJens Wiklander 
181*c34d0d91SJens Wiklander 	/*
182*c34d0d91SJens Wiklander 	 * RFC 4122 requires a SHA-1 digest for UUID v5. Use SHA-512
183*c34d0d91SJens Wiklander 	 * instead for better collision resistance.
184*c34d0d91SJens Wiklander 	 */
185*c34d0d91SJens Wiklander 	if (crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA512))
186*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
187*c34d0d91SJens Wiklander 
188*c34d0d91SJens Wiklander 	tmp = mempool_alloc(mempool_default, sizeof(*tmp) + name_size);
189*c34d0d91SJens Wiklander 	if (!tmp)
190*c34d0d91SJens Wiklander 		goto out_ctx;
191*c34d0d91SJens Wiklander 	memcpy(tmp->name_str, ns_name, name_size);
192*c34d0d91SJens Wiklander 
193*c34d0d91SJens Wiklander 	if (crypto_hash_init(ctx) ||
194*c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, my_uuid, sizeof(TEE_UUID)) ||
195*c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)tmp->name_str,
196*c34d0d91SJens Wiklander 			       strnlen(tmp->name_str, name_size)) ||
197*c34d0d91SJens Wiklander 	    crypto_hash_final(ctx, tmp->digest, sizeof(tmp->digest)))
198*c34d0d91SJens Wiklander 		goto out_mempool;
199*c34d0d91SJens Wiklander 
200*c34d0d91SJens Wiklander 	tee_uuid_from_octets(&tmp->uuid, tmp->digest);
201*c34d0d91SJens Wiklander 	/*
202*c34d0d91SJens Wiklander 	 * Set the four most significant bits (bits 12 through 15) of the
203*c34d0d91SJens Wiklander 	 * time_hi_and_version field to 5.
204*c34d0d91SJens Wiklander 	 */
205*c34d0d91SJens Wiklander 	tmp->uuid.timeHiAndVersion &= ~SHIFT_U32(0xf, 12);
206*c34d0d91SJens Wiklander 	tmp->uuid.timeHiAndVersion |= SHIFT_U32(5, 12);
207*c34d0d91SJens Wiklander 	/*
208*c34d0d91SJens Wiklander 	 * Set the two most significant bits (bits 6 and 7) of the
209*c34d0d91SJens Wiklander 	 * clock_seq_hi_and_reserved to zero and one, respectively.
210*c34d0d91SJens Wiklander 	 */
211*c34d0d91SJens Wiklander 	tmp->uuid.clockSeqAndNode[0] &= ~BIT(6);
212*c34d0d91SJens Wiklander 	tmp->uuid.clockSeqAndNode[0] |= BIT(7);
213*c34d0d91SJens Wiklander 
214*c34d0d91SJens Wiklander 	tee_uuid_to_octets(uuid, &tmp->uuid);
215*c34d0d91SJens Wiklander 	res = TEE_SUCCESS;
216*c34d0d91SJens Wiklander 
217*c34d0d91SJens Wiklander out_mempool:
218*c34d0d91SJens Wiklander 	mempool_free(mempool_default, tmp);
219*c34d0d91SJens Wiklander out_ctx:
220*c34d0d91SJens Wiklander 	crypto_hash_free_ctx(ctx);
221*c34d0d91SJens Wiklander 
222*c34d0d91SJens Wiklander 	return res;
223*c34d0d91SJens Wiklander }
224*c34d0d91SJens Wiklander 
225*c34d0d91SJens Wiklander TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs,
226*c34d0d91SJens Wiklander 			     const uint8_t *ns_img, size_t ns_img_size,
227*c34d0d91SJens Wiklander 			     const uint8_t next_uuid[sizeof(TEE_UUID)],
228*c34d0d91SJens Wiklander 			     uint32_t max_depth, struct shdr_pub_key *key)
229*c34d0d91SJens Wiklander {
230*c34d0d91SJens Wiklander 	struct shdr_subkey *subkey = NULL;
231*c34d0d91SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
232*c34d0d91SJens Wiklander 	void *digest = NULL;
233*c34d0d91SJens Wiklander 	uint8_t *img = NULL;
234*c34d0d91SJens Wiklander 	void *ctx = NULL;
235*c34d0d91SJens Wiklander 	size_t end = 0;
236*c34d0d91SJens Wiklander 
237*c34d0d91SJens Wiklander 	if (shdr->img_type != SHDR_SUBKEY)
238*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
239*c34d0d91SJens Wiklander 
240*c34d0d91SJens Wiklander 	if (shdr->img_size < sizeof(*subkey))
241*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
242*c34d0d91SJens Wiklander 
243*c34d0d91SJens Wiklander 	if (ADD_OVERFLOW(shdr->img_size, offs, &end) || end > ns_img_size)
244*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
245*c34d0d91SJens Wiklander 
246*c34d0d91SJens Wiklander 	img = mempool_alloc(mempool_default, shdr->img_size + shdr->hash_size);
247*c34d0d91SJens Wiklander 	if (!img)
248*c34d0d91SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
249*c34d0d91SJens Wiklander 	memcpy(img + shdr->hash_size, ns_img + offs, shdr->img_size);
250*c34d0d91SJens Wiklander 	subkey = (void *)(img + shdr->hash_size);
251*c34d0d91SJens Wiklander 	digest = img;
252*c34d0d91SJens Wiklander 
253*c34d0d91SJens Wiklander 	if (crypto_hash_alloc_ctx(&ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo))) {
254*c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
255*c34d0d91SJens Wiklander 		goto out_mempool;
256*c34d0d91SJens Wiklander 	}
257*c34d0d91SJens Wiklander 
258*c34d0d91SJens Wiklander 	if (crypto_hash_init(ctx) ||
259*c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)shdr, sizeof(*shdr)) ||
260*c34d0d91SJens Wiklander 	    crypto_hash_update(ctx, (const void *)subkey, shdr->img_size) ||
261*c34d0d91SJens Wiklander 	    crypto_hash_final(ctx, digest, shdr->hash_size) ||
262*c34d0d91SJens Wiklander 	    memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size)) {
263*c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
264*c34d0d91SJens Wiklander 		goto out_ctx;
265*c34d0d91SJens Wiklander 	}
266*c34d0d91SJens Wiklander 
267*c34d0d91SJens Wiklander 	res = check_attrs(subkey, shdr->img_size);
268*c34d0d91SJens Wiklander 	if (res)
269*c34d0d91SJens Wiklander 		goto out_ctx;
270*c34d0d91SJens Wiklander 
271*c34d0d91SJens Wiklander 	if (subkey->max_depth >= max_depth) {
272*c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
273*c34d0d91SJens Wiklander 		goto out_ctx;
274*c34d0d91SJens Wiklander 	}
275*c34d0d91SJens Wiklander 	if (next_uuid && memcmp(next_uuid, subkey->uuid, sizeof(TEE_UUID))) {
276*c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
277*c34d0d91SJens Wiklander 		goto out_ctx;
278*c34d0d91SJens Wiklander 	}
279*c34d0d91SJens Wiklander 
280*c34d0d91SJens Wiklander 	key->max_depth = subkey->max_depth;
281*c34d0d91SJens Wiklander 	key->name_size = subkey->name_size;
282*c34d0d91SJens Wiklander 	memcpy(key->uuid, subkey->uuid, sizeof(TEE_UUID));
283*c34d0d91SJens Wiklander 	if (ADD_OVERFLOW(key->name_size, offs + shdr->img_size, &end) ||
284*c34d0d91SJens Wiklander 	    end > ns_img_size) {
285*c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
286*c34d0d91SJens Wiklander 		goto out_ctx;
287*c34d0d91SJens Wiklander 	}
288*c34d0d91SJens Wiklander 	res = calc_next_uuid(key->next_uuid, key->uuid,
289*c34d0d91SJens Wiklander 			     ns_img + offs + shdr->img_size, key->name_size);
290*c34d0d91SJens Wiklander 	if (res)
291*c34d0d91SJens Wiklander 		goto out_ctx;
292*c34d0d91SJens Wiklander 
293*c34d0d91SJens Wiklander 	key->main_algo = TEE_ALG_GET_MAIN_ALG(subkey->algo);
294*c34d0d91SJens Wiklander 	switch (key->main_algo) {
295*c34d0d91SJens Wiklander 	case TEE_MAIN_ALGO_RSA:
296*c34d0d91SJens Wiklander 		res = load_rsa_key(subkey, &key->pub_key.rsa);
297*c34d0d91SJens Wiklander 		break;
298*c34d0d91SJens Wiklander 	default:
299*c34d0d91SJens Wiklander 		res = TEE_ERROR_SECURITY;
300*c34d0d91SJens Wiklander 		break;
301*c34d0d91SJens Wiklander 	}
302*c34d0d91SJens Wiklander 
303*c34d0d91SJens Wiklander out_ctx:
304*c34d0d91SJens Wiklander 	crypto_hash_free_ctx(ctx);
305*c34d0d91SJens Wiklander out_mempool:
306*c34d0d91SJens Wiklander 	mempool_free(mempool_default, img);
307*c34d0d91SJens Wiklander 	return res;
308*c34d0d91SJens Wiklander }
309*c34d0d91SJens Wiklander 
310*c34d0d91SJens Wiklander void shdr_free_pub_key(struct shdr_pub_key *key)
311*c34d0d91SJens Wiklander {
312*c34d0d91SJens Wiklander 	if (key) {
313*c34d0d91SJens Wiklander 		switch (key->main_algo) {
314*c34d0d91SJens Wiklander 		case TEE_MAIN_ALGO_RSA:
315*c34d0d91SJens Wiklander 			crypto_acipher_free_rsa_public_key(key->pub_key.rsa);
316*c34d0d91SJens Wiklander 			free(key->pub_key.rsa);
317*c34d0d91SJens Wiklander 			break;
318*c34d0d91SJens Wiklander 		default:
319*c34d0d91SJens Wiklander 			panic();
320*c34d0d91SJens Wiklander 		}
321*c34d0d91SJens Wiklander 	}
322*c34d0d91SJens Wiklander }
323*c34d0d91SJens Wiklander 
324*c34d0d91SJens Wiklander TEE_Result shdr_verify_signature2(struct shdr_pub_key *key,
325*c34d0d91SJens Wiklander 				  const struct shdr *shdr)
326*c34d0d91SJens Wiklander {
327*c34d0d91SJens Wiklander 	size_t hash_size = 0;
328*c34d0d91SJens Wiklander 
329*c34d0d91SJens Wiklander 	if (shdr->magic != SHDR_MAGIC)
330*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
331*c34d0d91SJens Wiklander 
332*c34d0d91SJens Wiklander 	if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo)
333*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
334*c34d0d91SJens Wiklander 
335*c34d0d91SJens Wiklander 	if (tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo),
336*c34d0d91SJens Wiklander 				    &hash_size) ||
337*c34d0d91SJens Wiklander 	    hash_size != shdr->hash_size)
338*c34d0d91SJens Wiklander 		return TEE_ERROR_SECURITY;
339*c34d0d91SJens Wiklander 
340*c34d0d91SJens Wiklander 	switch (key->main_algo) {
341*c34d0d91SJens Wiklander 	case TEE_MAIN_ALGO_RSA:
342*c34d0d91SJens Wiklander 		if (crypto_acipher_rsassa_verify(shdr->algo, key->pub_key.rsa,
343*c34d0d91SJens Wiklander 						 shdr->hash_size,
344*c34d0d91SJens Wiklander 						 SHDR_GET_HASH(shdr),
345*c34d0d91SJens Wiklander 						 shdr->hash_size,
346*c34d0d91SJens Wiklander 						 SHDR_GET_SIG(shdr),
347*c34d0d91SJens Wiklander 						 shdr->sig_size))
348*c34d0d91SJens Wiklander 			return TEE_ERROR_SECURITY;
349*c34d0d91SJens Wiklander 		break;
350*c34d0d91SJens Wiklander 	default:
351*c34d0d91SJens Wiklander 		panic();
352*c34d0d91SJens Wiklander 	}
353*c34d0d91SJens Wiklander 
354*c34d0d91SJens Wiklander 	return TEE_SUCCESS;
355*c34d0d91SJens Wiklander }
356