xref: /optee_os/lib/libmbedtls/core/rsa.c (revision 86ee543b2786068e4d192111ab5e582d065c2a8d)
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 
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 
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 
10032b31808SJens Wiklander static TEE_Result rsa_init_and_complete_from_key_pair(mbedtls_rsa_context *rsa,
101f8907bbfSEdison Ai 						      struct rsa_keypair *key)
102f8907bbfSEdison Ai {
10332b31808SJens Wiklander 	int lmd_res = 0;
10432b31808SJens Wiklander 
10532b31808SJens Wiklander 	mbedtls_rsa_init(rsa);
106f8907bbfSEdison Ai 
107f8907bbfSEdison Ai 	rsa->E = *(mbedtls_mpi *)key->e;
108f8907bbfSEdison Ai 	rsa->N = *(mbedtls_mpi *)key->n;
109f8907bbfSEdison Ai 	rsa->D = *(mbedtls_mpi *)key->d;
11032b31808SJens Wiklander 	rsa->len = mbedtls_mpi_size(&rsa->N);
11132b31808SJens Wiklander 
112f8907bbfSEdison Ai 	if (key->p && crypto_bignum_num_bytes(key->p)) {
113f8907bbfSEdison Ai 		rsa->P = *(mbedtls_mpi *)key->p;
114f8907bbfSEdison Ai 		rsa->Q = *(mbedtls_mpi *)key->q;
115f8907bbfSEdison Ai 		rsa->QP = *(mbedtls_mpi *)key->qp;
116f8907bbfSEdison Ai 		rsa->DP = *(mbedtls_mpi *)key->dp;
117f8907bbfSEdison Ai 		rsa->DQ = *(mbedtls_mpi *)key->dq;
11832b31808SJens Wiklander 	} else {
11932b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->P);
12032b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->Q);
12132b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->QP);
12232b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->DP);
12332b31808SJens Wiklander 		mbedtls_mpi_init_mempool(&rsa->DQ);
12432b31808SJens Wiklander 
12532b31808SJens Wiklander 		lmd_res = mbedtls_rsa_deduce_primes(&rsa->N, &rsa->E, &rsa->D,
12632b31808SJens Wiklander 						    &rsa->P, &rsa->Q);
12732b31808SJens Wiklander 		if (lmd_res) {
12832b31808SJens Wiklander 			DMSG("mbedtls_rsa_deduce_primes() returned 0x%x",
12932b31808SJens Wiklander 			     -lmd_res);
13032b31808SJens Wiklander 			goto err;
131f8907bbfSEdison Ai 		}
132f8907bbfSEdison Ai 
13332b31808SJens Wiklander 		lmd_res = mbedtls_rsa_deduce_crt(&rsa->P, &rsa->Q, &rsa->D,
13432b31808SJens Wiklander 						 &rsa->DP, &rsa->DQ, &rsa->QP);
13532b31808SJens Wiklander 		if (lmd_res) {
13632b31808SJens Wiklander 			DMSG("mbedtls_rsa_deduce_crt() returned 0x%x",
13732b31808SJens Wiklander 			     -lmd_res);
13832b31808SJens Wiklander 			goto err;
13932b31808SJens Wiklander 		}
14032b31808SJens Wiklander 	}
14132b31808SJens Wiklander 
14232b31808SJens Wiklander 	return TEE_SUCCESS;
14332b31808SJens Wiklander err:
14432b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->P);
14532b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->Q);
14632b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->QP);
14732b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->DP);
14832b31808SJens Wiklander 	mbedtls_mpi_free(&rsa->DQ);
14932b31808SJens Wiklander 
15032b31808SJens Wiklander 	return get_tee_result(lmd_res);
15132b31808SJens Wiklander }
15232b31808SJens Wiklander 
15332b31808SJens Wiklander static void mbd_rsa_free(mbedtls_rsa_context *rsa, struct rsa_keypair *key)
154f8907bbfSEdison Ai {
15532b31808SJens Wiklander 	/*
15632b31808SJens Wiklander 	 * The mpi's in @rsa are initialized from @key, but the primes and
15732b31808SJens Wiklander 	 * CRT part are generated if @key doesn't have them. When freeing
15832b31808SJens Wiklander 	 * we should only free the generated mpi's, the ones copied are
15932b31808SJens Wiklander 	 * reset instead.
16032b31808SJens Wiklander 	 */
161f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->E);
162f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->N);
163f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->D);
16432b31808SJens Wiklander 	if (key->p && crypto_bignum_num_bytes(key->p)) {
165f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->P);
166f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->Q);
167f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->QP);
168f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->DP);
169f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->DQ);
170f8907bbfSEdison Ai 	}
171f8907bbfSEdison Ai 	mbedtls_rsa_free(rsa);
172f8907bbfSEdison Ai }
173f8907bbfSEdison Ai 
174f8907bbfSEdison Ai TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
175f8907bbfSEdison Ai 					    size_t key_size_bits)
176eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_keypair");
177eac16613SJorge Ramirez-Ortiz 
178eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
179eac16613SJorge Ramirez-Ortiz 					       size_t key_size_bits)
180f8907bbfSEdison Ai {
181f8907bbfSEdison Ai 	memset(s, 0, sizeof(*s));
182f8907bbfSEdison Ai 	s->e = crypto_bignum_allocate(key_size_bits);
183f8907bbfSEdison Ai 	if (!s->e)
184f8907bbfSEdison Ai 		goto err;
185f8907bbfSEdison Ai 	s->d = crypto_bignum_allocate(key_size_bits);
186f8907bbfSEdison Ai 	if (!s->d)
187f8907bbfSEdison Ai 		goto err;
188f8907bbfSEdison Ai 	s->n = crypto_bignum_allocate(key_size_bits);
189f8907bbfSEdison Ai 	if (!s->n)
190f8907bbfSEdison Ai 		goto err;
191f8907bbfSEdison Ai 	s->p = crypto_bignum_allocate(key_size_bits);
192f8907bbfSEdison Ai 	if (!s->p)
193f8907bbfSEdison Ai 		goto err;
194f8907bbfSEdison Ai 	s->q = crypto_bignum_allocate(key_size_bits);
195f8907bbfSEdison Ai 	if (!s->q)
196f8907bbfSEdison Ai 		goto err;
197f8907bbfSEdison Ai 	s->qp = crypto_bignum_allocate(key_size_bits);
198f8907bbfSEdison Ai 	if (!s->qp)
199f8907bbfSEdison Ai 		goto err;
200f8907bbfSEdison Ai 	s->dp = crypto_bignum_allocate(key_size_bits);
201f8907bbfSEdison Ai 	if (!s->dp)
202f8907bbfSEdison Ai 		goto err;
203f8907bbfSEdison Ai 	s->dq = crypto_bignum_allocate(key_size_bits);
204f8907bbfSEdison Ai 	if (!s->dq)
205f8907bbfSEdison Ai 		goto err;
206f8907bbfSEdison Ai 
207f8907bbfSEdison Ai 	return TEE_SUCCESS;
208f8907bbfSEdison Ai err:
2091ab1ebd8SJerome Forissier 	crypto_acipher_free_rsa_keypair(s);
210f8907bbfSEdison Ai 	return TEE_ERROR_OUT_OF_MEMORY;
211f8907bbfSEdison Ai }
212f8907bbfSEdison Ai 
213f8907bbfSEdison Ai TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
214f8907bbfSEdison Ai 					       size_t key_size_bits)
215eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_public_key");
216eac16613SJorge Ramirez-Ortiz 
217eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
218eac16613SJorge Ramirez-Ortiz 						  size_t key_size_bits)
219f8907bbfSEdison Ai {
220f8907bbfSEdison Ai 	memset(s, 0, sizeof(*s));
221f8907bbfSEdison Ai 	s->e = crypto_bignum_allocate(key_size_bits);
222f8907bbfSEdison Ai 	if (!s->e)
223f8907bbfSEdison Ai 		return TEE_ERROR_OUT_OF_MEMORY;
224f8907bbfSEdison Ai 	s->n = crypto_bignum_allocate(key_size_bits);
225f8907bbfSEdison Ai 	if (!s->n)
226f8907bbfSEdison Ai 		goto err;
227f8907bbfSEdison Ai 	return TEE_SUCCESS;
228f8907bbfSEdison Ai err:
229e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
230f8907bbfSEdison Ai 	return TEE_ERROR_OUT_OF_MEMORY;
231f8907bbfSEdison Ai }
232f8907bbfSEdison Ai 
233f8907bbfSEdison Ai void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
234eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_public_key");
235eac16613SJorge Ramirez-Ortiz 
236eac16613SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
237f8907bbfSEdison Ai {
238f8907bbfSEdison Ai 	if (!s)
239f8907bbfSEdison Ai 		return;
240e2ec831cSJihwan Park 	crypto_bignum_free(&s->n);
241e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
242f8907bbfSEdison Ai }
243f8907bbfSEdison Ai 
244a1d5c81fSElias von Däniken void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
245eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_keypair");
246eac16613SJorge Ramirez-Ortiz 
247eac16613SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
248a1d5c81fSElias von Däniken {
249a1d5c81fSElias von Däniken 	if (!s)
250a1d5c81fSElias von Däniken 		return;
251e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
252e2ec831cSJihwan Park 	crypto_bignum_free(&s->d);
253e2ec831cSJihwan Park 	crypto_bignum_free(&s->n);
254e2ec831cSJihwan Park 	crypto_bignum_free(&s->p);
255e2ec831cSJihwan Park 	crypto_bignum_free(&s->q);
256e2ec831cSJihwan Park 	crypto_bignum_free(&s->qp);
257e2ec831cSJihwan Park 	crypto_bignum_free(&s->dp);
258e2ec831cSJihwan Park 	crypto_bignum_free(&s->dq);
259a1d5c81fSElias von Däniken }
260a1d5c81fSElias von Däniken 
261eac16613SJorge Ramirez-Ortiz TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
262eac16613SJorge Ramirez-Ortiz 				      size_t key_size)
263eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_gen_rsa_key");
264eac16613SJorge Ramirez-Ortiz 
265eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
266eac16613SJorge Ramirez-Ortiz 					 size_t key_size)
267f8907bbfSEdison Ai {
268f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
269f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
2707910f4d8SLars Persson 	mbedtls_ctr_drbg_context rngctx;
271f8907bbfSEdison Ai 	int lmd_res = 0;
272f8907bbfSEdison Ai 	uint32_t e = 0;
273f8907bbfSEdison Ai 
2747910f4d8SLars Persson 	mbedtls_ctr_drbg_init(&rngctx);
2757910f4d8SLars Persson 	if (mbedtls_ctr_drbg_seed(&rngctx, mbd_rand, NULL, NULL, 0))
2767910f4d8SLars Persson 		return TEE_ERROR_BAD_STATE;
2777910f4d8SLars Persson 
278f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
27932b31808SJens Wiklander 	mbedtls_rsa_init(&rsa);
280f8907bbfSEdison Ai 
281f8907bbfSEdison Ai 	/* get the public exponent */
282f8907bbfSEdison Ai 	mbedtls_mpi_write_binary((mbedtls_mpi *)key->e,
283f8907bbfSEdison Ai 				 (unsigned char *)&e, sizeof(uint32_t));
284f8907bbfSEdison Ai 
285f8907bbfSEdison Ai 	e = TEE_U32_FROM_BIG_ENDIAN(e);
2867910f4d8SLars Persson 	lmd_res = mbedtls_rsa_gen_key(&rsa, mbedtls_ctr_drbg_random, &rngctx,
2877910f4d8SLars Persson 				      key_size, (int)e);
2887910f4d8SLars Persson 	mbedtls_ctr_drbg_free(&rngctx);
289f8907bbfSEdison Ai 	if (lmd_res != 0) {
290f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
291f8907bbfSEdison Ai 	} else if ((size_t)mbedtls_mpi_bitlen(&rsa.N) != key_size) {
292f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
293f8907bbfSEdison Ai 	} else {
294f8907bbfSEdison Ai 		/* Copy the key */
295f8907bbfSEdison Ai 		crypto_bignum_copy(key->e, (void *)&rsa.E);
296f8907bbfSEdison Ai 		crypto_bignum_copy(key->d, (void *)&rsa.D);
297f8907bbfSEdison Ai 		crypto_bignum_copy(key->n, (void *)&rsa.N);
298f8907bbfSEdison Ai 		crypto_bignum_copy(key->p, (void *)&rsa.P);
299f8907bbfSEdison Ai 
300f8907bbfSEdison Ai 		crypto_bignum_copy(key->q, (void *)&rsa.Q);
301f8907bbfSEdison Ai 		crypto_bignum_copy(key->qp, (void *)&rsa.QP);
302f8907bbfSEdison Ai 		crypto_bignum_copy(key->dp, (void *)&rsa.DP);
303f8907bbfSEdison Ai 		crypto_bignum_copy(key->dq, (void *)&rsa.DQ);
304f8907bbfSEdison Ai 
305f8907bbfSEdison Ai 		res = TEE_SUCCESS;
306f8907bbfSEdison Ai 	}
307f8907bbfSEdison Ai 
308f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
309f8907bbfSEdison Ai 
310f8907bbfSEdison Ai 	return res;
311f8907bbfSEdison Ai }
312f8907bbfSEdison Ai 
313f8907bbfSEdison Ai TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
314eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src,
315eac16613SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
316eac16613SJorge Ramirez-Ortiz 					   size_t *dst_len)
317eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_encrypt");
318eac16613SJorge Ramirez-Ortiz 
319eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
320eac16613SJorge Ramirez-Ortiz 					      const uint8_t *src,
321eac16613SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
322eac16613SJorge Ramirez-Ortiz 					      size_t *dst_len)
323f8907bbfSEdison Ai {
324f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
325f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
326f8907bbfSEdison Ai 	int lmd_res = 0;
327f8907bbfSEdison Ai 	uint8_t *buf = NULL;
328f8907bbfSEdison Ai 	unsigned long blen = 0;
329f8907bbfSEdison Ai 	unsigned long offset = 0;
330f8907bbfSEdison Ai 
331f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
33232b31808SJens Wiklander 	mbedtls_rsa_init(&rsa);
333f8907bbfSEdison Ai 
334f8907bbfSEdison Ai 	rsa.E = *(mbedtls_mpi *)key->e;
335f8907bbfSEdison Ai 	rsa.N = *(mbedtls_mpi *)key->n;
336f8907bbfSEdison Ai 
337f8907bbfSEdison Ai 	rsa.len = crypto_bignum_num_bytes((void *)&rsa.N);
338f8907bbfSEdison Ai 
339f8907bbfSEdison Ai 	blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
340f8907bbfSEdison Ai 	buf = malloc(blen);
341f8907bbfSEdison Ai 	if (!buf) {
342f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
343f8907bbfSEdison Ai 		goto out;
344f8907bbfSEdison Ai 	}
345f8907bbfSEdison Ai 
346f8907bbfSEdison Ai 	memset(buf, 0, blen);
347f8907bbfSEdison Ai 	memcpy(buf + rsa.len - src_len, src, src_len);
348f8907bbfSEdison Ai 
349f8907bbfSEdison Ai 	lmd_res = mbedtls_rsa_public(&rsa, buf, buf);
350f8907bbfSEdison Ai 	if (lmd_res != 0) {
351f8907bbfSEdison Ai 		FMSG("mbedtls_rsa_public() returned 0x%x", -lmd_res);
352f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
353f8907bbfSEdison Ai 		goto out;
354f8907bbfSEdison Ai 	}
355f8907bbfSEdison Ai 
356f8907bbfSEdison Ai 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
357f8907bbfSEdison Ai 	offset = 0;
358f8907bbfSEdison Ai 	while ((offset < rsa.len - 1) && (buf[offset] == 0))
359f8907bbfSEdison Ai 		offset++;
360f8907bbfSEdison Ai 
361f8907bbfSEdison Ai 	if (*dst_len < rsa.len - offset) {
362f8907bbfSEdison Ai 		*dst_len = rsa.len - offset;
363f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
364f8907bbfSEdison Ai 		goto out;
365f8907bbfSEdison Ai 	}
366f8907bbfSEdison Ai 	*dst_len = rsa.len - offset;
367f8907bbfSEdison Ai 	memcpy(dst, buf + offset, *dst_len);
368f8907bbfSEdison Ai out:
369f8907bbfSEdison Ai 	free(buf);
370f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
371f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.E);
372f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.N);
373f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
374f8907bbfSEdison Ai 
375f8907bbfSEdison Ai 	return res;
376f8907bbfSEdison Ai }
377f8907bbfSEdison Ai 
378f8907bbfSEdison Ai TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
379eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src,
380eac16613SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
381eac16613SJorge Ramirez-Ortiz 					   size_t *dst_len)
382eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_decrypt");
383eac16613SJorge Ramirez-Ortiz 
384eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
385eac16613SJorge Ramirez-Ortiz 					      const uint8_t *src,
386eac16613SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
387eac16613SJorge Ramirez-Ortiz 					      size_t *dst_len)
388f8907bbfSEdison Ai {
389f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
39032b31808SJens Wiklander 	mbedtls_rsa_context rsa = { };
391f8907bbfSEdison Ai 	int lmd_res = 0;
392f8907bbfSEdison Ai 	uint8_t *buf = NULL;
393f8907bbfSEdison Ai 	unsigned long blen = 0;
394f8907bbfSEdison Ai 	unsigned long offset = 0;
395f8907bbfSEdison Ai 
39632b31808SJens Wiklander 	res = rsa_init_and_complete_from_key_pair(&rsa, key);
39732b31808SJens Wiklander 	if (res)
39832b31808SJens Wiklander 		return res;
399f8907bbfSEdison Ai 
400f8907bbfSEdison Ai 	blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
401f8907bbfSEdison Ai 	buf = malloc(blen);
402f8907bbfSEdison Ai 	if (!buf) {
403f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
404f8907bbfSEdison Ai 		goto out;
405f8907bbfSEdison Ai 	}
406f8907bbfSEdison Ai 
407f8907bbfSEdison Ai 	memset(buf, 0, blen);
408f8907bbfSEdison Ai 	memcpy(buf + rsa.len - src_len, src, src_len);
409f8907bbfSEdison Ai 
41032b31808SJens Wiklander 	lmd_res = mbedtls_rsa_private(&rsa, mbd_rand, NULL, buf, buf);
411f8907bbfSEdison Ai 	if (lmd_res != 0) {
412f8907bbfSEdison Ai 		FMSG("mbedtls_rsa_private() returned 0x%x", -lmd_res);
413f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
414f8907bbfSEdison Ai 		goto out;
415f8907bbfSEdison Ai 	}
416f8907bbfSEdison Ai 
417f8907bbfSEdison Ai 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
418f8907bbfSEdison Ai 	offset = 0;
419f8907bbfSEdison Ai 	while ((offset < rsa.len - 1) && (buf[offset] == 0))
420f8907bbfSEdison Ai 		offset++;
421f8907bbfSEdison Ai 
422f8907bbfSEdison Ai 	if (*dst_len < rsa.len - offset) {
423f8907bbfSEdison Ai 		*dst_len = rsa.len - offset;
424f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
425f8907bbfSEdison Ai 		goto out;
426f8907bbfSEdison Ai 	}
427f8907bbfSEdison Ai 	*dst_len = rsa.len - offset;
428f8907bbfSEdison Ai 	memcpy(dst, (char *)buf + offset, *dst_len);
429f8907bbfSEdison Ai out:
430f8907bbfSEdison Ai 	if (buf)
431f8907bbfSEdison Ai 		free(buf);
43232b31808SJens Wiklander 	mbd_rsa_free(&rsa, key);
433f8907bbfSEdison Ai 	return res;
434f8907bbfSEdison Ai }
435f8907bbfSEdison Ai 
436eac16613SJorge Ramirez-Ortiz TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo,
437eac16613SJorge Ramirez-Ortiz 					struct rsa_keypair *key,
438eac16613SJorge Ramirez-Ortiz 					const uint8_t *label __unused,
439eac16613SJorge Ramirez-Ortiz 					size_t label_len __unused,
440*86ee543bSSami Tolvanen 					uint32_t mgf_algo,
441eac16613SJorge Ramirez-Ortiz 					const uint8_t *src, size_t src_len,
442eac16613SJorge Ramirez-Ortiz 					uint8_t *dst, size_t *dst_len)
443eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_decrypt");
444eac16613SJorge Ramirez-Ortiz 
445eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
446eac16613SJorge Ramirez-Ortiz 					   struct rsa_keypair *key,
447f8907bbfSEdison Ai 					   const uint8_t *label __unused,
448f8907bbfSEdison Ai 					   size_t label_len __unused,
449*86ee543bSSami Tolvanen 					   uint32_t mgf_algo,
450f8907bbfSEdison Ai 					   const uint8_t *src, size_t src_len,
451f8907bbfSEdison Ai 					   uint8_t *dst, size_t *dst_len)
452f8907bbfSEdison Ai {
453f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
454f8907bbfSEdison Ai 	int lmd_res = 0;
455f8907bbfSEdison Ai 	int lmd_padding = 0;
456f8907bbfSEdison Ai 	size_t blen = 0;
457f8907bbfSEdison Ai 	size_t mod_size = 0;
458f8907bbfSEdison Ai 	void *buf = NULL;
45932b31808SJens Wiklander 	mbedtls_rsa_context rsa = { };
460f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
461f8907bbfSEdison Ai 	uint32_t md_algo = MBEDTLS_MD_NONE;
462f8907bbfSEdison Ai 
46332b31808SJens Wiklander 	res = rsa_init_and_complete_from_key_pair(&rsa, key);
46432b31808SJens Wiklander 	if (res)
46532b31808SJens Wiklander 		return res;
466f8907bbfSEdison Ai 
467f8907bbfSEdison Ai 	/*
468f8907bbfSEdison Ai 	 * Use a temporary buffer since we don't know exactly how large
469f8907bbfSEdison Ai 	 * the required size of the out buffer without doing a partial
470f8907bbfSEdison Ai 	 * decrypt. We know the upper bound though.
471f8907bbfSEdison Ai 	 */
472f8907bbfSEdison Ai 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
473f8907bbfSEdison Ai 		mod_size = crypto_bignum_num_bytes(key->n);
474f8907bbfSEdison Ai 		blen = mod_size - 11;
475f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
476f8907bbfSEdison Ai 	} else {
477f8907bbfSEdison Ai 		/* Decoded message is always shorter than encrypted message */
478f8907bbfSEdison Ai 		blen = src_len;
479f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
480f8907bbfSEdison Ai 	}
481f8907bbfSEdison Ai 
482f8907bbfSEdison Ai 	buf = malloc(blen);
483f8907bbfSEdison Ai 	if (!buf) {
484f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
485f8907bbfSEdison Ai 		goto out;
486f8907bbfSEdison Ai 	}
487f8907bbfSEdison Ai 
488f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
489f8907bbfSEdison Ai 	if (!pk_info) {
490f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
491f8907bbfSEdison Ai 		goto out;
492f8907bbfSEdison Ai 	}
493f8907bbfSEdison Ai 
494f8907bbfSEdison Ai 	/*
495f8907bbfSEdison Ai 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
496f8907bbfSEdison Ai 	 * not be used in rsa, so skip it here.
497f8907bbfSEdison Ai 	 */
498f8907bbfSEdison Ai 	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
499f8907bbfSEdison Ai 		md_algo = tee_algo_to_mbedtls_hash_algo(algo);
500f8907bbfSEdison Ai 		if (md_algo == MBEDTLS_MD_NONE) {
501f8907bbfSEdison Ai 			res = TEE_ERROR_NOT_SUPPORTED;
502f8907bbfSEdison Ai 			goto out;
503f8907bbfSEdison Ai 		}
504*86ee543bSSami Tolvanen 		if (md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) {
505*86ee543bSSami Tolvanen 			DMSG("Using a different MGF1 algorithm is not supported");
506*86ee543bSSami Tolvanen 			res = TEE_ERROR_NOT_SUPPORTED;
507*86ee543bSSami Tolvanen 			goto out;
508*86ee543bSSami Tolvanen 		}
509f8907bbfSEdison Ai 	}
510f8907bbfSEdison Ai 
511f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
512f8907bbfSEdison Ai 
513f8907bbfSEdison Ai 	lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen,
514f8907bbfSEdison Ai 					blen, mbd_rand, NULL);
515f8907bbfSEdison Ai 	if (lmd_res != 0) {
516f8907bbfSEdison Ai 		FMSG("decrypt_func() returned 0x%x", -lmd_res);
517f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
518f8907bbfSEdison Ai 		goto out;
519f8907bbfSEdison Ai 	}
520f8907bbfSEdison Ai 
521f8907bbfSEdison Ai 	if (*dst_len < blen) {
522f8907bbfSEdison Ai 		*dst_len = blen;
523f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
524f8907bbfSEdison Ai 		goto out;
525f8907bbfSEdison Ai 	}
526f8907bbfSEdison Ai 
527f8907bbfSEdison Ai 	res = TEE_SUCCESS;
528f8907bbfSEdison Ai 	*dst_len = blen;
529f8907bbfSEdison Ai 	memcpy(dst, buf, blen);
530f8907bbfSEdison Ai out:
531f8907bbfSEdison Ai 	if (buf)
532f8907bbfSEdison Ai 		free(buf);
53332b31808SJens Wiklander 	mbd_rsa_free(&rsa, key);
534f8907bbfSEdison Ai 	return res;
535f8907bbfSEdison Ai }
536f8907bbfSEdison Ai 
537f8907bbfSEdison Ai TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
538f8907bbfSEdison Ai 					struct rsa_public_key *key,
539f8907bbfSEdison Ai 					const uint8_t *label __unused,
540f8907bbfSEdison Ai 					size_t label_len __unused,
541*86ee543bSSami Tolvanen 					uint32_t mgf_algo,
542f8907bbfSEdison Ai 					const uint8_t *src, size_t src_len,
543f8907bbfSEdison Ai 					uint8_t *dst, size_t *dst_len)
544eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_encrypt");
545eac16613SJorge Ramirez-Ortiz 
546eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
547eac16613SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
548eac16613SJorge Ramirez-Ortiz 					   const uint8_t *label __unused,
549eac16613SJorge Ramirez-Ortiz 					   size_t label_len __unused,
550*86ee543bSSami Tolvanen 					   uint32_t mgf_algo,
551eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src, size_t src_len,
552eac16613SJorge Ramirez-Ortiz 					   uint8_t *dst, size_t *dst_len)
553f8907bbfSEdison Ai {
554f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
555f8907bbfSEdison Ai 	int lmd_res = 0;
556f8907bbfSEdison Ai 	int lmd_padding = 0;
557f8907bbfSEdison Ai 	size_t mod_size = 0;
558f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
559f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
560f8907bbfSEdison Ai 	uint32_t md_algo = MBEDTLS_MD_NONE;
561f8907bbfSEdison Ai 
562f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
56332b31808SJens Wiklander 	mbedtls_rsa_init(&rsa);
564f8907bbfSEdison Ai 
565f8907bbfSEdison Ai 	rsa.E = *(mbedtls_mpi *)key->e;
566f8907bbfSEdison Ai 	rsa.N = *(mbedtls_mpi *)key->n;
567f8907bbfSEdison Ai 
568f8907bbfSEdison Ai 	mod_size = crypto_bignum_num_bytes(key->n);
569f8907bbfSEdison Ai 	if (*dst_len < mod_size) {
570f8907bbfSEdison Ai 		*dst_len = mod_size;
571f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
572f8907bbfSEdison Ai 		goto out;
573f8907bbfSEdison Ai 	}
574f8907bbfSEdison Ai 	*dst_len = mod_size;
575f8907bbfSEdison Ai 	rsa.len = mod_size;
576f8907bbfSEdison Ai 
577f8907bbfSEdison Ai 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
578f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
579f8907bbfSEdison Ai 	else
580f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
581f8907bbfSEdison Ai 
582f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
583f8907bbfSEdison Ai 	if (!pk_info) {
584f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
585f8907bbfSEdison Ai 		goto out;
586f8907bbfSEdison Ai 	}
587f8907bbfSEdison Ai 
588f8907bbfSEdison Ai 	/*
589f8907bbfSEdison Ai 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
590f8907bbfSEdison Ai 	 * not be used in rsa, so skip it here.
591f8907bbfSEdison Ai 	 */
592f8907bbfSEdison Ai 	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
593f8907bbfSEdison Ai 		md_algo = tee_algo_to_mbedtls_hash_algo(algo);
594*86ee543bSSami Tolvanen 		/* Using a different MGF1 algorithm is not supported. */
595*86ee543bSSami Tolvanen 		if (md_algo == MBEDTLS_MD_NONE ||
596*86ee543bSSami Tolvanen 		    md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) {
597f8907bbfSEdison Ai 			res = TEE_ERROR_NOT_SUPPORTED;
598f8907bbfSEdison Ai 			goto out;
599f8907bbfSEdison Ai 		}
600f8907bbfSEdison Ai 	}
601f8907bbfSEdison Ai 
602f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
603f8907bbfSEdison Ai 
604f8907bbfSEdison Ai 	lmd_res = pk_info->encrypt_func(&rsa, src, src_len, dst, dst_len,
605f8907bbfSEdison Ai 					*dst_len, mbd_rand, NULL);
606f8907bbfSEdison Ai 	if (lmd_res != 0) {
607f8907bbfSEdison Ai 		FMSG("encrypt_func() returned 0x%x", -lmd_res);
608f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
609f8907bbfSEdison Ai 		goto out;
610f8907bbfSEdison Ai 	}
611f8907bbfSEdison Ai 	res = TEE_SUCCESS;
612f8907bbfSEdison Ai out:
613f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
614f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.E);
615f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.N);
616f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
617f8907bbfSEdison Ai 	return res;
618f8907bbfSEdison Ai }
619f8907bbfSEdison Ai 
620f8907bbfSEdison Ai TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
621eac16613SJorge Ramirez-Ortiz 				      int salt_len __unused,
622eac16613SJorge Ramirez-Ortiz 				      const uint8_t *msg, size_t msg_len,
623eac16613SJorge Ramirez-Ortiz 				      uint8_t *sig, size_t *sig_len)
624eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_sign");
625eac16613SJorge Ramirez-Ortiz 
626eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
627eac16613SJorge Ramirez-Ortiz 					 int salt_len __unused,
628eac16613SJorge Ramirez-Ortiz 					 const uint8_t *msg, size_t msg_len,
629eac16613SJorge Ramirez-Ortiz 					 uint8_t *sig, size_t *sig_len)
630f8907bbfSEdison Ai {
631f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
632f8907bbfSEdison Ai 	int lmd_res = 0;
633f8907bbfSEdison Ai 	int lmd_padding = 0;
634f8907bbfSEdison Ai 	size_t mod_size = 0;
635f8907bbfSEdison Ai 	size_t hash_size = 0;
63632b31808SJens Wiklander 	mbedtls_rsa_context rsa = { };
637f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
638f8907bbfSEdison Ai 	uint32_t md_algo = 0;
639f8907bbfSEdison Ai 
64032b31808SJens Wiklander 	res = rsa_init_and_complete_from_key_pair(&rsa, key);
64132b31808SJens Wiklander 	if (res)
64232b31808SJens Wiklander 		return res;
643f8907bbfSEdison Ai 
644f8907bbfSEdison Ai 	switch (algo) {
645f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
646f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
647f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
648f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
649f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
650f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
651f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
652f8907bbfSEdison Ai 		break;
653f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
654f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
655f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
656f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
657f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
658f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
659f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
660f8907bbfSEdison Ai 		break;
661f8907bbfSEdison Ai 	default:
662f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
663f8907bbfSEdison Ai 		goto err;
664f8907bbfSEdison Ai 	}
665f8907bbfSEdison Ai 
6667c767434SAlbert Schwarzkopf 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
667f8907bbfSEdison Ai 				      &hash_size);
668f8907bbfSEdison Ai 	if (res != TEE_SUCCESS)
669f8907bbfSEdison Ai 		goto err;
670f8907bbfSEdison Ai 
671f8907bbfSEdison Ai 	if (msg_len != hash_size) {
672f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
673f8907bbfSEdison Ai 		goto err;
674f8907bbfSEdison Ai 	}
675f8907bbfSEdison Ai 
676f8907bbfSEdison Ai 	mod_size = crypto_bignum_num_bytes(key->n);
677f8907bbfSEdison Ai 	if (*sig_len < mod_size) {
678f8907bbfSEdison Ai 		*sig_len = mod_size;
679f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
680f8907bbfSEdison Ai 		goto err;
681f8907bbfSEdison Ai 	}
682f8907bbfSEdison Ai 	rsa.len = mod_size;
683f8907bbfSEdison Ai 
684f8907bbfSEdison Ai 	md_algo = tee_algo_to_mbedtls_hash_algo(algo);
685f8907bbfSEdison Ai 	if (md_algo == MBEDTLS_MD_NONE) {
686f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
687f8907bbfSEdison Ai 		goto err;
688f8907bbfSEdison Ai 	}
689f8907bbfSEdison Ai 
690f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
691f8907bbfSEdison Ai 	if (!pk_info) {
692f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
693f8907bbfSEdison Ai 		goto err;
694f8907bbfSEdison Ai 	}
695f8907bbfSEdison Ai 
696f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
697f8907bbfSEdison Ai 
698f8907bbfSEdison Ai 	lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig,
69932b31808SJens Wiklander 				     *sig_len, sig_len, mbd_rand, NULL);
700f8907bbfSEdison Ai 	if (lmd_res != 0) {
701f8907bbfSEdison Ai 		FMSG("sign_func failed, returned 0x%x", -lmd_res);
702f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
703f8907bbfSEdison Ai 		goto err;
704f8907bbfSEdison Ai 	}
705f8907bbfSEdison Ai 	res = TEE_SUCCESS;
706f8907bbfSEdison Ai err:
70732b31808SJens Wiklander 	mbd_rsa_free(&rsa, key);
708f8907bbfSEdison Ai 	return res;
709f8907bbfSEdison Ai }
710f8907bbfSEdison Ai 
711f8907bbfSEdison Ai TEE_Result crypto_acipher_rsassa_verify(uint32_t algo,
712f8907bbfSEdison Ai 					struct rsa_public_key *key,
713f8907bbfSEdison Ai 					int salt_len __unused,
714f8907bbfSEdison Ai 					const uint8_t *msg,
715f8907bbfSEdison Ai 					size_t msg_len, const uint8_t *sig,
716f8907bbfSEdison Ai 					size_t sig_len)
717eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_verify");
718eac16613SJorge Ramirez-Ortiz 
719eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
720eac16613SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
721eac16613SJorge Ramirez-Ortiz 					   int salt_len __unused,
722eac16613SJorge Ramirez-Ortiz 					   const uint8_t *msg,
723eac16613SJorge Ramirez-Ortiz 					   size_t msg_len, const uint8_t *sig,
724eac16613SJorge Ramirez-Ortiz 					   size_t sig_len)
725f8907bbfSEdison Ai {
726f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
727f8907bbfSEdison Ai 	int lmd_res = 0;
728f8907bbfSEdison Ai 	int lmd_padding = 0;
729f8907bbfSEdison Ai 	size_t hash_size = 0;
730f8907bbfSEdison Ai 	size_t bigint_size = 0;
731f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
732f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
733f8907bbfSEdison Ai 	uint32_t md_algo = 0;
73498ada65eSJens Wiklander 	struct ftmn ftmn = { };
73598ada65eSJens Wiklander 	unsigned long arg_hash = 0;
73698ada65eSJens Wiklander 
73798ada65eSJens Wiklander 	/*
73898ada65eSJens Wiklander 	 * The caller expects to call crypto_acipher_rsassa_verify(),
73998ada65eSJens Wiklander 	 * update the hash as needed.
74098ada65eSJens Wiklander 	 */
74198ada65eSJens Wiklander 	FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify"));
742f8907bbfSEdison Ai 
743f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
74432b31808SJens Wiklander 	mbedtls_rsa_init(&rsa);
745f8907bbfSEdison Ai 
746f8907bbfSEdison Ai 	rsa.E = *(mbedtls_mpi *)key->e;
747f8907bbfSEdison Ai 	rsa.N = *(mbedtls_mpi *)key->n;
748f8907bbfSEdison Ai 
7497c767434SAlbert Schwarzkopf 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
750f8907bbfSEdison Ai 				      &hash_size);
751f8907bbfSEdison Ai 	if (res != TEE_SUCCESS)
752f8907bbfSEdison Ai 		goto err;
753f8907bbfSEdison Ai 
754f8907bbfSEdison Ai 	if (msg_len != hash_size) {
755f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
756f8907bbfSEdison Ai 		goto err;
757f8907bbfSEdison Ai 	}
758f8907bbfSEdison Ai 
759f8907bbfSEdison Ai 	bigint_size = crypto_bignum_num_bytes(key->n);
760f8907bbfSEdison Ai 	if (sig_len < bigint_size) {
761c282ebd6Slubing 		res = TEE_ERROR_SIGNATURE_INVALID;
762f8907bbfSEdison Ai 		goto err;
763f8907bbfSEdison Ai 	}
764f8907bbfSEdison Ai 
765f8907bbfSEdison Ai 	rsa.len = bigint_size;
766f8907bbfSEdison Ai 
767f8907bbfSEdison Ai 	switch (algo) {
768f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
769f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
770f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
771f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
772f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
773f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
77498ada65eSJens Wiklander 		arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pkcs1_v15_verify");
775f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
776f8907bbfSEdison Ai 		break;
777f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
778f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
779f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
780f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
781f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
782f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
78398ada65eSJens Wiklander 		arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pss_verify_ext");
784f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
785f8907bbfSEdison Ai 		break;
786f8907bbfSEdison Ai 	default:
787f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
788f8907bbfSEdison Ai 		goto err;
789f8907bbfSEdison Ai 	}
790f8907bbfSEdison Ai 
791f8907bbfSEdison Ai 	md_algo = tee_algo_to_mbedtls_hash_algo(algo);
792f8907bbfSEdison Ai 	if (md_algo == MBEDTLS_MD_NONE) {
793f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
794f8907bbfSEdison Ai 		goto err;
795f8907bbfSEdison Ai 	}
796f8907bbfSEdison Ai 
797f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
798f8907bbfSEdison Ai 	if (!pk_info) {
799f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
800f8907bbfSEdison Ai 		goto err;
801f8907bbfSEdison Ai 	}
802f8907bbfSEdison Ai 
803f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
804f8907bbfSEdison Ai 
80598ada65eSJens Wiklander 	FTMN_PUSH_LINKED_CALL(&ftmn, arg_hash);
806f8907bbfSEdison Ai 	lmd_res = pk_info->verify_func(&rsa, md_algo, msg, msg_len,
807f8907bbfSEdison Ai 				       sig, sig_len);
80898ada65eSJens Wiklander 	if (!lmd_res)
80998ada65eSJens Wiklander 		FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, lmd_res);
81098ada65eSJens Wiklander 	FTMN_POP_LINKED_CALL(&ftmn);
811f8907bbfSEdison Ai 	if (lmd_res != 0) {
812f8907bbfSEdison Ai 		FMSG("verify_func failed, returned 0x%x", -lmd_res);
813f8907bbfSEdison Ai 		res = TEE_ERROR_SIGNATURE_INVALID;
814f8907bbfSEdison Ai 		goto err;
815f8907bbfSEdison Ai 	}
816f8907bbfSEdison Ai 	res = TEE_SUCCESS;
81798ada65eSJens Wiklander 	goto out;
81898ada65eSJens Wiklander 
819f8907bbfSEdison Ai err:
82098ada65eSJens Wiklander 	FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res);
82198ada65eSJens Wiklander out:
82298ada65eSJens Wiklander 	FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res);
823f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
824f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.E);
825f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.N);
826f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
827f8907bbfSEdison Ai 	return res;
828f8907bbfSEdison Ai }
829