xref: /optee_os/core/lib/libtomcrypt/rsa.c (revision 92e38694f3dbc72402d0b4301b2fb3e46933e6e6)
189ed30d1SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
289ed30d1SJens Wiklander /*
389ed30d1SJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
489ed30d1SJens Wiklander  */
589ed30d1SJens Wiklander 
689ed30d1SJens Wiklander #include <crypto/crypto.h>
789ed30d1SJens Wiklander #include <stdlib.h>
889ed30d1SJens Wiklander #include <string.h>
989ed30d1SJens Wiklander #include <tee_api_types.h>
1089ed30d1SJens Wiklander #include <tee_api_defines_extensions.h>
1189ed30d1SJens Wiklander #include <tee/tee_cryp_utl.h>
1289ed30d1SJens Wiklander #include <trace.h>
1389ed30d1SJens Wiklander #include <utee_defines.h>
1489ed30d1SJens Wiklander 
1589ed30d1SJens Wiklander #include "acipher_helpers.h"
1689ed30d1SJens Wiklander 
1789ed30d1SJens Wiklander 
1889ed30d1SJens Wiklander /*
1989ed30d1SJens Wiklander  * Compute the LibTomCrypt "hashindex" given a TEE Algorithm "algo"
2089ed30d1SJens Wiklander  * Return
2189ed30d1SJens Wiklander  * - TEE_SUCCESS in case of success,
2289ed30d1SJens Wiklander  * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo
2389ed30d1SJens Wiklander  * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC
2489ed30d1SJens Wiklander  * Return -1 in case of error
2589ed30d1SJens Wiklander  */
2689ed30d1SJens Wiklander static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
2789ed30d1SJens Wiklander {
2889ed30d1SJens Wiklander 	switch (algo) {
29a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA1)
3089ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
3189ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
3289ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
3389ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha1");
3489ed30d1SJens Wiklander 		break;
3589ed30d1SJens Wiklander #endif
36a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_MD5)
3789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
3889ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("md5");
3989ed30d1SJens Wiklander 		break;
4089ed30d1SJens Wiklander #endif
41a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA224)
4289ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
4389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
4489ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
4589ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha224");
4689ed30d1SJens Wiklander 		break;
4789ed30d1SJens Wiklander #endif
48a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA256)
4989ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
5089ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
5189ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
5289ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha256");
5389ed30d1SJens Wiklander 		break;
5489ed30d1SJens Wiklander #endif
55a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA384)
5689ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
5789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
5889ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
5989ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha384");
6089ed30d1SJens Wiklander 		break;
6189ed30d1SJens Wiklander #endif
62a1cbb728SJens Wiklander #if defined(_CFG_CORE_LTC_SHA512)
6389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
6489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
6589ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
6689ed30d1SJens Wiklander 		*ltc_hashindex = find_hash("sha512");
6789ed30d1SJens Wiklander 		break;
6889ed30d1SJens Wiklander #endif
6989ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5:
7089ed30d1SJens Wiklander 	case TEE_ALG_RSAES_PKCS1_V1_5:
7189ed30d1SJens Wiklander 		/* invalid one. but it should not be used anyway */
7289ed30d1SJens Wiklander 		*ltc_hashindex = -1;
7389ed30d1SJens Wiklander 		return TEE_SUCCESS;
7489ed30d1SJens Wiklander 
7589ed30d1SJens Wiklander 	default:
7689ed30d1SJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
7789ed30d1SJens Wiklander 	}
7889ed30d1SJens Wiklander 
7989ed30d1SJens Wiklander 	if (*ltc_hashindex < 0)
8089ed30d1SJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
8189ed30d1SJens Wiklander 	else
8289ed30d1SJens Wiklander 		return TEE_SUCCESS;
8389ed30d1SJens Wiklander }
8489ed30d1SJens Wiklander 
8589ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
8689ed30d1SJens Wiklander 					    size_t key_size_bits __unused)
8789ed30d1SJens Wiklander {
8889ed30d1SJens Wiklander 	memset(s, 0, sizeof(*s));
8989ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->e))
9089ed30d1SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
9189ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->d))
9289ed30d1SJens Wiklander 		goto err;
9389ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->n))
9489ed30d1SJens Wiklander 		goto err;
9589ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->p))
9689ed30d1SJens Wiklander 		goto err;
9789ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->q))
9889ed30d1SJens Wiklander 		goto err;
9989ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->qp))
10089ed30d1SJens Wiklander 		goto err;
10189ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->dp))
10289ed30d1SJens Wiklander 		goto err;
10389ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->dq))
10489ed30d1SJens Wiklander 		goto err;
10589ed30d1SJens Wiklander 
10689ed30d1SJens Wiklander 	return TEE_SUCCESS;
10789ed30d1SJens Wiklander err:
108*92e38694SJerome Forissier 	crypto_acipher_free_rsa_keypair(s);
10989ed30d1SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
11089ed30d1SJens Wiklander }
11189ed30d1SJens Wiklander 
11289ed30d1SJens Wiklander TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
11389ed30d1SJens Wiklander 					       size_t key_size_bits __unused)
11489ed30d1SJens Wiklander {
11589ed30d1SJens Wiklander 	memset(s, 0, sizeof(*s));
11689ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->e))
11789ed30d1SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
11889ed30d1SJens Wiklander 	if (!bn_alloc_max(&s->n))
11989ed30d1SJens Wiklander 		goto err;
12089ed30d1SJens Wiklander 	return TEE_SUCCESS;
12189ed30d1SJens Wiklander err:
12289ed30d1SJens Wiklander 	crypto_bignum_free(s->e);
12389ed30d1SJens Wiklander 	return TEE_ERROR_OUT_OF_MEMORY;
12489ed30d1SJens Wiklander }
12589ed30d1SJens Wiklander 
12689ed30d1SJens Wiklander void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
12789ed30d1SJens Wiklander {
12889ed30d1SJens Wiklander 	if (!s)
12989ed30d1SJens Wiklander 		return;
13089ed30d1SJens Wiklander 	crypto_bignum_free(s->n);
13189ed30d1SJens Wiklander 	crypto_bignum_free(s->e);
13289ed30d1SJens Wiklander }
13389ed30d1SJens Wiklander 
134a1d5c81fSElias von Däniken void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
135a1d5c81fSElias von Däniken {
136a1d5c81fSElias von Däniken 	if (!s)
137a1d5c81fSElias von Däniken 		return;
138a1d5c81fSElias von Däniken 	crypto_bignum_free(s->e);
139a1d5c81fSElias von Däniken 	crypto_bignum_free(s->d);
140a1d5c81fSElias von Däniken 	crypto_bignum_free(s->n);
141a1d5c81fSElias von Däniken 	crypto_bignum_free(s->p);
142a1d5c81fSElias von Däniken 	crypto_bignum_free(s->q);
143a1d5c81fSElias von Däniken 	crypto_bignum_free(s->qp);
144a1d5c81fSElias von Däniken 	crypto_bignum_free(s->dp);
14585f7c554SJerome Forissier 	crypto_bignum_free(s->dq);
146a1d5c81fSElias von Däniken }
147a1d5c81fSElias von Däniken 
14889ed30d1SJens Wiklander TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size)
14989ed30d1SJens Wiklander {
15089ed30d1SJens Wiklander 	TEE_Result res;
15189ed30d1SJens Wiklander 	rsa_key ltc_tmp_key;
15289ed30d1SJens Wiklander 	int ltc_res;
15389ed30d1SJens Wiklander 	long e;
15489ed30d1SJens Wiklander 
15589ed30d1SJens Wiklander 	/* get the public exponent */
15689ed30d1SJens Wiklander 	e = mp_get_int(key->e);
15789ed30d1SJens Wiklander 
15889ed30d1SJens Wiklander 	/* Generate a temporary RSA key */
1591f3b1115SJens Wiklander 	ltc_res = rsa_make_key(NULL, find_prng("prng_crypto"), key_size / 8, e,
16089ed30d1SJens Wiklander 			       &ltc_tmp_key);
16189ed30d1SJens Wiklander 	if (ltc_res != CRYPT_OK) {
16289ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
16389ed30d1SJens Wiklander 	} else if ((size_t)mp_count_bits(ltc_tmp_key.N) != key_size) {
16489ed30d1SJens Wiklander 		rsa_free(&ltc_tmp_key);
16589ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
16689ed30d1SJens Wiklander 	} else {
16789ed30d1SJens Wiklander 		/* Copy the key */
16889ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.e,  key->e);
16989ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.d,  key->d);
17089ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.N,  key->n);
17189ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.p,  key->p);
17289ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.q,  key->q);
17389ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.qP, key->qp);
17489ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.dP, key->dp);
17589ed30d1SJens Wiklander 		ltc_mp.copy(ltc_tmp_key.dQ, key->dq);
17689ed30d1SJens Wiklander 
17789ed30d1SJens Wiklander 		/* Free the temporary key */
17889ed30d1SJens Wiklander 		rsa_free(&ltc_tmp_key);
17989ed30d1SJens Wiklander 		res = TEE_SUCCESS;
18089ed30d1SJens Wiklander 	}
18189ed30d1SJens Wiklander 
18289ed30d1SJens Wiklander 	return res;
18389ed30d1SJens Wiklander }
18489ed30d1SJens Wiklander 
18589ed30d1SJens Wiklander static TEE_Result rsadorep(rsa_key *ltc_key, const uint8_t *src,
18689ed30d1SJens Wiklander 			   size_t src_len, uint8_t *dst, size_t *dst_len)
18789ed30d1SJens Wiklander {
18889ed30d1SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
18989ed30d1SJens Wiklander 	uint8_t *buf = NULL;
19089ed30d1SJens Wiklander 	unsigned long blen, offset;
19189ed30d1SJens Wiklander 	int ltc_res;
19289ed30d1SJens Wiklander 
19389ed30d1SJens Wiklander 	/*
19489ed30d1SJens Wiklander 	 * Use a temporary buffer since we don't know exactly how large the
19589ed30d1SJens Wiklander 	 * required size of the out buffer without doing a partial decrypt.
19689ed30d1SJens Wiklander 	 * We know the upper bound though.
19789ed30d1SJens Wiklander 	 */
198a1cbb728SJens Wiklander 	blen = _CFG_CORE_LTC_BIGNUM_MAX_BITS / sizeof(uint8_t);
19989ed30d1SJens Wiklander 	buf = malloc(blen);
20089ed30d1SJens Wiklander 	if (!buf) {
20189ed30d1SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
20289ed30d1SJens Wiklander 		goto out;
20389ed30d1SJens Wiklander 	}
20489ed30d1SJens Wiklander 
20589ed30d1SJens Wiklander 	ltc_res = rsa_exptmod(src, src_len, buf, &blen, ltc_key->type,
20689ed30d1SJens Wiklander 			      ltc_key);
20789ed30d1SJens Wiklander 	switch (ltc_res) {
20889ed30d1SJens Wiklander 	case CRYPT_PK_NOT_PRIVATE:
20989ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_TYPE:
21089ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_SIZE:
21189ed30d1SJens Wiklander 	case CRYPT_INVALID_PACKET:
21289ed30d1SJens Wiklander 		EMSG("rsa_exptmod() returned %d", ltc_res);
21389ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
21489ed30d1SJens Wiklander 		goto out;
21589ed30d1SJens Wiklander 	case CRYPT_OK:
21689ed30d1SJens Wiklander 		break;
21789ed30d1SJens Wiklander 	default:
21889ed30d1SJens Wiklander 		/* This will result in a panic */
21989ed30d1SJens Wiklander 		EMSG("rsa_exptmod() returned %d", ltc_res);
22089ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
22189ed30d1SJens Wiklander 		goto out;
22289ed30d1SJens Wiklander 	}
22389ed30d1SJens Wiklander 
22489ed30d1SJens Wiklander 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
22589ed30d1SJens Wiklander 	offset = 0;
22689ed30d1SJens Wiklander 	while ((offset < blen - 1) && (buf[offset] == 0))
22789ed30d1SJens Wiklander 		offset++;
22889ed30d1SJens Wiklander 
22989ed30d1SJens Wiklander 	if (*dst_len < blen - offset) {
23089ed30d1SJens Wiklander 		*dst_len = blen - offset;
23189ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
23289ed30d1SJens Wiklander 		goto out;
23389ed30d1SJens Wiklander 	}
23489ed30d1SJens Wiklander 
23589ed30d1SJens Wiklander 	res = TEE_SUCCESS;
23689ed30d1SJens Wiklander 	*dst_len = blen - offset;
23789ed30d1SJens Wiklander 	memcpy(dst, (char *)buf + offset, *dst_len);
23889ed30d1SJens Wiklander 
23989ed30d1SJens Wiklander out:
24089ed30d1SJens Wiklander 	if (buf)
24189ed30d1SJens Wiklander 		free(buf);
24289ed30d1SJens Wiklander 
24389ed30d1SJens Wiklander 	return res;
24489ed30d1SJens Wiklander }
24589ed30d1SJens Wiklander 
24689ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
24789ed30d1SJens Wiklander 					   const uint8_t *src, size_t src_len,
24889ed30d1SJens Wiklander 					   uint8_t *dst, size_t *dst_len)
24989ed30d1SJens Wiklander {
25089ed30d1SJens Wiklander 	TEE_Result res;
25189ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
25289ed30d1SJens Wiklander 
25389ed30d1SJens Wiklander 	ltc_key.type = PK_PUBLIC;
25489ed30d1SJens Wiklander 	ltc_key.e = key->e;
25589ed30d1SJens Wiklander 	ltc_key.N = key->n;
25689ed30d1SJens Wiklander 
25789ed30d1SJens Wiklander 	res = rsadorep(&ltc_key, src, src_len, dst, dst_len);
25889ed30d1SJens Wiklander 	return res;
25989ed30d1SJens Wiklander }
26089ed30d1SJens Wiklander 
26189ed30d1SJens Wiklander TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
26289ed30d1SJens Wiklander 					   const uint8_t *src, size_t src_len,
26389ed30d1SJens Wiklander 					   uint8_t *dst, size_t *dst_len)
26489ed30d1SJens Wiklander {
26589ed30d1SJens Wiklander 	TEE_Result res;
26689ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
26789ed30d1SJens Wiklander 
26889ed30d1SJens Wiklander 	ltc_key.type = PK_PRIVATE;
26989ed30d1SJens Wiklander 	ltc_key.e = key->e;
27089ed30d1SJens Wiklander 	ltc_key.N = key->n;
27189ed30d1SJens Wiklander 	ltc_key.d = key->d;
27289ed30d1SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
27389ed30d1SJens Wiklander 		ltc_key.p = key->p;
27489ed30d1SJens Wiklander 		ltc_key.q = key->q;
27589ed30d1SJens Wiklander 		ltc_key.qP = key->qp;
27689ed30d1SJens Wiklander 		ltc_key.dP = key->dp;
27789ed30d1SJens Wiklander 		ltc_key.dQ = key->dq;
27889ed30d1SJens Wiklander 	}
27989ed30d1SJens Wiklander 
28089ed30d1SJens Wiklander 	res = rsadorep(&ltc_key, src, src_len, dst, dst_len);
28189ed30d1SJens Wiklander 	return res;
28289ed30d1SJens Wiklander }
28389ed30d1SJens Wiklander 
28489ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key,
28589ed30d1SJens Wiklander 					const uint8_t *label, size_t label_len,
28689ed30d1SJens Wiklander 					const uint8_t *src, size_t src_len,
28789ed30d1SJens Wiklander 					uint8_t *dst, size_t *dst_len)
28889ed30d1SJens Wiklander {
28989ed30d1SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
29089ed30d1SJens Wiklander 	void *buf = NULL;
29189ed30d1SJens Wiklander 	unsigned long blen;
29289ed30d1SJens Wiklander 	int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo;
29389ed30d1SJens Wiklander 	size_t mod_size;
29489ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
29589ed30d1SJens Wiklander 
29689ed30d1SJens Wiklander 	ltc_key.type = PK_PRIVATE;
29789ed30d1SJens Wiklander 	ltc_key.e = key->e;
29889ed30d1SJens Wiklander 	ltc_key.d = key->d;
29989ed30d1SJens Wiklander 	ltc_key.N = key->n;
30089ed30d1SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
30189ed30d1SJens Wiklander 		ltc_key.p = key->p;
30289ed30d1SJens Wiklander 		ltc_key.q = key->q;
30389ed30d1SJens Wiklander 		ltc_key.qP = key->qp;
30489ed30d1SJens Wiklander 		ltc_key.dP = key->dp;
30589ed30d1SJens Wiklander 		ltc_key.dQ = key->dq;
30689ed30d1SJens Wiklander 	}
30789ed30d1SJens Wiklander 
30889ed30d1SJens Wiklander 	/* Get the algorithm */
30989ed30d1SJens Wiklander 	res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
31089ed30d1SJens Wiklander 	if (res != TEE_SUCCESS) {
31189ed30d1SJens Wiklander 		EMSG("tee_algo_to_ltc_hashindex() returned %d", (int)res);
31289ed30d1SJens Wiklander 		goto out;
31389ed30d1SJens Wiklander 	}
31489ed30d1SJens Wiklander 
31589ed30d1SJens Wiklander 	/*
31689ed30d1SJens Wiklander 	 * Use a temporary buffer since we don't know exactly how large
31789ed30d1SJens Wiklander 	 * the required size of the out buffer without doing a partial
31889ed30d1SJens Wiklander 	 * decrypt. We know the upper bound though.
31989ed30d1SJens Wiklander 	 */
32089ed30d1SJens Wiklander 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
32189ed30d1SJens Wiklander 		mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N));
32289ed30d1SJens Wiklander 		blen = mod_size - 11;
32389ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
32489ed30d1SJens Wiklander 	} else {
32589ed30d1SJens Wiklander 		/* Decoded message is always shorter than encrypted message */
32689ed30d1SJens Wiklander 		blen = src_len;
32789ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_OAEP;
32889ed30d1SJens Wiklander 	}
32989ed30d1SJens Wiklander 
33089ed30d1SJens Wiklander 	buf = malloc(blen);
33189ed30d1SJens Wiklander 	if (!buf) {
33289ed30d1SJens Wiklander 		res = TEE_ERROR_OUT_OF_MEMORY;
33389ed30d1SJens Wiklander 		goto out;
33489ed30d1SJens Wiklander 	}
33589ed30d1SJens Wiklander 
33689ed30d1SJens Wiklander 	ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen,
33789ed30d1SJens Wiklander 				     ((label_len == 0) ? 0 : label), label_len,
33889ed30d1SJens Wiklander 				     ltc_hashindex, ltc_rsa_algo, &ltc_stat,
33989ed30d1SJens Wiklander 				     &ltc_key);
34089ed30d1SJens Wiklander 	switch (ltc_res) {
34189ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_PADDING:
34289ed30d1SJens Wiklander 	case CRYPT_INVALID_PACKET:
34389ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_SIZE:
34489ed30d1SJens Wiklander 		EMSG("rsa_decrypt_key_ex() returned %d", ltc_res);
34589ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
34689ed30d1SJens Wiklander 		goto out;
34789ed30d1SJens Wiklander 	case CRYPT_OK:
34889ed30d1SJens Wiklander 		break;
34989ed30d1SJens Wiklander 	default:
35089ed30d1SJens Wiklander 		/* This will result in a panic */
35189ed30d1SJens Wiklander 		EMSG("rsa_decrypt_key_ex() returned %d", ltc_res);
35289ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
35389ed30d1SJens Wiklander 		goto out;
35489ed30d1SJens Wiklander 	}
35589ed30d1SJens Wiklander 	if (ltc_stat != 1) {
35689ed30d1SJens Wiklander 		/* This will result in a panic */
35789ed30d1SJens Wiklander 		EMSG("rsa_decrypt_key_ex() returned %d and %d",
35889ed30d1SJens Wiklander 		     ltc_res, ltc_stat);
35989ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
36089ed30d1SJens Wiklander 		goto out;
36189ed30d1SJens Wiklander 	}
36289ed30d1SJens Wiklander 
36389ed30d1SJens Wiklander 	if (*dst_len < blen) {
36489ed30d1SJens Wiklander 		*dst_len = blen;
36589ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
36689ed30d1SJens Wiklander 		goto out;
36789ed30d1SJens Wiklander 	}
36889ed30d1SJens Wiklander 
36989ed30d1SJens Wiklander 	res = TEE_SUCCESS;
37089ed30d1SJens Wiklander 	*dst_len = blen;
37189ed30d1SJens Wiklander 	memcpy(dst, buf, blen);
37289ed30d1SJens Wiklander 
37389ed30d1SJens Wiklander out:
37489ed30d1SJens Wiklander 	if (buf)
37589ed30d1SJens Wiklander 		free(buf);
37689ed30d1SJens Wiklander 
37789ed30d1SJens Wiklander 	return res;
37889ed30d1SJens Wiklander }
37989ed30d1SJens Wiklander 
38089ed30d1SJens Wiklander TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
38189ed30d1SJens Wiklander 					struct rsa_public_key *key,
38289ed30d1SJens Wiklander 					const uint8_t *label, size_t label_len,
38389ed30d1SJens Wiklander 					const uint8_t *src, size_t src_len,
38489ed30d1SJens Wiklander 					uint8_t *dst, size_t *dst_len)
38589ed30d1SJens Wiklander {
38689ed30d1SJens Wiklander 	TEE_Result res;
38789ed30d1SJens Wiklander 	uint32_t mod_size;
38889ed30d1SJens Wiklander 	int ltc_hashindex, ltc_res, ltc_rsa_algo;
38989ed30d1SJens Wiklander 	rsa_key ltc_key = {
39089ed30d1SJens Wiklander 		.type = PK_PUBLIC,
39189ed30d1SJens Wiklander 		.e = key->e,
39289ed30d1SJens Wiklander 		.N = key->n
39389ed30d1SJens Wiklander 	};
39489ed30d1SJens Wiklander 
39589ed30d1SJens Wiklander 	mod_size =  ltc_mp.unsigned_size((void *)(ltc_key.N));
39689ed30d1SJens Wiklander 	if (*dst_len < mod_size) {
39789ed30d1SJens Wiklander 		*dst_len = mod_size;
39889ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
39989ed30d1SJens Wiklander 		goto out;
40089ed30d1SJens Wiklander 	}
40189ed30d1SJens Wiklander 	*dst_len = mod_size;
40289ed30d1SJens Wiklander 
40389ed30d1SJens Wiklander 	/* Get the algorithm */
40489ed30d1SJens Wiklander 	res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
40589ed30d1SJens Wiklander 	if (res != TEE_SUCCESS)
40689ed30d1SJens Wiklander 		goto out;
40789ed30d1SJens Wiklander 
40889ed30d1SJens Wiklander 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
40989ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
41089ed30d1SJens Wiklander 	else
41189ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_OAEP;
41289ed30d1SJens Wiklander 
41389ed30d1SJens Wiklander 	ltc_res = rsa_encrypt_key_ex(src, src_len, dst,
41489ed30d1SJens Wiklander 				     (unsigned long *)(dst_len), label,
4151f3b1115SJens Wiklander 				     label_len, NULL, find_prng("prng_crypto"),
41689ed30d1SJens Wiklander 				     ltc_hashindex, ltc_rsa_algo, &ltc_key);
41789ed30d1SJens Wiklander 	switch (ltc_res) {
41889ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_PADDING:
41989ed30d1SJens Wiklander 	case CRYPT_INVALID_PACKET:
42089ed30d1SJens Wiklander 	case CRYPT_PK_INVALID_SIZE:
42189ed30d1SJens Wiklander 		EMSG("rsa_encrypt_key_ex() returned %d", ltc_res);
42289ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
42389ed30d1SJens Wiklander 		goto out;
42489ed30d1SJens Wiklander 	case CRYPT_OK:
42589ed30d1SJens Wiklander 		break;
42689ed30d1SJens Wiklander 	default:
42789ed30d1SJens Wiklander 		/* This will result in a panic */
42889ed30d1SJens Wiklander 		res = TEE_ERROR_GENERIC;
42989ed30d1SJens Wiklander 		goto out;
43089ed30d1SJens Wiklander 	}
43189ed30d1SJens Wiklander 	res = TEE_SUCCESS;
43289ed30d1SJens Wiklander 
43389ed30d1SJens Wiklander out:
43489ed30d1SJens Wiklander 	return res;
43589ed30d1SJens Wiklander }
43689ed30d1SJens Wiklander 
43789ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
43889ed30d1SJens Wiklander 				      int salt_len, const uint8_t *msg,
43989ed30d1SJens Wiklander 				      size_t msg_len, uint8_t *sig,
44089ed30d1SJens Wiklander 				      size_t *sig_len)
44189ed30d1SJens Wiklander {
44289ed30d1SJens Wiklander 	TEE_Result res;
44389ed30d1SJens Wiklander 	size_t hash_size, mod_size;
44489ed30d1SJens Wiklander 	int ltc_res, ltc_rsa_algo, ltc_hashindex;
44589ed30d1SJens Wiklander 	unsigned long ltc_sig_len;
44689ed30d1SJens Wiklander 	rsa_key ltc_key = { 0, };
44789ed30d1SJens Wiklander 
44889ed30d1SJens Wiklander 	ltc_key.type = PK_PRIVATE;
44989ed30d1SJens Wiklander 	ltc_key.e = key->e;
45089ed30d1SJens Wiklander 	ltc_key.N = key->n;
45189ed30d1SJens Wiklander 	ltc_key.d = key->d;
45289ed30d1SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
45389ed30d1SJens Wiklander 		ltc_key.p = key->p;
45489ed30d1SJens Wiklander 		ltc_key.q = key->q;
45589ed30d1SJens Wiklander 		ltc_key.qP = key->qp;
45689ed30d1SJens Wiklander 		ltc_key.dP = key->dp;
45789ed30d1SJens Wiklander 		ltc_key.dQ = key->dq;
45889ed30d1SJens Wiklander 	}
45989ed30d1SJens Wiklander 
46089ed30d1SJens Wiklander 	switch (algo) {
46189ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5:
46289ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1;
46389ed30d1SJens Wiklander 		break;
46489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
46589ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
46689ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
46789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
46889ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
46989ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
47089ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
47189ed30d1SJens Wiklander 		break;
47289ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
47389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
47489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
47589ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
47689ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
47789ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_PSS;
47889ed30d1SJens Wiklander 		break;
47989ed30d1SJens Wiklander 	default:
48089ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
48189ed30d1SJens Wiklander 		goto err;
48289ed30d1SJens Wiklander 	}
48389ed30d1SJens Wiklander 
48489ed30d1SJens Wiklander 	if (ltc_rsa_algo != LTC_PKCS_1_V1_5_NA1) {
48589ed30d1SJens Wiklander 		ltc_res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
48689ed30d1SJens Wiklander 		if (ltc_res != CRYPT_OK) {
48789ed30d1SJens Wiklander 			res = TEE_ERROR_BAD_PARAMETERS;
48889ed30d1SJens Wiklander 			goto err;
48989ed30d1SJens Wiklander 		}
49089ed30d1SJens Wiklander 
4917c767434SAlbert Schwarzkopf 		res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
49289ed30d1SJens Wiklander 					      &hash_size);
49389ed30d1SJens Wiklander 		if (res != TEE_SUCCESS)
49489ed30d1SJens Wiklander 			goto err;
49589ed30d1SJens Wiklander 
49689ed30d1SJens Wiklander 		if (msg_len != hash_size) {
49789ed30d1SJens Wiklander 			res = TEE_ERROR_BAD_PARAMETERS;
49889ed30d1SJens Wiklander 			goto err;
49989ed30d1SJens Wiklander 		}
50089ed30d1SJens Wiklander 	}
50189ed30d1SJens Wiklander 
50289ed30d1SJens Wiklander 	mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N));
50389ed30d1SJens Wiklander 
50489ed30d1SJens Wiklander 	if (*sig_len < mod_size) {
50589ed30d1SJens Wiklander 		*sig_len = mod_size;
50689ed30d1SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
50789ed30d1SJens Wiklander 		goto err;
50889ed30d1SJens Wiklander 	}
50989ed30d1SJens Wiklander 
51089ed30d1SJens Wiklander 	ltc_sig_len = mod_size;
51189ed30d1SJens Wiklander 
51289ed30d1SJens Wiklander 	ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, &ltc_sig_len,
5131f3b1115SJens Wiklander 				   ltc_rsa_algo, NULL, find_prng("prng_crypto"),
51489ed30d1SJens Wiklander 				   ltc_hashindex, salt_len, &ltc_key);
51589ed30d1SJens Wiklander 
51689ed30d1SJens Wiklander 	*sig_len = ltc_sig_len;
51789ed30d1SJens Wiklander 
51889ed30d1SJens Wiklander 	if (ltc_res != CRYPT_OK) {
51989ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
52089ed30d1SJens Wiklander 		goto err;
52189ed30d1SJens Wiklander 	}
52289ed30d1SJens Wiklander 	res = TEE_SUCCESS;
52389ed30d1SJens Wiklander 
52489ed30d1SJens Wiklander err:
52589ed30d1SJens Wiklander 	return res;
52689ed30d1SJens Wiklander }
52789ed30d1SJens Wiklander 
52889ed30d1SJens Wiklander TEE_Result crypto_acipher_rsassa_verify(uint32_t algo,
52989ed30d1SJens Wiklander 					struct rsa_public_key *key,
53089ed30d1SJens Wiklander 					int salt_len, const uint8_t *msg,
53189ed30d1SJens Wiklander 					size_t msg_len, const uint8_t *sig,
53289ed30d1SJens Wiklander 					size_t sig_len)
53389ed30d1SJens Wiklander {
53489ed30d1SJens Wiklander 	TEE_Result res;
53589ed30d1SJens Wiklander 	uint32_t bigint_size;
53689ed30d1SJens Wiklander 	size_t hash_size;
53789ed30d1SJens Wiklander 	int stat, ltc_hashindex, ltc_res, ltc_rsa_algo;
53889ed30d1SJens Wiklander 	rsa_key ltc_key = {
53989ed30d1SJens Wiklander 		.type = PK_PUBLIC,
54089ed30d1SJens Wiklander 		.e = key->e,
54189ed30d1SJens Wiklander 		.N = key->n
54289ed30d1SJens Wiklander 	};
54389ed30d1SJens Wiklander 
54489ed30d1SJens Wiklander 	if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) {
5457c767434SAlbert Schwarzkopf 		res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
54689ed30d1SJens Wiklander 					      &hash_size);
54789ed30d1SJens Wiklander 		if (res != TEE_SUCCESS)
54889ed30d1SJens Wiklander 			goto err;
54989ed30d1SJens Wiklander 
55089ed30d1SJens Wiklander 		if (msg_len != hash_size) {
55189ed30d1SJens Wiklander 			res = TEE_ERROR_BAD_PARAMETERS;
55289ed30d1SJens Wiklander 			goto err;
55389ed30d1SJens Wiklander 		}
55489ed30d1SJens Wiklander 	}
55589ed30d1SJens Wiklander 
55689ed30d1SJens Wiklander 	bigint_size = ltc_mp.unsigned_size(ltc_key.N);
55789ed30d1SJens Wiklander 	if (sig_len < bigint_size) {
55889ed30d1SJens Wiklander 		res = TEE_ERROR_SIGNATURE_INVALID;
55989ed30d1SJens Wiklander 		goto err;
56089ed30d1SJens Wiklander 	}
56189ed30d1SJens Wiklander 
56289ed30d1SJens Wiklander 	/* Get the algorithm */
56389ed30d1SJens Wiklander 	if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) {
56489ed30d1SJens Wiklander 		res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
56589ed30d1SJens Wiklander 		if (res != TEE_SUCCESS)
56689ed30d1SJens Wiklander 			goto err;
56789ed30d1SJens Wiklander 	}
56889ed30d1SJens Wiklander 
56989ed30d1SJens Wiklander 	switch (algo) {
57089ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5:
57189ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1;
57289ed30d1SJens Wiklander 		break;
57389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
57489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
57589ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
57689ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
57789ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
57889ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
57989ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
58089ed30d1SJens Wiklander 		break;
58189ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
58289ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
58389ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
58489ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
58589ed30d1SJens Wiklander 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
58689ed30d1SJens Wiklander 		ltc_rsa_algo = LTC_PKCS_1_PSS;
58789ed30d1SJens Wiklander 		break;
58889ed30d1SJens Wiklander 	default:
58989ed30d1SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
59089ed30d1SJens Wiklander 		goto err;
59189ed30d1SJens Wiklander 	}
59289ed30d1SJens Wiklander 
59389ed30d1SJens Wiklander 	ltc_res = rsa_verify_hash_ex(sig, sig_len, msg, msg_len, ltc_rsa_algo,
59489ed30d1SJens Wiklander 				     ltc_hashindex, salt_len, &stat, &ltc_key);
59589ed30d1SJens Wiklander 	res = convert_ltc_verify_status(ltc_res, stat);
59689ed30d1SJens Wiklander err:
59789ed30d1SJens Wiklander 	return res;
59889ed30d1SJens Wiklander }
599