xref: /optee_os/core/lib/libtomcrypt/rsa.c (revision f5c3d85a579c9594ee7592af0c0783891c21d9e0)
189ed30d1SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
289ed30d1SJens Wiklander /*
38f6ac972SJens Wiklander  * Copyright (c) 2014-2019, 2022 Linaro Limited
489ed30d1SJens Wiklander  */
589ed30d1SJens Wiklander 
689ed30d1SJens Wiklander #include <crypto/crypto.h>
7c2c27539SJorge Ramirez-Ortiz #include <crypto/crypto_impl.h>
88f6ac972SJens Wiklander #include <fault_mitigation.h>
9d71c4cd4SJens Wiklander #include <mempool.h>
1089ed30d1SJens Wiklander #include <stdlib.h>
1189ed30d1SJens Wiklander #include <string.h>
1289ed30d1SJens Wiklander #include <tee_api_defines_extensions.h>
138f6ac972SJens Wiklander #include <tee_api_types.h>
1489ed30d1SJens Wiklander #include <tee/tee_cryp_utl.h>
1589ed30d1SJens Wiklander #include <trace.h>
1689ed30d1SJens Wiklander #include <utee_defines.h>
1789ed30d1SJens Wiklander 
1889ed30d1SJens Wiklander #include "acipher_helpers.h"
1989ed30d1SJens Wiklander 
2089ed30d1SJens Wiklander 
2189ed30d1SJens Wiklander /*
2289ed30d1SJens Wiklander  * Compute the LibTomCrypt "hashindex" given a TEE Algorithm "algo"
2389ed30d1SJens Wiklander  * Return
2489ed30d1SJens Wiklander  * - TEE_SUCCESS in case of success,
2589ed30d1SJens Wiklander  * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo
2689ed30d1SJens Wiklander  * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC
2789ed30d1SJens Wiklander  * Return -1 in case of error
2889ed30d1SJens Wiklander  */
2989ed30d1SJens Wiklander static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
3089ed30d1SJens Wiklander {
3189ed30d1SJens Wiklander 	switch (algo) {
32a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA1)
3389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
3489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
3589ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
3689ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha1");
3789ed30d1SJens Wiklander 		break;
3889ed30d1SJens Wiklander #endif
39a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_MD5)
4089ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
41*f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
42*f5c3d85aSJulien Masson 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5:
4389ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("md5");
4489ed30d1SJens Wiklander 		break;
4589ed30d1SJens Wiklander #endif
46a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA224)
4789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
4889ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
4989ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
5089ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha224");
5189ed30d1SJens Wiklander 		break;
5289ed30d1SJens Wiklander #endif
53a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA256)
5489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
5589ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
5689ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
5789ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha256");
5889ed30d1SJens Wiklander 		break;
5989ed30d1SJens Wiklander #endif
60a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA384)
6189ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
6289ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
6389ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
6489ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha384");
6589ed30d1SJens Wiklander 		break;
6689ed30d1SJens Wiklander #endif
67a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA512)
6889ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
6989ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
7089ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
7189ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha512");
7289ed30d1SJens Wiklander 		break;
7389ed30d1SJens Wiklander #endif
7489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5:
7589ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_V1_5:
7689ed30d1SJens Wiklander 		/* invalid one. but it should not be used anyway */
7789ed30d1SJens Wiklander 		*ltc_hashindex = -1;
7889ed30d1SJens Wiklander 		return TEE_SUCCESS;
7989ed30d1SJens Wiklander 
8089ed30d1SJens Wiklander 	default:
8189ed30d1SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
8289ed30d1SJens Wiklander 	}
8389ed30d1SJens Wiklander 
8489ed30d1SJens Wiklander 	if (*ltc_hashindex < 0)
8589ed30d1SJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
8689ed30d1SJens Wiklander 	else
8789ed30d1SJens Wiklander 		return TEE_SUCCESS;
8889ed30d1SJens Wiklander }
8989ed30d1SJens Wiklander 
9089ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
9189ed30d1SJens Wiklander 					    size_t key_size_bits __unused)
92c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_keypair");
93c2c27539SJorge Ramirez-Ortiz 
94c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
95c2c27539SJorge Ramirez-Ortiz 					       size_t key_size_bits __unused)
9689ed30d1SJens Wiklander {
9789ed30d1SJens Wiklander 	memset(s, 0, sizeof(*s));
9889ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->e))
9989ed30d1SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
10089ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->d))
10189ed30d1SJens Wiklander 		goto err;
10289ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->n))
10389ed30d1SJens Wiklander 		goto err;
10489ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->p))
10589ed30d1SJens Wiklander 		goto err;
10689ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->q))
10789ed30d1SJens Wiklander 		goto err;
10889ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->qp))
10989ed30d1SJens Wiklander 		goto err;
11089ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->dp))
11189ed30d1SJens Wiklander 		goto err;
11289ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->dq))
11389ed30d1SJens Wiklander 		goto err;
11489ed30d1SJens Wiklander 
11589ed30d1SJens Wiklander 	return TEE_SUCCESS;
11689ed30d1SJens Wiklander err:
11792e38694SJerome Forissier 	crypto_acipher_free_rsa_keypair(s);
11889ed30d1SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
11989ed30d1SJens Wiklander }
12089ed30d1SJens Wiklander 
121c2c27539SJorge Ramirez-Ortiz 
12289ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
12389ed30d1SJens Wiklander 					       size_t key_size_bits __unused)
124c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_public_key");
125c2c27539SJorge Ramirez-Ortiz 
126c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
127c2c27539SJorge Ramirez-Ortiz 						  size_t key_size_bits __unused)
12889ed30d1SJens Wiklander {
12989ed30d1SJens Wiklander 	memset(s, 0, sizeof(*s));
13089ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->e))
13189ed30d1SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
13289ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->n))
13389ed30d1SJens Wiklander 		goto err;
13489ed30d1SJens Wiklander 	return TEE_SUCCESS;
13589ed30d1SJens Wiklander err:
13689ed30d1SJens Wiklander 	crypto_bignum_free(s->e);
13789ed30d1SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
13889ed30d1SJens Wiklander }
13989ed30d1SJens Wiklander 
140c2c27539SJorge Ramirez-Ortiz 
14189ed30d1SJens Wiklander void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
142c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_public_key");
143c2c27539SJorge Ramirez-Ortiz 
144c2c27539SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
14589ed30d1SJens Wiklander {
14689ed30d1SJens Wiklander 	if (!s)
14789ed30d1SJens Wiklander 		return;
14889ed30d1SJens Wiklander 	crypto_bignum_free(s->n);
14989ed30d1SJens Wiklander 	crypto_bignum_free(s->e);
15089ed30d1SJens Wiklander }
15189ed30d1SJens Wiklander 
152c2c27539SJorge Ramirez-Ortiz 
153a1d5c81fSElias von Däniken void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
154c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_keypair");
155c2c27539SJorge Ramirez-Ortiz 
156c2c27539SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
157a1d5c81fSElias von Däniken {
158a1d5c81fSElias von Däniken 	if (!s)
159a1d5c81fSElias von Däniken 		return;
160a1d5c81fSElias von Däniken 	crypto_bignum_free(s->e);
161a1d5c81fSElias von Däniken 	crypto_bignum_free(s->d);
162a1d5c81fSElias von Däniken 	crypto_bignum_free(s->n);
163a1d5c81fSElias von Däniken 	crypto_bignum_free(s->p);
164a1d5c81fSElias von Däniken 	crypto_bignum_free(s->q);
165a1d5c81fSElias von Däniken 	crypto_bignum_free(s->qp);
166a1d5c81fSElias von Däniken 	crypto_bignum_free(s->dp);
16785f7c554SJerome Forissier 	crypto_bignum_free(s->dq);
168a1d5c81fSElias von Däniken }
169a1d5c81fSElias von Däniken 
170c2c27539SJorge Ramirez-Ortiz TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
171c2c27539SJorge Ramirez-Ortiz 				      size_t key_size)
172c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_gen_rsa_key");
173c2c27539SJorge Ramirez-Ortiz 
174c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
175c2c27539SJorge Ramirez-Ortiz 					 size_t key_size)
17689ed30d1SJens Wiklander {
17789ed30d1SJens Wiklander 	TEE_Result res;
17889ed30d1SJens Wiklander 	rsa_key ltc_tmp_key;
17989ed30d1SJens Wiklander 	int ltc_res;
18089ed30d1SJens Wiklander 
18189ed30d1SJens Wiklander 	/* Generate a temporary RSA key */
18274524a75SCedric Neveux 	ltc_res = rsa_make_key_bn_e(NULL, find_prng("prng_crypto"),
18374524a75SCedric Neveux 				    key_size / 8, key->e, &ltc_tmp_key);
18489ed30d1SJens Wiklander 	if (ltc_res != CRYPT_OK) {
18589ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
18689ed30d1SJens Wiklander 	} else if ((size_t)mp_count_bits(ltc_tmp_key.N) != key_size) {
18789ed30d1SJens Wiklander 		rsa_free(&ltc_tmp_key);
18889ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
18989ed30d1SJens Wiklander 	} else {
19089ed30d1SJens Wiklander 		/* Copy the key */
19189ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.d,  key->d);
19289ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.N,  key->n);
19389ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.p,  key->p);
19489ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.q,  key->q);
19589ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.qP, key->qp);
19689ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.dP, key->dp);
19789ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.dQ, key->dq);
19889ed30d1SJens Wiklander 
19989ed30d1SJens Wiklander 		/* Free the temporary key */
20089ed30d1SJens Wiklander 		rsa_free(&ltc_tmp_key);
20189ed30d1SJens Wiklander 		res = TEE_SUCCESS;
20289ed30d1SJens Wiklander 	}
20389ed30d1SJens Wiklander 
20489ed30d1SJens Wiklander 	return res;
20589ed30d1SJens Wiklander }
20689ed30d1SJens Wiklander 
20789ed30d1SJens Wiklander static TEE_Result rsadorep(rsa_key *ltc_key, const uint8_t *src,
20889ed30d1SJens Wiklander 			   size_t src_len, uint8_t *dst, size_t *dst_len)
20989ed30d1SJens Wiklander {
21089ed30d1SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
21189ed30d1SJens Wiklander 	uint8_t *buf = NULL;
21289ed30d1SJens Wiklander 	unsigned long blen, offset;
21389ed30d1SJens Wiklander 	int ltc_res;
21489ed30d1SJens Wiklander 
21589ed30d1SJens Wiklander 	/*
21689ed30d1SJens Wiklander 	 * Use a temporary buffer since we don't know exactly how large the
21789ed30d1SJens Wiklander 	 * required size of the out buffer without doing a partial decrypt.
21889ed30d1SJens Wiklander 	 * We know the upper bound though.
21989ed30d1SJens Wiklander 	 */
220a1cbb728SJens Wiklander 	blen = _CFG_CORE_LTC_BIGNUM_MAX_BITS / sizeof(uint8_t);
221d71c4cd4SJens Wiklander 	buf = mempool_alloc(mempool_default, blen);
22289ed30d1SJens Wiklander 	if (!buf) {
22389ed30d1SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
22489ed30d1SJens Wiklander 		goto out;
22589ed30d1SJens Wiklander 	}
22689ed30d1SJens Wiklander 
22789ed30d1SJens Wiklander 	ltc_res = rsa_exptmod(src, src_len, buf, &blen, ltc_key->type,
22889ed30d1SJens Wiklander 			      ltc_key);
22989ed30d1SJens Wiklander 	switch (ltc_res) {
23089ed30d1SJens Wiklander 	case CRYPT_PK_NOT_PRIVATE:
23189ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_TYPE:
23289ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_SIZE:
23389ed30d1SJens Wiklander 	case CRYPT_INVALID_PACKET:
23489ed30d1SJens Wiklander 		EMSG("rsa_exptmod() returned %d", ltc_res);
23589ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
23689ed30d1SJens Wiklander 		goto out;
23789ed30d1SJens Wiklander 	case CRYPT_OK:
23889ed30d1SJens Wiklander 		break;
23989ed30d1SJens Wiklander 	default:
24089ed30d1SJens Wiklander 		/* This will result in a panic */
24189ed30d1SJens Wiklander 		EMSG("rsa_exptmod() returned %d", ltc_res);
24289ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
24389ed30d1SJens Wiklander 		goto out;
24489ed30d1SJens Wiklander 	}
24589ed30d1SJens Wiklander 
24689ed30d1SJens Wiklander 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
24789ed30d1SJens Wiklander 	offset = 0;
24889ed30d1SJens Wiklander 	while ((offset < blen - 1) && (buf[offset] == 0))
24989ed30d1SJens Wiklander 		offset++;
25089ed30d1SJens Wiklander 
25189ed30d1SJens Wiklander 	if (*dst_len < blen - offset) {
25289ed30d1SJens Wiklander 		*dst_len = blen - offset;
25389ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
25489ed30d1SJens Wiklander 		goto out;
25589ed30d1SJens Wiklander 	}
25689ed30d1SJens Wiklander 
25789ed30d1SJens Wiklander 	res = TEE_SUCCESS;
25889ed30d1SJens Wiklander 	*dst_len = blen - offset;
25989ed30d1SJens Wiklander 	memcpy(dst, (char *)buf + offset, *dst_len);
26089ed30d1SJens Wiklander 
26189ed30d1SJens Wiklander out:
262d71c4cd4SJens Wiklander 	mempool_free(mempool_default, buf);
26389ed30d1SJens Wiklander 
26489ed30d1SJens Wiklander 	return res;
26589ed30d1SJens Wiklander }
26689ed30d1SJens Wiklander 
26789ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
268c2c27539SJorge Ramirez-Ortiz 					   const uint8_t *src,
269c2c27539SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
270c2c27539SJorge Ramirez-Ortiz 					   size_t *dst_len)
271c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_encrypt");
272c2c27539SJorge Ramirez-Ortiz 
273c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
274c2c27539SJorge Ramirez-Ortiz 					      const uint8_t *src,
275c2c27539SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
276c2c27539SJorge Ramirez-Ortiz 					      size_t *dst_len)
27789ed30d1SJens Wiklander {
27889ed30d1SJens Wiklander 	TEE_Result res;
27989ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
28089ed30d1SJens Wiklander 
28189ed30d1SJens Wiklander 	ltc_key.type = PK_PUBLIC;
28289ed30d1SJens Wiklander 	ltc_key.e = key->e;
28389ed30d1SJens Wiklander 	ltc_key.N = key->n;
28489ed30d1SJens Wiklander 
28589ed30d1SJens Wiklander 	res = rsadorep(&ltc_key, src, src_len, dst, dst_len);
28689ed30d1SJens Wiklander 	return res;
28789ed30d1SJens Wiklander }
28889ed30d1SJens Wiklander 
28989ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
290c2c27539SJorge Ramirez-Ortiz 					   const uint8_t *src,
291c2c27539SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
292c2c27539SJorge Ramirez-Ortiz 					   size_t *dst_len)
293c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_decrypt");
294c2c27539SJorge Ramirez-Ortiz 
295c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
296c2c27539SJorge Ramirez-Ortiz 					      const uint8_t *src,
297c2c27539SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
298c2c27539SJorge Ramirez-Ortiz 					      size_t *dst_len)
29989ed30d1SJens Wiklander {
30089ed30d1SJens Wiklander 	TEE_Result res;
30189ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
30289ed30d1SJens Wiklander 
30389ed30d1SJens Wiklander 	ltc_key.type = PK_PRIVATE;
30489ed30d1SJens Wiklander 	ltc_key.e = key->e;
30589ed30d1SJens Wiklander 	ltc_key.N = key->n;
30689ed30d1SJens Wiklander 	ltc_key.d = key->d;
30789ed30d1SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
30889ed30d1SJens Wiklander 		ltc_key.p = key->p;
30989ed30d1SJens Wiklander 		ltc_key.q = key->q;
31089ed30d1SJens Wiklander 		ltc_key.qP = key->qp;
31189ed30d1SJens Wiklander 		ltc_key.dP = key->dp;
31289ed30d1SJens Wiklander 		ltc_key.dQ = key->dq;
31389ed30d1SJens Wiklander 	}
31489ed30d1SJens Wiklander 
31589ed30d1SJens Wiklander 	res = rsadorep(&ltc_key, src, src_len, dst, dst_len);
31689ed30d1SJens Wiklander 	return res;
31789ed30d1SJens Wiklander }
31889ed30d1SJens Wiklander 
319c2c27539SJorge Ramirez-Ortiz TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo,
320c2c27539SJorge Ramirez-Ortiz 					struct rsa_keypair *key,
321c2c27539SJorge Ramirez-Ortiz 					const uint8_t *label,
322c2c27539SJorge Ramirez-Ortiz 					size_t label_len, const uint8_t *src,
323c2c27539SJorge Ramirez-Ortiz 					size_t src_len, uint8_t *dst,
324c2c27539SJorge Ramirez-Ortiz 					size_t *dst_len)
325c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_decrypt");
326c2c27539SJorge Ramirez-Ortiz 
327c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
328c2c27539SJorge Ramirez-Ortiz 					   struct rsa_keypair *key,
329c2c27539SJorge Ramirez-Ortiz 					   const uint8_t *label,
330c2c27539SJorge Ramirez-Ortiz 					   size_t label_len, const uint8_t *src,
331c2c27539SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
332c2c27539SJorge Ramirez-Ortiz 					   size_t *dst_len)
33389ed30d1SJens Wiklander {
33489ed30d1SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
33589ed30d1SJens Wiklander 	void *buf = NULL;
33689ed30d1SJens Wiklander 	unsigned long blen;
33789ed30d1SJens Wiklander 	int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo;
33889ed30d1SJens Wiklander 	size_t mod_size;
33989ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
34089ed30d1SJens Wiklander 
34189ed30d1SJens Wiklander 	ltc_key.type = PK_PRIVATE;
34289ed30d1SJens Wiklander 	ltc_key.e = key->e;
34389ed30d1SJens Wiklander 	ltc_key.d = key->d;
34489ed30d1SJens Wiklander 	ltc_key.N = key->n;
34589ed30d1SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
34689ed30d1SJens Wiklander 		ltc_key.p = key->p;
34789ed30d1SJens Wiklander 		ltc_key.q = key->q;
34889ed30d1SJens Wiklander 		ltc_key.qP = key->qp;
34989ed30d1SJens Wiklander 		ltc_key.dP = key->dp;
35089ed30d1SJens Wiklander 		ltc_key.dQ = key->dq;
35189ed30d1SJens Wiklander 	}
35289ed30d1SJens Wiklander 
35389ed30d1SJens Wiklander 	/* Get the algorithm */
35489ed30d1SJens Wiklander 	res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
35589ed30d1SJens Wiklander 	if (res != TEE_SUCCESS) {
35689ed30d1SJens Wiklander 		EMSG("tee_algo_to_ltc_hashindex() returned %d", (int)res);
35789ed30d1SJens Wiklander 		goto out;
35889ed30d1SJens Wiklander 	}
35989ed30d1SJens Wiklander 
36089ed30d1SJens Wiklander 	/*
36189ed30d1SJens Wiklander 	 * Use a temporary buffer since we don't know exactly how large
36289ed30d1SJens Wiklander 	 * the required size of the out buffer without doing a partial
36389ed30d1SJens Wiklander 	 * decrypt. We know the upper bound though.
36489ed30d1SJens Wiklander 	 */
36589ed30d1SJens Wiklander 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
36689ed30d1SJens Wiklander 		mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N));
36789ed30d1SJens Wiklander 		blen = mod_size - 11;
36889ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
36989ed30d1SJens Wiklander 	} else {
37089ed30d1SJens Wiklander 		/* Decoded message is always shorter than encrypted message */
37189ed30d1SJens Wiklander 		blen = src_len;
37289ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_OAEP;
37389ed30d1SJens Wiklander 	}
37489ed30d1SJens Wiklander 
375d71c4cd4SJens Wiklander 	buf = mempool_alloc(mempool_default, blen);
37689ed30d1SJens Wiklander 	if (!buf) {
37789ed30d1SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
37889ed30d1SJens Wiklander 		goto out;
37989ed30d1SJens Wiklander 	}
38089ed30d1SJens Wiklander 
38189ed30d1SJens Wiklander 	ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen,
38289ed30d1SJens Wiklander 				     ((label_len == 0) ? 0 : label), label_len,
38389ed30d1SJens Wiklander 				     ltc_hashindex, ltc_rsa_algo, &ltc_stat,
38489ed30d1SJens Wiklander 				     &ltc_key);
38589ed30d1SJens Wiklander 	switch (ltc_res) {
38689ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_PADDING:
38789ed30d1SJens Wiklander 	case CRYPT_INVALID_PACKET:
38889ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_SIZE:
38989ed30d1SJens Wiklander 		EMSG("rsa_decrypt_key_ex() returned %d", ltc_res);
39089ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
39189ed30d1SJens Wiklander 		goto out;
39289ed30d1SJens Wiklander 	case CRYPT_OK:
39389ed30d1SJens Wiklander 		break;
39489ed30d1SJens Wiklander 	default:
39589ed30d1SJens Wiklander 		/* This will result in a panic */
39689ed30d1SJens Wiklander 		EMSG("rsa_decrypt_key_ex() returned %d", ltc_res);
39789ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
39889ed30d1SJens Wiklander 		goto out;
39989ed30d1SJens Wiklander 	}
40089ed30d1SJens Wiklander 	if (ltc_stat != 1) {
40189ed30d1SJens Wiklander 		/* This will result in a panic */
40289ed30d1SJens Wiklander 		EMSG("rsa_decrypt_key_ex() returned %d and %d",
40389ed30d1SJens Wiklander 		     ltc_res, ltc_stat);
40489ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
40589ed30d1SJens Wiklander 		goto out;
40689ed30d1SJens Wiklander 	}
40789ed30d1SJens Wiklander 
40889ed30d1SJens Wiklander 	if (*dst_len < blen) {
40989ed30d1SJens Wiklander 		*dst_len = blen;
41089ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
41189ed30d1SJens Wiklander 		goto out;
41289ed30d1SJens Wiklander 	}
41389ed30d1SJens Wiklander 
41489ed30d1SJens Wiklander 	res = TEE_SUCCESS;
41589ed30d1SJens Wiklander 	*dst_len = blen;
41689ed30d1SJens Wiklander 	memcpy(dst, buf, blen);
41789ed30d1SJens Wiklander 
41889ed30d1SJens Wiklander out:
419d71c4cd4SJens Wiklander 	mempool_free(mempool_default, buf);
42089ed30d1SJens Wiklander 
42189ed30d1SJens Wiklander 	return res;
42289ed30d1SJens Wiklander }
42389ed30d1SJens Wiklander 
42489ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
42589ed30d1SJens Wiklander 					struct rsa_public_key *key,
426c2c27539SJorge Ramirez-Ortiz 					const uint8_t *label,
427c2c27539SJorge Ramirez-Ortiz 					size_t label_len, const uint8_t *src,
428c2c27539SJorge Ramirez-Ortiz 					size_t src_len, uint8_t *dst,
429c2c27539SJorge Ramirez-Ortiz 					size_t *dst_len)
430c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_encrypt");
431c2c27539SJorge Ramirez-Ortiz 
432c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
433c2c27539SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
434c2c27539SJorge Ramirez-Ortiz 					   const uint8_t *label,
435c2c27539SJorge Ramirez-Ortiz 					   size_t label_len, const uint8_t *src,
436c2c27539SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
437c2c27539SJorge Ramirez-Ortiz 					   size_t *dst_len)
43889ed30d1SJens Wiklander {
43989ed30d1SJens Wiklander 	TEE_Result res;
44089ed30d1SJens Wiklander 	uint32_t mod_size;
44189ed30d1SJens Wiklander 	int ltc_hashindex, ltc_res, ltc_rsa_algo;
44289ed30d1SJens Wiklander 	rsa_key ltc_key = {
44389ed30d1SJens Wiklander 		.type = PK_PUBLIC,
44489ed30d1SJens Wiklander 		.e = key->e,
44589ed30d1SJens Wiklander 		.N = key->n
44689ed30d1SJens Wiklander 	};
44789ed30d1SJens Wiklander 
44889ed30d1SJens Wiklander 	mod_size =  ltc_mp.unsigned_size((void *)(ltc_key.N));
44989ed30d1SJens Wiklander 	if (*dst_len < mod_size) {
45089ed30d1SJens Wiklander 		*dst_len = mod_size;
45189ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
45289ed30d1SJens Wiklander 		goto out;
45389ed30d1SJens Wiklander 	}
45489ed30d1SJens Wiklander 	*dst_len = mod_size;
45589ed30d1SJens Wiklander 
45689ed30d1SJens Wiklander 	/* Get the algorithm */
45789ed30d1SJens Wiklander 	res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
45889ed30d1SJens Wiklander 	if (res != TEE_SUCCESS)
45989ed30d1SJens Wiklander 		goto out;
46089ed30d1SJens Wiklander 
46189ed30d1SJens Wiklander 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
46289ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
46389ed30d1SJens Wiklander 	else
46489ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_OAEP;
46589ed30d1SJens Wiklander 
46689ed30d1SJens Wiklander 	ltc_res = rsa_encrypt_key_ex(src, src_len, dst,
46789ed30d1SJens Wiklander 				     (unsigned long *)(dst_len), label,
4681f3b1115SJens Wiklander 				     label_len, NULL, find_prng("prng_crypto"),
46989ed30d1SJens Wiklander 				     ltc_hashindex, ltc_rsa_algo, &ltc_key);
47089ed30d1SJens Wiklander 	switch (ltc_res) {
47189ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_PADDING:
47289ed30d1SJens Wiklander 	case CRYPT_INVALID_PACKET:
47389ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_SIZE:
47489ed30d1SJens Wiklander 		EMSG("rsa_encrypt_key_ex() returned %d", ltc_res);
47589ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
47689ed30d1SJens Wiklander 		goto out;
47789ed30d1SJens Wiklander 	case CRYPT_OK:
47889ed30d1SJens Wiklander 		break;
47989ed30d1SJens Wiklander 	default:
48089ed30d1SJens Wiklander 		/* This will result in a panic */
48189ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
48289ed30d1SJens Wiklander 		goto out;
48389ed30d1SJens Wiklander 	}
48489ed30d1SJens Wiklander 	res = TEE_SUCCESS;
48589ed30d1SJens Wiklander 
48689ed30d1SJens Wiklander out:
48789ed30d1SJens Wiklander 	return res;
48889ed30d1SJens Wiklander }
48989ed30d1SJens Wiklander 
49089ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
49189ed30d1SJens Wiklander 				      int salt_len, const uint8_t *msg,
49289ed30d1SJens Wiklander 				      size_t msg_len, uint8_t *sig,
49389ed30d1SJens Wiklander 				      size_t *sig_len)
494c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_sign");
495c2c27539SJorge Ramirez-Ortiz 
496c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
497c2c27539SJorge Ramirez-Ortiz 					 int salt_len, const uint8_t *msg,
498c2c27539SJorge Ramirez-Ortiz 					 size_t msg_len, uint8_t *sig,
499c2c27539SJorge Ramirez-Ortiz 					 size_t *sig_len)
50089ed30d1SJens Wiklander {
50189ed30d1SJens Wiklander 	TEE_Result res;
50289ed30d1SJens Wiklander 	size_t hash_size, mod_size;
50389ed30d1SJens Wiklander 	int ltc_res, ltc_rsa_algo, ltc_hashindex;
50489ed30d1SJens Wiklander 	unsigned long ltc_sig_len;
50589ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
50689ed30d1SJens Wiklander 
50789ed30d1SJens Wiklander 	ltc_key.type = PK_PRIVATE;
50889ed30d1SJens Wiklander 	ltc_key.e = key->e;
50989ed30d1SJens Wiklander 	ltc_key.N = key->n;
51089ed30d1SJens Wiklander 	ltc_key.d = key->d;
51189ed30d1SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
51289ed30d1SJens Wiklander 		ltc_key.p = key->p;
51389ed30d1SJens Wiklander 		ltc_key.q = key->q;
51489ed30d1SJens Wiklander 		ltc_key.qP = key->qp;
51589ed30d1SJens Wiklander 		ltc_key.dP = key->dp;
51689ed30d1SJens Wiklander 		ltc_key.dQ = key->dq;
51789ed30d1SJens Wiklander 	}
51889ed30d1SJens Wiklander 
51989ed30d1SJens Wiklander 	switch (algo) {
52089ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5:
52189ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1;
52289ed30d1SJens Wiklander 		break;
52389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
52489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
52589ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
52689ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
52789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
52889ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
52989ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
53089ed30d1SJens Wiklander 		break;
531*f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
53289ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
53389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
53489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
53589ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
53689ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
53789ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_PSS;
53889ed30d1SJens Wiklander 		break;
53989ed30d1SJens Wiklander 	default:
54089ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
54189ed30d1SJens Wiklander 		goto err;
54289ed30d1SJens Wiklander 	}
54389ed30d1SJens Wiklander 
54489ed30d1SJens Wiklander 	if (ltc_rsa_algo != LTC_PKCS_1_V1_5_NA1) {
54589ed30d1SJens Wiklander 		ltc_res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
54689ed30d1SJens Wiklander 		if (ltc_res != CRYPT_OK) {
54789ed30d1SJens Wiklander 			res = TEE_ERROR_BAD_PARAMETERS;
54889ed30d1SJens Wiklander 			goto err;
54989ed30d1SJens Wiklander 		}
55089ed30d1SJens Wiklander 
5517c767434SAlbert Schwarzkopf 		res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
55289ed30d1SJens Wiklander 					      &hash_size);
55389ed30d1SJens Wiklander 		if (res != TEE_SUCCESS)
55489ed30d1SJens Wiklander 			goto err;
55589ed30d1SJens Wiklander 
55689ed30d1SJens Wiklander 		if (msg_len != hash_size) {
55789ed30d1SJens Wiklander 			res = TEE_ERROR_BAD_PARAMETERS;
55889ed30d1SJens Wiklander 			goto err;
55989ed30d1SJens Wiklander 		}
56089ed30d1SJens Wiklander 	}
56189ed30d1SJens Wiklander 
56289ed30d1SJens Wiklander 	mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N));
56389ed30d1SJens Wiklander 
56489ed30d1SJens Wiklander 	if (*sig_len < mod_size) {
56589ed30d1SJens Wiklander 		*sig_len = mod_size;
56689ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
56789ed30d1SJens Wiklander 		goto err;
56889ed30d1SJens Wiklander 	}
56989ed30d1SJens Wiklander 
57089ed30d1SJens Wiklander 	ltc_sig_len = mod_size;
57189ed30d1SJens Wiklander 
57289ed30d1SJens Wiklander 	ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, &ltc_sig_len,
5731f3b1115SJens Wiklander 				   ltc_rsa_algo, NULL, find_prng("prng_crypto"),
57489ed30d1SJens Wiklander 				   ltc_hashindex, salt_len, &ltc_key);
57589ed30d1SJens Wiklander 
57689ed30d1SJens Wiklander 	*sig_len = ltc_sig_len;
57789ed30d1SJens Wiklander 
57889ed30d1SJens Wiklander 	if (ltc_res != CRYPT_OK) {
57989ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
58089ed30d1SJens Wiklander 		goto err;
58189ed30d1SJens Wiklander 	}
58289ed30d1SJens Wiklander 	res = TEE_SUCCESS;
58389ed30d1SJens Wiklander 
58489ed30d1SJens Wiklander err:
58589ed30d1SJens Wiklander 	return res;
58689ed30d1SJens Wiklander }
58789ed30d1SJens Wiklander 
58889ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_verify(uint32_t algo,
58989ed30d1SJens Wiklander 					struct rsa_public_key *key,
59089ed30d1SJens Wiklander 					int salt_len, const uint8_t *msg,
59189ed30d1SJens Wiklander 					size_t msg_len, const uint8_t *sig,
59289ed30d1SJens Wiklander 					size_t sig_len)
593c2c27539SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_verify");
594c2c27539SJorge Ramirez-Ortiz 
595c2c27539SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
596c2c27539SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
597c2c27539SJorge Ramirez-Ortiz 					   int salt_len, const uint8_t *msg,
598c2c27539SJorge Ramirez-Ortiz 					   size_t msg_len, const uint8_t *sig,
599c2c27539SJorge Ramirez-Ortiz 					   size_t sig_len)
60089ed30d1SJens Wiklander {
60189ed30d1SJens Wiklander 	TEE_Result res;
60289ed30d1SJens Wiklander 	uint32_t bigint_size;
60389ed30d1SJens Wiklander 	size_t hash_size;
60489ed30d1SJens Wiklander 	int stat, ltc_hashindex, ltc_res, ltc_rsa_algo;
60589ed30d1SJens Wiklander 	rsa_key ltc_key = {
60689ed30d1SJens Wiklander 		.type = PK_PUBLIC,
60789ed30d1SJens Wiklander 		.e = key->e,
60889ed30d1SJens Wiklander 		.N = key->n
60989ed30d1SJens Wiklander 	};
6108f6ac972SJens Wiklander 	struct ftmn   ftmn = { };
6118f6ac972SJens Wiklander 
6128f6ac972SJens Wiklander 	/*
6138f6ac972SJens Wiklander 	 * The caller expects to call crypto_acipher_rsassa_verify(),
6148f6ac972SJens Wiklander 	 * update the hash as needed.
6158f6ac972SJens Wiklander 	 */
6168f6ac972SJens Wiklander 	FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify"));
61789ed30d1SJens Wiklander 
61889ed30d1SJens Wiklander 	if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) {
6197c767434SAlbert Schwarzkopf 		res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
62089ed30d1SJens Wiklander 					      &hash_size);
62189ed30d1SJens Wiklander 		if (res != TEE_SUCCESS)
62289ed30d1SJens Wiklander 			goto err;
62389ed30d1SJens Wiklander 
62489ed30d1SJens Wiklander 		if (msg_len != hash_size) {
62589ed30d1SJens Wiklander 			res = TEE_ERROR_BAD_PARAMETERS;
62689ed30d1SJens Wiklander 			goto err;
62789ed30d1SJens Wiklander 		}
62889ed30d1SJens Wiklander 	}
62989ed30d1SJens Wiklander 
63089ed30d1SJens Wiklander 	bigint_size = ltc_mp.unsigned_size(ltc_key.N);
63189ed30d1SJens Wiklander 	if (sig_len < bigint_size) {
63289ed30d1SJens Wiklander 		res = TEE_ERROR_SIGNATURE_INVALID;
63389ed30d1SJens Wiklander 		goto err;
63489ed30d1SJens Wiklander 	}
63589ed30d1SJens Wiklander 
63689ed30d1SJens Wiklander 	/* Get the algorithm */
63789ed30d1SJens Wiklander 	if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) {
63889ed30d1SJens Wiklander 		res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
63989ed30d1SJens Wiklander 		if (res != TEE_SUCCESS)
64089ed30d1SJens Wiklander 			goto err;
64189ed30d1SJens Wiklander 	}
64289ed30d1SJens Wiklander 
64389ed30d1SJens Wiklander 	switch (algo) {
64489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5:
64589ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1;
64689ed30d1SJens Wiklander 		break;
64789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
64889ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
64989ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
65089ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
65189ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
65289ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
65389ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
65489ed30d1SJens Wiklander 		break;
655*f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
65689ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
65789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
65889ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
65989ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
66089ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
66189ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_PSS;
66289ed30d1SJens Wiklander 		break;
66389ed30d1SJens Wiklander 	default:
66489ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
66589ed30d1SJens Wiklander 		goto err;
66689ed30d1SJens Wiklander 	}
66789ed30d1SJens Wiklander 
6688f6ac972SJens Wiklander 	FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("rsa_verify_hash_ex"));
66989ed30d1SJens Wiklander 	ltc_res = rsa_verify_hash_ex(sig, sig_len, msg, msg_len, ltc_rsa_algo,
67089ed30d1SJens Wiklander 				     ltc_hashindex, salt_len, &stat, &ltc_key);
67189ed30d1SJens Wiklander 	res = convert_ltc_verify_status(ltc_res, stat);
6728f6ac972SJens Wiklander 	if (res)
6738f6ac972SJens Wiklander 		FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res);
6748f6ac972SJens Wiklander 	else
6758f6ac972SJens Wiklander 		FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, 0);
6768f6ac972SJens Wiklander 	FTMN_POP_LINKED_CALL(&ftmn);
6778f6ac972SJens Wiklander 	FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res);
6788f6ac972SJens Wiklander 	return res;
67989ed30d1SJens Wiklander err:
6808f6ac972SJens Wiklander 	FTMN_CALLEE_DONE_NOT_ZERO(res);
68189ed30d1SJens Wiklander 	return res;
68289ed30d1SJens Wiklander }
683