xref: /optee_os/lib/libmbedtls/core/rsa.c (revision b0563631928755fe864b97785160fb3088e9efdc)
1f8907bbfSEdison Ai // SPDX-License-Identifier: BSD-2-Clause
2f8907bbfSEdison Ai /*
3f8907bbfSEdison Ai  * Copyright (C) 2018, ARM Limited
4f8907bbfSEdison Ai  * Copyright (C) 2019, Linaro Limited
5f8907bbfSEdison Ai  */
6f8907bbfSEdison Ai 
7f8907bbfSEdison Ai #include <assert.h>
8f8907bbfSEdison Ai #include <crypto/crypto.h>
9eac16613SJorge Ramirez-Ortiz #include <crypto/crypto_impl.h>
10f8907bbfSEdison Ai #include <mbedtls/ctr_drbg.h>
11f8907bbfSEdison Ai #include <mbedtls/entropy.h>
12f8907bbfSEdison Ai #include <mbedtls/pk.h>
13f8907bbfSEdison Ai #include <stdlib.h>
14f8907bbfSEdison Ai #include <string.h>
15f8907bbfSEdison Ai #include <tee/tee_cryp_utl.h>
16f8907bbfSEdison Ai #include <utee_defines.h>
1798ada65eSJens Wiklander #include <fault_mitigation.h>
18f8907bbfSEdison Ai 
196630b846SJerome Forissier #include "mbed_helpers.h"
2032b31808SJens Wiklander #include "../mbedtls/library/pk_wrap.h"
2132b31808SJens Wiklander #include "../mbedtls/library/rsa_alt_helpers.h"
22f8907bbfSEdison Ai 
get_tee_result(int lmd_res)23f8907bbfSEdison Ai static TEE_Result get_tee_result(int lmd_res)
24f8907bbfSEdison Ai {
25f8907bbfSEdison Ai 	switch (lmd_res) {
26f8907bbfSEdison Ai 	case 0:
27f8907bbfSEdison Ai 		return TEE_SUCCESS;
283ddd5cd7Sliushiwei 	case MBEDTLS_ERR_RSA_PRIVATE_FAILED +
293ddd5cd7Sliushiwei 		MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
30f8907bbfSEdison Ai 	case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:
31f8907bbfSEdison Ai 	case MBEDTLS_ERR_RSA_INVALID_PADDING:
32f8907bbfSEdison Ai 	case MBEDTLS_ERR_PK_TYPE_MISMATCH:
33f8907bbfSEdison Ai 		return TEE_ERROR_BAD_PARAMETERS;
34f8907bbfSEdison Ai 	case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
35f8907bbfSEdison Ai 		return TEE_ERROR_SHORT_BUFFER;
36f8907bbfSEdison Ai 	default:
37f8907bbfSEdison Ai 		return TEE_ERROR_BAD_STATE;
38f8907bbfSEdison Ai 	}
39f8907bbfSEdison Ai }
40f8907bbfSEdison Ai 
tee_algo_to_mbedtls_hash_algo(uint32_t algo)41f8907bbfSEdison Ai static uint32_t tee_algo_to_mbedtls_hash_algo(uint32_t algo)
42f8907bbfSEdison Ai {
43f8907bbfSEdison Ai 	switch (algo) {
44f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA1)
45f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
46f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
47f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
48f8907bbfSEdison Ai 	case TEE_ALG_SHA1:
49f8907bbfSEdison Ai 	case TEE_ALG_DSA_SHA1:
50f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA1:
51f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA1;
52f8907bbfSEdison Ai #endif
53f8907bbfSEdison Ai #if defined(CFG_CRYPTO_MD5)
54f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
55f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
56f5c3d85aSJulien Masson 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5:
57f8907bbfSEdison Ai 	case TEE_ALG_MD5:
58f8907bbfSEdison Ai 	case TEE_ALG_HMAC_MD5:
59f8907bbfSEdison Ai 		return MBEDTLS_MD_MD5;
60f8907bbfSEdison Ai #endif
61f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA224)
62f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
63f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
64f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
65f8907bbfSEdison Ai 	case TEE_ALG_SHA224:
66f8907bbfSEdison Ai 	case TEE_ALG_DSA_SHA224:
67f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA224:
68f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA224;
69f8907bbfSEdison Ai #endif
70f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA256)
71f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
72f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
73f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
74f8907bbfSEdison Ai 	case TEE_ALG_SHA256:
75f8907bbfSEdison Ai 	case TEE_ALG_DSA_SHA256:
76f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA256:
77f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA256;
78f8907bbfSEdison Ai #endif
79f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA384)
80f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
81f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
82f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
83f8907bbfSEdison Ai 	case TEE_ALG_SHA384:
84f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA384:
85f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA384;
86f8907bbfSEdison Ai #endif
87f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA512)
88f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
89f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
90f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
91f8907bbfSEdison Ai 	case TEE_ALG_SHA512:
92f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA512:
93f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA512;
94f8907bbfSEdison Ai #endif
95f8907bbfSEdison Ai 	default:
96f8907bbfSEdison Ai 		return MBEDTLS_MD_NONE;
97f8907bbfSEdison Ai 	}
98f8907bbfSEdison Ai }
99f8907bbfSEdison Ai 
rsa_complete_from_key_pair(mbedtls_rsa_context * rsa,struct rsa_keypair * key)100*b0563631STom Van Eyck static TEE_Result rsa_complete_from_key_pair(mbedtls_rsa_context *rsa,
101f8907bbfSEdison Ai 						      struct rsa_keypair *key)
102f8907bbfSEdison Ai {
10332b31808SJens Wiklander 	int lmd_res = 0;
10432b31808SJens Wiklander 
105f8907bbfSEdison Ai 	rsa->E = *(mbedtls_mpi *)key->e;
106f8907bbfSEdison Ai 	rsa->N = *(mbedtls_mpi *)key->n;
107f8907bbfSEdison Ai 	rsa->D = *(mbedtls_mpi *)key->d;
10832b31808SJens Wiklander 	rsa->len = mbedtls_mpi_size(&rsa->N);
10932b31808SJens Wiklander 
110f8907bbfSEdison Ai 	if (key->p && crypto_bignum_num_bytes(key->p)) {
111f8907bbfSEdison Ai 		rsa->P = *(mbedtls_mpi *)key->p;
112f8907bbfSEdison Ai 		rsa->Q = *(mbedtls_mpi *)key->q;
113f8907bbfSEdison Ai 		rsa->QP = *(mbedtls_mpi *)key->qp;
114f8907bbfSEdison Ai 		rsa->DP = *(mbedtls_mpi *)key->dp;
115f8907bbfSEdison Ai 		rsa->DQ = *(mbedtls_mpi *)key->dq;
11632b31808SJens Wiklander 	} else {
11732b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->P);
11832b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->Q);
11932b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->QP);
12032b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->DP);
12132b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->DQ);
12232b31808SJens Wiklander 
12332b31808SJens Wiklander 		lmd_res = mbedtls_rsa_deduce_primes(&rsa->N, &rsa->E, &rsa->D,
12432b31808SJens Wiklander 						    &rsa->P, &rsa->Q);
12532b31808SJens Wiklander 		if (lmd_res) {
12632b31808SJens Wiklander 			DMSG("mbedtls_rsa_deduce_primes() returned 0x%x",
12732b31808SJens Wiklander 			     -lmd_res);
12832b31808SJens Wiklander 			goto err;
129f8907bbfSEdison Ai 		}
130f8907bbfSEdison Ai 
13132b31808SJens Wiklander 		lmd_res = mbedtls_rsa_deduce_crt(&rsa->P, &rsa->Q, &rsa->D,
13232b31808SJens Wiklander 						 &rsa->DP, &rsa->DQ, &rsa->QP);
13332b31808SJens Wiklander 		if (lmd_res) {
13432b31808SJens Wiklander 			DMSG("mbedtls_rsa_deduce_crt() returned 0x%x",
13532b31808SJens Wiklander 			     -lmd_res);
13632b31808SJens Wiklander 			goto err;
13732b31808SJens Wiklander 		}
13832b31808SJens Wiklander 	}
13932b31808SJens Wiklander 
14032b31808SJens Wiklander 	return TEE_SUCCESS;
14132b31808SJens Wiklander err:
14232b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->P);
14332b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->Q);
14432b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->QP);
14532b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->DP);
14632b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->DQ);
14732b31808SJens Wiklander 
14832b31808SJens Wiklander 	return get_tee_result(lmd_res);
14932b31808SJens Wiklander }
15032b31808SJens Wiklander 
rsa_init_and_complete_from_key_pair(mbedtls_rsa_context * rsa,struct rsa_keypair * key)151*b0563631STom Van Eyck static TEE_Result rsa_init_and_complete_from_key_pair(mbedtls_rsa_context *rsa,
152*b0563631STom Van Eyck 						      struct rsa_keypair *key)
153*b0563631STom Van Eyck {
154*b0563631STom Van Eyck 	mbedtls_rsa_init(rsa);
155*b0563631STom Van Eyck 
156*b0563631STom Van Eyck 	return rsa_complete_from_key_pair(rsa, key);
157*b0563631STom Van Eyck }
158*b0563631STom Van Eyck 
mbd_rsa_free(mbedtls_rsa_context * rsa,struct rsa_keypair * key)15932b31808SJens Wiklander static void mbd_rsa_free(mbedtls_rsa_context *rsa, struct rsa_keypair *key)
160f8907bbfSEdison Ai {
16132b31808SJens Wiklander 	/*
16232b31808SJens Wiklander 	 * The mpi's in @rsa are initialized from @key, but the primes and
16332b31808SJens Wiklander 	 * CRT part are generated if @key doesn't have them. When freeing
16432b31808SJens Wiklander 	 * we should only free the generated mpi's, the ones copied are
16532b31808SJens Wiklander 	 * reset instead.
16632b31808SJens Wiklander 	 */
167f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->E);
168f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->N);
169f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->D);
17032b31808SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
171f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->P);
172f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->Q);
173f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->QP);
174f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->DP);
175f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->DQ);
176f8907bbfSEdison Ai 	}
177f8907bbfSEdison Ai 	mbedtls_rsa_free(rsa);
178f8907bbfSEdison Ai }
179f8907bbfSEdison Ai 
mbd_pk_free(mbedtls_pk_context * ctx,struct rsa_keypair * key)180*b0563631STom Van Eyck static void mbd_pk_free(mbedtls_pk_context *ctx, struct rsa_keypair *key)
181*b0563631STom Van Eyck {
182*b0563631STom Van Eyck 	mbedtls_rsa_context *rsa = ctx->pk_ctx;
183*b0563631STom Van Eyck 
184*b0563631STom Van Eyck 	/*
185*b0563631STom Van Eyck 	 * Executing mbedtls_rsa_free twice is fine, as it does nothing if its
186*b0563631STom Van Eyck 	 * argument is NULL.
187*b0563631STom Van Eyck 	 */
188*b0563631STom Van Eyck 	mbd_rsa_free(rsa, key);
189*b0563631STom Van Eyck 	mbedtls_pk_free(ctx);
190*b0563631STom Van Eyck }
191*b0563631STom Van Eyck 
192f8907bbfSEdison Ai TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
193f8907bbfSEdison Ai 					    size_t key_size_bits)
194eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_keypair");
195eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair * s,size_t key_size_bits)196eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
197eac16613SJorge Ramirez-Ortiz 					       size_t key_size_bits)
198f8907bbfSEdison Ai {
199f8907bbfSEdison Ai 	memset(s, 0, sizeof(*s));
200f8907bbfSEdison Ai 	s->e = crypto_bignum_allocate(key_size_bits);
201f8907bbfSEdison Ai 	if (!s->e)
202f8907bbfSEdison Ai 		goto err;
203f8907bbfSEdison Ai 	s->d = crypto_bignum_allocate(key_size_bits);
204f8907bbfSEdison Ai 	if (!s->d)
205f8907bbfSEdison Ai 		goto err;
206f8907bbfSEdison Ai 	s->n = crypto_bignum_allocate(key_size_bits);
207f8907bbfSEdison Ai 	if (!s->n)
208f8907bbfSEdison Ai 		goto err;
209f8907bbfSEdison Ai 	s->p = crypto_bignum_allocate(key_size_bits);
210f8907bbfSEdison Ai 	if (!s->p)
211f8907bbfSEdison Ai 		goto err;
212f8907bbfSEdison Ai 	s->q = crypto_bignum_allocate(key_size_bits);
213f8907bbfSEdison Ai 	if (!s->q)
214f8907bbfSEdison Ai 		goto err;
215f8907bbfSEdison Ai 	s->qp = crypto_bignum_allocate(key_size_bits);
216f8907bbfSEdison Ai 	if (!s->qp)
217f8907bbfSEdison Ai 		goto err;
218f8907bbfSEdison Ai 	s->dp = crypto_bignum_allocate(key_size_bits);
219f8907bbfSEdison Ai 	if (!s->dp)
220f8907bbfSEdison Ai 		goto err;
221f8907bbfSEdison Ai 	s->dq = crypto_bignum_allocate(key_size_bits);
222f8907bbfSEdison Ai 	if (!s->dq)
223f8907bbfSEdison Ai 		goto err;
224f8907bbfSEdison Ai 
225f8907bbfSEdison Ai 	return TEE_SUCCESS;
226f8907bbfSEdison Ai err:
2271ab1ebd8SJerome Forissier 	crypto_acipher_free_rsa_keypair(s);
228f8907bbfSEdison Ai 	return TEE_ERROR_OUT_OF_MEMORY;
229f8907bbfSEdison Ai }
230f8907bbfSEdison Ai 
231f8907bbfSEdison Ai TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
232f8907bbfSEdison Ai 					       size_t key_size_bits)
233eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_public_key");
234eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key * s,size_t key_size_bits)235eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
236eac16613SJorge Ramirez-Ortiz 						  size_t key_size_bits)
237f8907bbfSEdison Ai {
238f8907bbfSEdison Ai 	memset(s, 0, sizeof(*s));
239f8907bbfSEdison Ai 	s->e = crypto_bignum_allocate(key_size_bits);
240f8907bbfSEdison Ai 	if (!s->e)
241f8907bbfSEdison Ai 		return TEE_ERROR_OUT_OF_MEMORY;
242f8907bbfSEdison Ai 	s->n = crypto_bignum_allocate(key_size_bits);
243f8907bbfSEdison Ai 	if (!s->n)
244f8907bbfSEdison Ai 		goto err;
245f8907bbfSEdison Ai 	return TEE_SUCCESS;
246f8907bbfSEdison Ai err:
247e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
248f8907bbfSEdison Ai 	return TEE_ERROR_OUT_OF_MEMORY;
249f8907bbfSEdison Ai }
250f8907bbfSEdison Ai 
251f8907bbfSEdison Ai void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
252eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_public_key");
253eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key * s)254eac16613SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
255f8907bbfSEdison Ai {
256f8907bbfSEdison Ai 	if (!s)
257f8907bbfSEdison Ai 		return;
258e2ec831cSJihwan Park 	crypto_bignum_free(&s->n);
259e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
260f8907bbfSEdison Ai }
261f8907bbfSEdison Ai 
262a1d5c81fSElias von Däniken void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
263eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_keypair");
264eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair * s)265eac16613SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
266a1d5c81fSElias von Däniken {
267a1d5c81fSElias von Däniken 	if (!s)
268a1d5c81fSElias von Däniken 		return;
269e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
270e2ec831cSJihwan Park 	crypto_bignum_free(&s->d);
271e2ec831cSJihwan Park 	crypto_bignum_free(&s->n);
272e2ec831cSJihwan Park 	crypto_bignum_free(&s->p);
273e2ec831cSJihwan Park 	crypto_bignum_free(&s->q);
274e2ec831cSJihwan Park 	crypto_bignum_free(&s->qp);
275e2ec831cSJihwan Park 	crypto_bignum_free(&s->dp);
276e2ec831cSJihwan Park 	crypto_bignum_free(&s->dq);
277a1d5c81fSElias von Däniken }
278a1d5c81fSElias von Däniken 
279eac16613SJorge Ramirez-Ortiz TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
280eac16613SJorge Ramirez-Ortiz 				      size_t key_size)
281eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_gen_rsa_key");
282eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_gen_rsa_key(struct rsa_keypair * key,size_t key_size)283eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
284eac16613SJorge Ramirez-Ortiz 					 size_t key_size)
285f8907bbfSEdison Ai {
286f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
287f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
2887910f4d8SLars Persson 	mbedtls_ctr_drbg_context rngctx;
289f8907bbfSEdison Ai 	int lmd_res = 0;
290f8907bbfSEdison Ai 	uint32_t e = 0;
291f8907bbfSEdison Ai 
2927910f4d8SLars Persson 	mbedtls_ctr_drbg_init(&rngctx);
2937910f4d8SLars Persson 	if (mbedtls_ctr_drbg_seed(&rngctx, mbd_rand, NULL, NULL, 0))
2947910f4d8SLars Persson 		return TEE_ERROR_BAD_STATE;
2957910f4d8SLars Persson 
296f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
29732b31808SJens Wiklander 	mbedtls_rsa_init(&rsa);
298f8907bbfSEdison Ai 
299f8907bbfSEdison Ai 	/* get the public exponent */
300f8907bbfSEdison Ai 	mbedtls_mpi_write_binary((mbedtls_mpi *)key->e,
301f8907bbfSEdison Ai 				 (unsigned char *)&e, sizeof(uint32_t));
302f8907bbfSEdison Ai 
303f8907bbfSEdison Ai 	e = TEE_U32_FROM_BIG_ENDIAN(e);
3047910f4d8SLars Persson 	lmd_res = mbedtls_rsa_gen_key(&rsa, mbedtls_ctr_drbg_random, &rngctx,
3057910f4d8SLars Persson 				      key_size, (int)e);
3067910f4d8SLars Persson 	mbedtls_ctr_drbg_free(&rngctx);
307f8907bbfSEdison Ai 	if (lmd_res != 0) {
308f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
309f8907bbfSEdison Ai 	} else if ((size_t)mbedtls_mpi_bitlen(&rsa.N) != key_size) {
310f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
311f8907bbfSEdison Ai 	} else {
312f8907bbfSEdison Ai 		/* Copy the key */
313f8907bbfSEdison Ai 		crypto_bignum_copy(key->e, (void *)&rsa.E);
314f8907bbfSEdison Ai 		crypto_bignum_copy(key->d, (void *)&rsa.D);
315f8907bbfSEdison Ai 		crypto_bignum_copy(key->n, (void *)&rsa.N);
316f8907bbfSEdison Ai 		crypto_bignum_copy(key->p, (void *)&rsa.P);
317f8907bbfSEdison Ai 
318f8907bbfSEdison Ai 		crypto_bignum_copy(key->q, (void *)&rsa.Q);
319f8907bbfSEdison Ai 		crypto_bignum_copy(key->qp, (void *)&rsa.QP);
320f8907bbfSEdison Ai 		crypto_bignum_copy(key->dp, (void *)&rsa.DP);
321f8907bbfSEdison Ai 		crypto_bignum_copy(key->dq, (void *)&rsa.DQ);
322f8907bbfSEdison Ai 
323f8907bbfSEdison Ai 		res = TEE_SUCCESS;
324f8907bbfSEdison Ai 	}
325f8907bbfSEdison Ai 
326f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
327f8907bbfSEdison Ai 
328f8907bbfSEdison Ai 	return res;
329f8907bbfSEdison Ai }
330f8907bbfSEdison Ai 
331f8907bbfSEdison Ai TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
332eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src,
333eac16613SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
334eac16613SJorge Ramirez-Ortiz 					   size_t *dst_len)
335eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_encrypt");
336eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)337eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
338eac16613SJorge Ramirez-Ortiz 					      const uint8_t *src,
339eac16613SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
340eac16613SJorge Ramirez-Ortiz 					      size_t *dst_len)
341f8907bbfSEdison Ai {
342f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
343f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
344f8907bbfSEdison Ai 	int lmd_res = 0;
345f8907bbfSEdison Ai 	uint8_t *buf = NULL;
346f8907bbfSEdison Ai 	unsigned long blen = 0;
347f8907bbfSEdison Ai 	unsigned long offset = 0;
348f8907bbfSEdison Ai 
349f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
35032b31808SJens Wiklander 	mbedtls_rsa_init(&rsa);
351f8907bbfSEdison Ai 
352f8907bbfSEdison Ai 	rsa.E = *(mbedtls_mpi *)key->e;
353f8907bbfSEdison Ai 	rsa.N = *(mbedtls_mpi *)key->n;
354f8907bbfSEdison Ai 
355f8907bbfSEdison Ai 	rsa.len = crypto_bignum_num_bytes((void *)&rsa.N);
356f8907bbfSEdison Ai 
357f8907bbfSEdison Ai 	blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
358f8907bbfSEdison Ai 	buf = malloc(blen);
359f8907bbfSEdison Ai 	if (!buf) {
360f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
361f8907bbfSEdison Ai 		goto out;
362f8907bbfSEdison Ai 	}
363f8907bbfSEdison Ai 
364f8907bbfSEdison Ai 	memset(buf, 0, blen);
365f8907bbfSEdison Ai 	memcpy(buf + rsa.len - src_len, src, src_len);
366f8907bbfSEdison Ai 
367f8907bbfSEdison Ai 	lmd_res = mbedtls_rsa_public(&rsa, buf, buf);
368f8907bbfSEdison Ai 	if (lmd_res != 0) {
369f8907bbfSEdison Ai 		FMSG("mbedtls_rsa_public() returned 0x%x", -lmd_res);
370f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
371f8907bbfSEdison Ai 		goto out;
372f8907bbfSEdison Ai 	}
373f8907bbfSEdison Ai 
374f8907bbfSEdison Ai 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
375f8907bbfSEdison Ai 	offset = 0;
376f8907bbfSEdison Ai 	while ((offset < rsa.len - 1) && (buf[offset] == 0))
377f8907bbfSEdison Ai 		offset++;
378f8907bbfSEdison Ai 
379f8907bbfSEdison Ai 	if (*dst_len < rsa.len - offset) {
380f8907bbfSEdison Ai 		*dst_len = rsa.len - offset;
381f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
382f8907bbfSEdison Ai 		goto out;
383f8907bbfSEdison Ai 	}
384f8907bbfSEdison Ai 	*dst_len = rsa.len - offset;
385f8907bbfSEdison Ai 	memcpy(dst, buf + offset, *dst_len);
386f8907bbfSEdison Ai out:
387f8907bbfSEdison Ai 	free(buf);
388f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
389f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.E);
390f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.N);
391f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
392f8907bbfSEdison Ai 
393f8907bbfSEdison Ai 	return res;
394f8907bbfSEdison Ai }
395f8907bbfSEdison Ai 
396f8907bbfSEdison Ai TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
397eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src,
398eac16613SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
399eac16613SJorge Ramirez-Ortiz 					   size_t *dst_len)
400eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_decrypt");
401eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)402eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
403eac16613SJorge Ramirez-Ortiz 					      const uint8_t *src,
404eac16613SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
405eac16613SJorge Ramirez-Ortiz 					      size_t *dst_len)
406f8907bbfSEdison Ai {
407f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
40832b31808SJens Wiklander 	mbedtls_rsa_context rsa = { };
409f8907bbfSEdison Ai 	int lmd_res = 0;
410f8907bbfSEdison Ai 	uint8_t *buf = NULL;
411f8907bbfSEdison Ai 	unsigned long blen = 0;
412f8907bbfSEdison Ai 	unsigned long offset = 0;
413f8907bbfSEdison Ai 
41432b31808SJens Wiklander 	res = rsa_init_and_complete_from_key_pair(&rsa, key);
41532b31808SJens Wiklander 	if (res)
41632b31808SJens Wiklander 		return res;
417f8907bbfSEdison Ai 
418f8907bbfSEdison Ai 	blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
419f8907bbfSEdison Ai 	buf = malloc(blen);
420f8907bbfSEdison Ai 	if (!buf) {
421f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
422f8907bbfSEdison Ai 		goto out;
423f8907bbfSEdison Ai 	}
424f8907bbfSEdison Ai 
425f8907bbfSEdison Ai 	memset(buf, 0, blen);
426f8907bbfSEdison Ai 	memcpy(buf + rsa.len - src_len, src, src_len);
427f8907bbfSEdison Ai 
42832b31808SJens Wiklander 	lmd_res = mbedtls_rsa_private(&rsa, mbd_rand, NULL, buf, buf);
429f8907bbfSEdison Ai 	if (lmd_res != 0) {
430f8907bbfSEdison Ai 		FMSG("mbedtls_rsa_private() returned 0x%x", -lmd_res);
431f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
432f8907bbfSEdison Ai 		goto out;
433f8907bbfSEdison Ai 	}
434f8907bbfSEdison Ai 
435f8907bbfSEdison Ai 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
436f8907bbfSEdison Ai 	offset = 0;
437f8907bbfSEdison Ai 	while ((offset < rsa.len - 1) && (buf[offset] == 0))
438f8907bbfSEdison Ai 		offset++;
439f8907bbfSEdison Ai 
440f8907bbfSEdison Ai 	if (*dst_len < rsa.len - offset) {
441f8907bbfSEdison Ai 		*dst_len = rsa.len - offset;
442f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
443f8907bbfSEdison Ai 		goto out;
444f8907bbfSEdison Ai 	}
445f8907bbfSEdison Ai 	*dst_len = rsa.len - offset;
446f8907bbfSEdison Ai 	memcpy(dst, (char *)buf + offset, *dst_len);
447f8907bbfSEdison Ai out:
448f8907bbfSEdison Ai 	if (buf)
449f8907bbfSEdison Ai 		free(buf);
45032b31808SJens Wiklander 	mbd_rsa_free(&rsa, key);
451f8907bbfSEdison Ai 	return res;
452f8907bbfSEdison Ai }
453f8907bbfSEdison Ai 
454eac16613SJorge Ramirez-Ortiz TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo,
455eac16613SJorge Ramirez-Ortiz 					struct rsa_keypair *key,
456eac16613SJorge Ramirez-Ortiz 					const uint8_t *label __unused,
457eac16613SJorge Ramirez-Ortiz 					size_t label_len __unused,
45886ee543bSSami Tolvanen 					uint32_t mgf_algo,
459eac16613SJorge Ramirez-Ortiz 					const uint8_t *src, size_t src_len,
460eac16613SJorge Ramirez-Ortiz 					uint8_t *dst, size_t *dst_len)
461eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_decrypt");
462eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_rsaes_decrypt(uint32_t algo,struct rsa_keypair * key,const uint8_t * label __unused,size_t label_len __unused,uint32_t mgf_algo,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)463eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
464eac16613SJorge Ramirez-Ortiz 					   struct rsa_keypair *key,
465f8907bbfSEdison Ai 					   const uint8_t *label __unused,
466f8907bbfSEdison Ai 					   size_t label_len __unused,
46786ee543bSSami Tolvanen 					   uint32_t mgf_algo,
468f8907bbfSEdison Ai 					   const uint8_t *src, size_t src_len,
469f8907bbfSEdison Ai 					   uint8_t *dst, size_t *dst_len)
470f8907bbfSEdison Ai {
471f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
472f8907bbfSEdison Ai 	int lmd_res = 0;
473f8907bbfSEdison Ai 	int lmd_padding = 0;
474f8907bbfSEdison Ai 	size_t blen = 0;
475f8907bbfSEdison Ai 	size_t mod_size = 0;
476f8907bbfSEdison Ai 	void *buf = NULL;
477*b0563631STom Van Eyck 	mbedtls_pk_context ctx = { };
478*b0563631STom Van Eyck 	mbedtls_rsa_context *rsa = NULL;
479f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
480f8907bbfSEdison Ai 	uint32_t md_algo = MBEDTLS_MD_NONE;
481f8907bbfSEdison Ai 
482*b0563631STom Van Eyck 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
483*b0563631STom Van Eyck 	if (!pk_info) {
484*b0563631STom Van Eyck 		return TEE_ERROR_NOT_SUPPORTED;
485*b0563631STom Van Eyck 	}
486*b0563631STom Van Eyck 
487*b0563631STom Van Eyck 	mbedtls_pk_init(&ctx);
488*b0563631STom Van Eyck 	res = mbedtls_pk_setup(&ctx, pk_info);
489*b0563631STom Van Eyck 	if (res != 0) {
490*b0563631STom Van Eyck 		goto out;
491*b0563631STom Van Eyck 	}
492*b0563631STom Van Eyck 
493*b0563631STom Van Eyck 	rsa = ctx.pk_ctx;
494*b0563631STom Van Eyck 	res = rsa_complete_from_key_pair(rsa, key);
49532b31808SJens Wiklander 	if (res)
49632b31808SJens Wiklander 		return res;
497f8907bbfSEdison Ai 
498f8907bbfSEdison Ai 	/*
499f8907bbfSEdison Ai 	 * Use a temporary buffer since we don't know exactly how large
500f8907bbfSEdison Ai 	 * the required size of the out buffer without doing a partial
501f8907bbfSEdison Ai 	 * decrypt. We know the upper bound though.
502f8907bbfSEdison Ai 	 */
503f8907bbfSEdison Ai 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
504f8907bbfSEdison Ai 		mod_size = crypto_bignum_num_bytes(key->n);
505f8907bbfSEdison Ai 		blen = mod_size - 11;
506f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
507f8907bbfSEdison Ai 	} else {
508f8907bbfSEdison Ai 		/* Decoded message is always shorter than encrypted message */
509f8907bbfSEdison Ai 		blen = src_len;
510f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
511f8907bbfSEdison Ai 	}
512f8907bbfSEdison Ai 
513f8907bbfSEdison Ai 	buf = malloc(blen);
514f8907bbfSEdison Ai 	if (!buf) {
515f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
516f8907bbfSEdison Ai 		goto out;
517f8907bbfSEdison Ai 	}
518f8907bbfSEdison Ai 
519f8907bbfSEdison Ai 	/*
520f8907bbfSEdison Ai 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
521f8907bbfSEdison Ai 	 * not be used in rsa, so skip it here.
522f8907bbfSEdison Ai 	 */
523f8907bbfSEdison Ai 	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
524f8907bbfSEdison Ai 		md_algo = tee_algo_to_mbedtls_hash_algo(algo);
525f8907bbfSEdison Ai 		if (md_algo == MBEDTLS_MD_NONE) {
526f8907bbfSEdison Ai 			res = TEE_ERROR_NOT_SUPPORTED;
527f8907bbfSEdison Ai 			goto out;
528f8907bbfSEdison Ai 		}
52986ee543bSSami Tolvanen 		if (md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) {
53086ee543bSSami Tolvanen 			DMSG("Using a different MGF1 algorithm is not supported");
53186ee543bSSami Tolvanen 			res = TEE_ERROR_NOT_SUPPORTED;
53286ee543bSSami Tolvanen 			goto out;
53386ee543bSSami Tolvanen 		}
534f8907bbfSEdison Ai 	}
535f8907bbfSEdison Ai 
536*b0563631STom Van Eyck 	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
537f8907bbfSEdison Ai 
538*b0563631STom Van Eyck 	lmd_res = pk_info->decrypt_func(&ctx, src, src_len, buf, &blen,
539f8907bbfSEdison Ai 					blen, mbd_rand, NULL);
540f8907bbfSEdison Ai 	if (lmd_res != 0) {
541f8907bbfSEdison Ai 		FMSG("decrypt_func() returned 0x%x", -lmd_res);
542f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
543f8907bbfSEdison Ai 		goto out;
544f8907bbfSEdison Ai 	}
545f8907bbfSEdison Ai 
546f8907bbfSEdison Ai 	if (*dst_len < blen) {
547f8907bbfSEdison Ai 		*dst_len = blen;
548f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
549f8907bbfSEdison Ai 		goto out;
550f8907bbfSEdison Ai 	}
551f8907bbfSEdison Ai 
552f8907bbfSEdison Ai 	res = TEE_SUCCESS;
553f8907bbfSEdison Ai 	*dst_len = blen;
554f8907bbfSEdison Ai 	memcpy(dst, buf, blen);
555f8907bbfSEdison Ai out:
556f8907bbfSEdison Ai 	if (buf)
557f8907bbfSEdison Ai 		free(buf);
558*b0563631STom Van Eyck 	mbd_pk_free(&ctx, key);
559f8907bbfSEdison Ai 	return res;
560f8907bbfSEdison Ai }
561f8907bbfSEdison Ai 
562f8907bbfSEdison Ai TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
563f8907bbfSEdison Ai 					struct rsa_public_key *key,
564f8907bbfSEdison Ai 					const uint8_t *label __unused,
565f8907bbfSEdison Ai 					size_t label_len __unused,
56686ee543bSSami Tolvanen 					uint32_t mgf_algo,
567f8907bbfSEdison Ai 					const uint8_t *src, size_t src_len,
568f8907bbfSEdison Ai 					uint8_t *dst, size_t *dst_len)
569eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_encrypt");
570eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_rsaes_encrypt(uint32_t algo,struct rsa_public_key * key,const uint8_t * label __unused,size_t label_len __unused,uint32_t mgf_algo,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)571eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
572eac16613SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
573eac16613SJorge Ramirez-Ortiz 					   const uint8_t *label __unused,
574eac16613SJorge Ramirez-Ortiz 					   size_t label_len __unused,
57586ee543bSSami Tolvanen 					   uint32_t mgf_algo,
576eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src, size_t src_len,
577eac16613SJorge Ramirez-Ortiz 					   uint8_t *dst, size_t *dst_len)
578f8907bbfSEdison Ai {
579f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
580f8907bbfSEdison Ai 	int lmd_res = 0;
581f8907bbfSEdison Ai 	int lmd_padding = 0;
582f8907bbfSEdison Ai 	size_t mod_size = 0;
583*b0563631STom Van Eyck 	mbedtls_pk_context ctx = { };
584*b0563631STom Van Eyck 	mbedtls_rsa_context *rsa = NULL;
585f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
586f8907bbfSEdison Ai 	uint32_t md_algo = MBEDTLS_MD_NONE;
587f8907bbfSEdison Ai 
588*b0563631STom Van Eyck 	memset(&ctx, 0, sizeof(ctx));
589f8907bbfSEdison Ai 
590*b0563631STom Van Eyck 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
591*b0563631STom Van Eyck 	if (!pk_info) {
592*b0563631STom Van Eyck 		return TEE_ERROR_NOT_SUPPORTED;
593*b0563631STom Van Eyck 	}
594*b0563631STom Van Eyck 
595*b0563631STom Van Eyck 	mbedtls_pk_init(&ctx);
596*b0563631STom Van Eyck 	res = mbedtls_pk_setup(&ctx, pk_info);
597*b0563631STom Van Eyck 	if (res != 0) {
598*b0563631STom Van Eyck 		goto out;
599*b0563631STom Van Eyck 	}
600*b0563631STom Van Eyck 
601*b0563631STom Van Eyck 	rsa = ctx.pk_ctx;
602*b0563631STom Van Eyck 
603*b0563631STom Van Eyck 	rsa->E = *(mbedtls_mpi *)key->e;
604*b0563631STom Van Eyck 	rsa->N = *(mbedtls_mpi *)key->n;
605f8907bbfSEdison Ai 
606f8907bbfSEdison Ai 	mod_size = crypto_bignum_num_bytes(key->n);
607f8907bbfSEdison Ai 	if (*dst_len < mod_size) {
608f8907bbfSEdison Ai 		*dst_len = mod_size;
609f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
610f8907bbfSEdison Ai 		goto out;
611f8907bbfSEdison Ai 	}
612f8907bbfSEdison Ai 	*dst_len = mod_size;
613*b0563631STom Van Eyck 	rsa->len = mod_size;
614f8907bbfSEdison Ai 
615f8907bbfSEdison Ai 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
616f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
617f8907bbfSEdison Ai 	else
618f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
619f8907bbfSEdison Ai 
620f8907bbfSEdison Ai 	/*
621f8907bbfSEdison Ai 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
622f8907bbfSEdison Ai 	 * not be used in rsa, so skip it here.
623f8907bbfSEdison Ai 	 */
624f8907bbfSEdison Ai 	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
625f8907bbfSEdison Ai 		md_algo = tee_algo_to_mbedtls_hash_algo(algo);
62686ee543bSSami Tolvanen 		/* Using a different MGF1 algorithm is not supported. */
62786ee543bSSami Tolvanen 		if (md_algo == MBEDTLS_MD_NONE ||
62886ee543bSSami Tolvanen 		    md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) {
629f8907bbfSEdison Ai 			res = TEE_ERROR_NOT_SUPPORTED;
630f8907bbfSEdison Ai 			goto out;
631f8907bbfSEdison Ai 		}
632f8907bbfSEdison Ai 	}
633f8907bbfSEdison Ai 
634*b0563631STom Van Eyck 	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
635f8907bbfSEdison Ai 
636*b0563631STom Van Eyck 	lmd_res = pk_info->encrypt_func(&ctx, src, src_len, dst, dst_len,
637f8907bbfSEdison Ai 					*dst_len, mbd_rand, NULL);
638f8907bbfSEdison Ai 	if (lmd_res != 0) {
639f8907bbfSEdison Ai 		FMSG("encrypt_func() returned 0x%x", -lmd_res);
640f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
641f8907bbfSEdison Ai 		goto out;
642f8907bbfSEdison Ai 	}
643f8907bbfSEdison Ai 	res = TEE_SUCCESS;
644f8907bbfSEdison Ai out:
645f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
646*b0563631STom Van Eyck 	mbedtls_mpi_init(&rsa->E);
647*b0563631STom Van Eyck 	mbedtls_mpi_init(&rsa->N);
648*b0563631STom Van Eyck 	mbedtls_pk_free(&ctx);
649f8907bbfSEdison Ai 	return res;
650f8907bbfSEdison Ai }
651f8907bbfSEdison Ai 
652f8907bbfSEdison Ai TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
653eac16613SJorge Ramirez-Ortiz 				      int salt_len __unused,
654eac16613SJorge Ramirez-Ortiz 				      const uint8_t *msg, size_t msg_len,
655eac16613SJorge Ramirez-Ortiz 				      uint8_t *sig, size_t *sig_len)
656eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_sign");
657eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_rsassa_sign(uint32_t algo,struct rsa_keypair * key,int salt_len __unused,const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len)658eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
659eac16613SJorge Ramirez-Ortiz 					 int salt_len __unused,
660eac16613SJorge Ramirez-Ortiz 					 const uint8_t *msg, size_t msg_len,
661eac16613SJorge Ramirez-Ortiz 					 uint8_t *sig, size_t *sig_len)
662f8907bbfSEdison Ai {
663f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
664f8907bbfSEdison Ai 	int lmd_res = 0;
665f8907bbfSEdison Ai 	int lmd_padding = 0;
666f8907bbfSEdison Ai 	size_t mod_size = 0;
667f8907bbfSEdison Ai 	size_t hash_size = 0;
668*b0563631STom Van Eyck 	mbedtls_pk_context ctx = { };
669*b0563631STom Van Eyck 	mbedtls_rsa_context *rsa = NULL;
670f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
671f8907bbfSEdison Ai 	uint32_t md_algo = 0;
672f8907bbfSEdison Ai 
673*b0563631STom Van Eyck 	memset(&ctx, 0, sizeof(ctx));
674*b0563631STom Van Eyck 
675*b0563631STom Van Eyck 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
676*b0563631STom Van Eyck 	if (!pk_info) {
677*b0563631STom Van Eyck 		return TEE_ERROR_NOT_SUPPORTED;
678*b0563631STom Van Eyck 	}
679*b0563631STom Van Eyck 
680*b0563631STom Van Eyck 	mbedtls_pk_init(&ctx);
681*b0563631STom Van Eyck 	res = mbedtls_pk_setup(&ctx, pk_info);
682*b0563631STom Van Eyck 	if (res != 0) {
683*b0563631STom Van Eyck 		goto err;
684*b0563631STom Van Eyck 	}
685*b0563631STom Van Eyck 
686*b0563631STom Van Eyck 	rsa = ctx.pk_ctx;
687*b0563631STom Van Eyck 	res = rsa_complete_from_key_pair(rsa, key);
68832b31808SJens Wiklander 	if (res)
68932b31808SJens Wiklander 		return res;
690f8907bbfSEdison Ai 
691f8907bbfSEdison Ai 	switch (algo) {
692f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
693f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
694f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
695f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
696f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
697f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
698f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
699f8907bbfSEdison Ai 		break;
700f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
701f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
702f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
703f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
704f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
705f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
706f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
707f8907bbfSEdison Ai 		break;
708f8907bbfSEdison Ai 	default:
709f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
710f8907bbfSEdison Ai 		goto err;
711f8907bbfSEdison Ai 	}
712f8907bbfSEdison Ai 
7137c767434SAlbert Schwarzkopf 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
714f8907bbfSEdison Ai 				      &hash_size);
715f8907bbfSEdison Ai 	if (res != TEE_SUCCESS)
716f8907bbfSEdison Ai 		goto err;
717f8907bbfSEdison Ai 
718f8907bbfSEdison Ai 	if (msg_len != hash_size) {
719f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
720f8907bbfSEdison Ai 		goto err;
721f8907bbfSEdison Ai 	}
722f8907bbfSEdison Ai 
723f8907bbfSEdison Ai 	mod_size = crypto_bignum_num_bytes(key->n);
724f8907bbfSEdison Ai 	if (*sig_len < mod_size) {
725f8907bbfSEdison Ai 		*sig_len = mod_size;
726f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
727f8907bbfSEdison Ai 		goto err;
728f8907bbfSEdison Ai 	}
729*b0563631STom Van Eyck 	rsa->len = mod_size;
730f8907bbfSEdison Ai 
731f8907bbfSEdison Ai 	md_algo = tee_algo_to_mbedtls_hash_algo(algo);
732f8907bbfSEdison Ai 	if (md_algo == MBEDTLS_MD_NONE) {
733f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
734f8907bbfSEdison Ai 		goto err;
735f8907bbfSEdison Ai 	}
736f8907bbfSEdison Ai 
737f8907bbfSEdison Ai 
738*b0563631STom Van Eyck 	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
739f8907bbfSEdison Ai 
740*b0563631STom Van Eyck 	lmd_res = pk_info->sign_func(&ctx, md_algo, msg, msg_len, sig,
74132b31808SJens Wiklander 				     *sig_len, sig_len, mbd_rand, NULL);
742f8907bbfSEdison Ai 	if (lmd_res != 0) {
743f8907bbfSEdison Ai 		FMSG("sign_func failed, returned 0x%x", -lmd_res);
744f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
745f8907bbfSEdison Ai 		goto err;
746f8907bbfSEdison Ai 	}
747f8907bbfSEdison Ai 	res = TEE_SUCCESS;
748f8907bbfSEdison Ai err:
749*b0563631STom Van Eyck 	mbd_pk_free(&ctx, key);
750f8907bbfSEdison Ai 	return res;
751f8907bbfSEdison Ai }
752f8907bbfSEdison Ai 
753f8907bbfSEdison Ai TEE_Result crypto_acipher_rsassa_verify(uint32_t algo,
754f8907bbfSEdison Ai 					struct rsa_public_key *key,
755f8907bbfSEdison Ai 					int salt_len __unused,
756f8907bbfSEdison Ai 					const uint8_t *msg,
757f8907bbfSEdison Ai 					size_t msg_len, const uint8_t *sig,
758f8907bbfSEdison Ai 					size_t sig_len)
759eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_verify");
760eac16613SJorge Ramirez-Ortiz 
sw_crypto_acipher_rsassa_verify(uint32_t algo,struct rsa_public_key * key,int salt_len __unused,const uint8_t * msg,size_t msg_len,const uint8_t * sig,size_t sig_len)761eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
762eac16613SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
763eac16613SJorge Ramirez-Ortiz 					   int salt_len __unused,
764eac16613SJorge Ramirez-Ortiz 					   const uint8_t *msg,
765eac16613SJorge Ramirez-Ortiz 					   size_t msg_len, const uint8_t *sig,
766eac16613SJorge Ramirez-Ortiz 					   size_t sig_len)
767f8907bbfSEdison Ai {
768f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
769f8907bbfSEdison Ai 	int lmd_res = 0;
770f8907bbfSEdison Ai 	int lmd_padding = 0;
771f8907bbfSEdison Ai 	size_t hash_size = 0;
772f8907bbfSEdison Ai 	size_t bigint_size = 0;
773*b0563631STom Van Eyck 	mbedtls_pk_context ctx = { };
774*b0563631STom Van Eyck 	mbedtls_rsa_context *rsa = NULL;
775f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
776f8907bbfSEdison Ai 	uint32_t md_algo = 0;
77798ada65eSJens Wiklander 	struct ftmn ftmn = { };
77898ada65eSJens Wiklander 	unsigned long arg_hash = 0;
77998ada65eSJens Wiklander 
78098ada65eSJens Wiklander 	/*
78198ada65eSJens Wiklander 	 * The caller expects to call crypto_acipher_rsassa_verify(),
78298ada65eSJens Wiklander 	 * update the hash as needed.
78398ada65eSJens Wiklander 	 */
78498ada65eSJens Wiklander 	FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify"));
785f8907bbfSEdison Ai 
786*b0563631STom Van Eyck 	memset(&ctx, 0, sizeof(ctx));
787f8907bbfSEdison Ai 
788*b0563631STom Van Eyck 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
789*b0563631STom Van Eyck 	if (!pk_info) {
790*b0563631STom Van Eyck 		return TEE_ERROR_NOT_SUPPORTED;
791*b0563631STom Van Eyck 	}
792*b0563631STom Van Eyck 
793*b0563631STom Van Eyck 	mbedtls_pk_init(&ctx);
794*b0563631STom Van Eyck 	res = mbedtls_pk_setup(&ctx, pk_info);
795*b0563631STom Van Eyck 	if (res != 0) {
796*b0563631STom Van Eyck 		goto err;
797*b0563631STom Van Eyck 	}
798*b0563631STom Van Eyck 
799*b0563631STom Van Eyck 	rsa = ctx.pk_ctx;
800*b0563631STom Van Eyck 
801*b0563631STom Van Eyck 	rsa->E = *(mbedtls_mpi *)key->e;
802*b0563631STom Van Eyck 	rsa->N = *(mbedtls_mpi *)key->n;
803f8907bbfSEdison Ai 
8047c767434SAlbert Schwarzkopf 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
805f8907bbfSEdison Ai 				      &hash_size);
806f8907bbfSEdison Ai 	if (res != TEE_SUCCESS)
807f8907bbfSEdison Ai 		goto err;
808f8907bbfSEdison Ai 
809f8907bbfSEdison Ai 	if (msg_len != hash_size) {
810f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
811f8907bbfSEdison Ai 		goto err;
812f8907bbfSEdison Ai 	}
813f8907bbfSEdison Ai 
814f8907bbfSEdison Ai 	bigint_size = crypto_bignum_num_bytes(key->n);
815f8907bbfSEdison Ai 	if (sig_len < bigint_size) {
816c282ebd6Slubing 		res = TEE_ERROR_SIGNATURE_INVALID;
817f8907bbfSEdison Ai 		goto err;
818f8907bbfSEdison Ai 	}
819f8907bbfSEdison Ai 
820*b0563631STom Van Eyck 	rsa->len = bigint_size;
821f8907bbfSEdison Ai 
822f8907bbfSEdison Ai 	switch (algo) {
823f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
824f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
825f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
826f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
827f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
828f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
82998ada65eSJens Wiklander 		arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pkcs1_v15_verify");
830f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
831f8907bbfSEdison Ai 		break;
832f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
833f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
834f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
835f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
836f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
837f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
83898ada65eSJens Wiklander 		arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pss_verify_ext");
839f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
840f8907bbfSEdison Ai 		break;
841f8907bbfSEdison Ai 	default:
842f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
843f8907bbfSEdison Ai 		goto err;
844f8907bbfSEdison Ai 	}
845f8907bbfSEdison Ai 
846f8907bbfSEdison Ai 	md_algo = tee_algo_to_mbedtls_hash_algo(algo);
847f8907bbfSEdison Ai 	if (md_algo == MBEDTLS_MD_NONE) {
848f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
849f8907bbfSEdison Ai 		goto err;
850f8907bbfSEdison Ai 	}
851f8907bbfSEdison Ai 
852*b0563631STom Van Eyck 	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
853f8907bbfSEdison Ai 
85498ada65eSJens Wiklander 	FTMN_PUSH_LINKED_CALL(&ftmn, arg_hash);
855*b0563631STom Van Eyck 	lmd_res = pk_info->verify_func(&ctx, md_algo, msg, msg_len,
856f8907bbfSEdison Ai 	                               sig, sig_len);
85798ada65eSJens Wiklander 	if (!lmd_res)
85898ada65eSJens Wiklander 		FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, lmd_res);
85998ada65eSJens Wiklander 	FTMN_POP_LINKED_CALL(&ftmn);
860f8907bbfSEdison Ai 	if (lmd_res != 0) {
861f8907bbfSEdison Ai 		FMSG("verify_func failed, returned 0x%x", -lmd_res);
862f8907bbfSEdison Ai 		res = TEE_ERROR_SIGNATURE_INVALID;
863f8907bbfSEdison Ai 		goto err;
864f8907bbfSEdison Ai 	}
865f8907bbfSEdison Ai 	res = TEE_SUCCESS;
86698ada65eSJens Wiklander 	goto out;
86798ada65eSJens Wiklander 
868f8907bbfSEdison Ai err:
86998ada65eSJens Wiklander 	FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res);
87098ada65eSJens Wiklander out:
87198ada65eSJens Wiklander 	FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res);
872f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
873*b0563631STom Van Eyck 	mbedtls_mpi_init(&rsa->E);
874*b0563631STom Van Eyck 	mbedtls_mpi_init(&rsa->N);
875*b0563631STom Van Eyck 	mbedtls_pk_free(&ctx);
876f8907bbfSEdison Ai 	return res;
877f8907bbfSEdison Ai }
878