xref: /optee_os/lib/libmbedtls/core/rsa.c (revision e2ec831cb07ed0099535c7c140cb6338aa62816a)
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 <mbedtls/pk_internal.h>
14f8907bbfSEdison Ai #include <stdlib.h>
15f8907bbfSEdison Ai #include <string.h>
16f8907bbfSEdison Ai #include <tee/tee_cryp_utl.h>
17f8907bbfSEdison Ai #include <utee_defines.h>
1898ada65eSJens Wiklander #include <fault_mitigation.h>
19f8907bbfSEdison Ai 
206630b846SJerome Forissier #include "mbed_helpers.h"
21f8907bbfSEdison Ai 
22f8907bbfSEdison Ai static TEE_Result get_tee_result(int lmd_res)
23f8907bbfSEdison Ai {
24f8907bbfSEdison Ai 	switch (lmd_res) {
25f8907bbfSEdison Ai 	case 0:
26f8907bbfSEdison Ai 		return TEE_SUCCESS;
273ddd5cd7Sliushiwei 	case MBEDTLS_ERR_RSA_PRIVATE_FAILED +
283ddd5cd7Sliushiwei 		MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
29f8907bbfSEdison Ai 	case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:
30f8907bbfSEdison Ai 	case MBEDTLS_ERR_RSA_INVALID_PADDING:
31f8907bbfSEdison Ai 	case MBEDTLS_ERR_PK_TYPE_MISMATCH:
32f8907bbfSEdison Ai 		return TEE_ERROR_BAD_PARAMETERS;
33f8907bbfSEdison Ai 	case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
34f8907bbfSEdison Ai 		return TEE_ERROR_SHORT_BUFFER;
35f8907bbfSEdison Ai 	default:
36f8907bbfSEdison Ai 		return TEE_ERROR_BAD_STATE;
37f8907bbfSEdison Ai 	}
38f8907bbfSEdison Ai }
39f8907bbfSEdison Ai 
40f8907bbfSEdison Ai static uint32_t tee_algo_to_mbedtls_hash_algo(uint32_t algo)
41f8907bbfSEdison Ai {
42f8907bbfSEdison Ai 	switch (algo) {
43f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA1)
44f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
45f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
46f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
47f8907bbfSEdison Ai 	case TEE_ALG_SHA1:
48f8907bbfSEdison Ai 	case TEE_ALG_DSA_SHA1:
49f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA1:
50f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA1;
51f8907bbfSEdison Ai #endif
52f8907bbfSEdison Ai #if defined(CFG_CRYPTO_MD5)
53f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
54f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
55f5c3d85aSJulien Masson 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5:
56f8907bbfSEdison Ai 	case TEE_ALG_MD5:
57f8907bbfSEdison Ai 	case TEE_ALG_HMAC_MD5:
58f8907bbfSEdison Ai 		return MBEDTLS_MD_MD5;
59f8907bbfSEdison Ai #endif
60f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA224)
61f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
62f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
63f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
64f8907bbfSEdison Ai 	case TEE_ALG_SHA224:
65f8907bbfSEdison Ai 	case TEE_ALG_DSA_SHA224:
66f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA224:
67f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA224;
68f8907bbfSEdison Ai #endif
69f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA256)
70f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
71f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
72f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
73f8907bbfSEdison Ai 	case TEE_ALG_SHA256:
74f8907bbfSEdison Ai 	case TEE_ALG_DSA_SHA256:
75f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA256:
76f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA256;
77f8907bbfSEdison Ai #endif
78f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA384)
79f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
80f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
81f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
82f8907bbfSEdison Ai 	case TEE_ALG_SHA384:
83f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA384:
84f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA384;
85f8907bbfSEdison Ai #endif
86f8907bbfSEdison Ai #if defined(CFG_CRYPTO_SHA512)
87f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
88f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
89f8907bbfSEdison Ai 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
90f8907bbfSEdison Ai 	case TEE_ALG_SHA512:
91f8907bbfSEdison Ai 	case TEE_ALG_HMAC_SHA512:
92f8907bbfSEdison Ai 		return MBEDTLS_MD_SHA512;
93f8907bbfSEdison Ai #endif
94f8907bbfSEdison Ai 	default:
95f8907bbfSEdison Ai 		return MBEDTLS_MD_NONE;
96f8907bbfSEdison Ai 	}
97f8907bbfSEdison Ai }
98f8907bbfSEdison Ai 
99f8907bbfSEdison Ai static void rsa_init_from_key_pair(mbedtls_rsa_context *rsa,
100f8907bbfSEdison Ai 				struct rsa_keypair *key)
101f8907bbfSEdison Ai {
102f8907bbfSEdison Ai 	mbedtls_rsa_init(rsa, 0, 0);
103f8907bbfSEdison Ai 
104f8907bbfSEdison Ai 	rsa->E = *(mbedtls_mpi *)key->e;
105f8907bbfSEdison Ai 	rsa->N = *(mbedtls_mpi *)key->n;
106f8907bbfSEdison Ai 	rsa->D = *(mbedtls_mpi *)key->d;
107f8907bbfSEdison Ai 	if (key->p && crypto_bignum_num_bytes(key->p)) {
108f8907bbfSEdison Ai 		rsa->P = *(mbedtls_mpi *)key->p;
109f8907bbfSEdison Ai 		rsa->Q = *(mbedtls_mpi *)key->q;
110f8907bbfSEdison Ai 		rsa->QP = *(mbedtls_mpi *)key->qp;
111f8907bbfSEdison Ai 		rsa->DP = *(mbedtls_mpi *)key->dp;
112f8907bbfSEdison Ai 		rsa->DQ = *(mbedtls_mpi *)key->dq;
113f8907bbfSEdison Ai 	}
114f8907bbfSEdison Ai 	rsa->len = mbedtls_mpi_size(&rsa->N);
115f8907bbfSEdison Ai }
116f8907bbfSEdison Ai 
117f8907bbfSEdison Ai static void mbd_rsa_free(mbedtls_rsa_context *rsa)
118f8907bbfSEdison Ai {
119f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
120f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->E);
121f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->N);
122f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa->D);
123f8907bbfSEdison Ai 	if (mbedtls_mpi_size(&rsa->P)) {
124f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->P);
125f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->Q);
126f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->QP);
127f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->DP);
128f8907bbfSEdison Ai 		mbedtls_mpi_init(&rsa->DQ);
129f8907bbfSEdison Ai 	}
130f8907bbfSEdison Ai 	mbedtls_rsa_free(rsa);
131f8907bbfSEdison Ai }
132f8907bbfSEdison Ai 
133f8907bbfSEdison Ai TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
134f8907bbfSEdison Ai 					    size_t key_size_bits)
135eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_keypair");
136eac16613SJorge Ramirez-Ortiz 
137eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
138eac16613SJorge Ramirez-Ortiz 					       size_t key_size_bits)
139f8907bbfSEdison Ai {
140f8907bbfSEdison Ai 	memset(s, 0, sizeof(*s));
141f8907bbfSEdison Ai 	s->e = crypto_bignum_allocate(key_size_bits);
142f8907bbfSEdison Ai 	if (!s->e)
143f8907bbfSEdison Ai 		goto err;
144f8907bbfSEdison Ai 	s->d = crypto_bignum_allocate(key_size_bits);
145f8907bbfSEdison Ai 	if (!s->d)
146f8907bbfSEdison Ai 		goto err;
147f8907bbfSEdison Ai 	s->n = crypto_bignum_allocate(key_size_bits);
148f8907bbfSEdison Ai 	if (!s->n)
149f8907bbfSEdison Ai 		goto err;
150f8907bbfSEdison Ai 	s->p = crypto_bignum_allocate(key_size_bits);
151f8907bbfSEdison Ai 	if (!s->p)
152f8907bbfSEdison Ai 		goto err;
153f8907bbfSEdison Ai 	s->q = crypto_bignum_allocate(key_size_bits);
154f8907bbfSEdison Ai 	if (!s->q)
155f8907bbfSEdison Ai 		goto err;
156f8907bbfSEdison Ai 	s->qp = crypto_bignum_allocate(key_size_bits);
157f8907bbfSEdison Ai 	if (!s->qp)
158f8907bbfSEdison Ai 		goto err;
159f8907bbfSEdison Ai 	s->dp = crypto_bignum_allocate(key_size_bits);
160f8907bbfSEdison Ai 	if (!s->dp)
161f8907bbfSEdison Ai 		goto err;
162f8907bbfSEdison Ai 	s->dq = crypto_bignum_allocate(key_size_bits);
163f8907bbfSEdison Ai 	if (!s->dq)
164f8907bbfSEdison Ai 		goto err;
165f8907bbfSEdison Ai 
166f8907bbfSEdison Ai 	return TEE_SUCCESS;
167f8907bbfSEdison Ai err:
1681ab1ebd8SJerome Forissier 	crypto_acipher_free_rsa_keypair(s);
169f8907bbfSEdison Ai 	return TEE_ERROR_OUT_OF_MEMORY;
170f8907bbfSEdison Ai }
171f8907bbfSEdison Ai 
172f8907bbfSEdison Ai TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
173f8907bbfSEdison Ai 					       size_t key_size_bits)
174eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_alloc_rsa_public_key");
175eac16613SJorge Ramirez-Ortiz 
176eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s,
177eac16613SJorge Ramirez-Ortiz 						  size_t key_size_bits)
178f8907bbfSEdison Ai {
179f8907bbfSEdison Ai 	memset(s, 0, sizeof(*s));
180f8907bbfSEdison Ai 	s->e = crypto_bignum_allocate(key_size_bits);
181f8907bbfSEdison Ai 	if (!s->e)
182f8907bbfSEdison Ai 		return TEE_ERROR_OUT_OF_MEMORY;
183f8907bbfSEdison Ai 	s->n = crypto_bignum_allocate(key_size_bits);
184f8907bbfSEdison Ai 	if (!s->n)
185f8907bbfSEdison Ai 		goto err;
186f8907bbfSEdison Ai 	return TEE_SUCCESS;
187f8907bbfSEdison Ai err:
188*e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
189f8907bbfSEdison Ai 	return TEE_ERROR_OUT_OF_MEMORY;
190f8907bbfSEdison Ai }
191f8907bbfSEdison Ai 
192f8907bbfSEdison Ai void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
193eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_public_key");
194eac16613SJorge Ramirez-Ortiz 
195eac16613SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s)
196f8907bbfSEdison Ai {
197f8907bbfSEdison Ai 	if (!s)
198f8907bbfSEdison Ai 		return;
199*e2ec831cSJihwan Park 	crypto_bignum_free(&s->n);
200*e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
201f8907bbfSEdison Ai }
202f8907bbfSEdison Ai 
203a1d5c81fSElias von Däniken void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
204eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_free_rsa_keypair");
205eac16613SJorge Ramirez-Ortiz 
206eac16613SJorge Ramirez-Ortiz void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s)
207a1d5c81fSElias von Däniken {
208a1d5c81fSElias von Däniken 	if (!s)
209a1d5c81fSElias von Däniken 		return;
210*e2ec831cSJihwan Park 	crypto_bignum_free(&s->e);
211*e2ec831cSJihwan Park 	crypto_bignum_free(&s->d);
212*e2ec831cSJihwan Park 	crypto_bignum_free(&s->n);
213*e2ec831cSJihwan Park 	crypto_bignum_free(&s->p);
214*e2ec831cSJihwan Park 	crypto_bignum_free(&s->q);
215*e2ec831cSJihwan Park 	crypto_bignum_free(&s->qp);
216*e2ec831cSJihwan Park 	crypto_bignum_free(&s->dp);
217*e2ec831cSJihwan Park 	crypto_bignum_free(&s->dq);
218a1d5c81fSElias von Däniken }
219a1d5c81fSElias von Däniken 
220eac16613SJorge Ramirez-Ortiz TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
221eac16613SJorge Ramirez-Ortiz 				      size_t key_size)
222eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_gen_rsa_key");
223eac16613SJorge Ramirez-Ortiz 
224eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key,
225eac16613SJorge Ramirez-Ortiz 					 size_t key_size)
226f8907bbfSEdison Ai {
227f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
228f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
2297910f4d8SLars Persson 	mbedtls_ctr_drbg_context rngctx;
230f8907bbfSEdison Ai 	int lmd_res = 0;
231f8907bbfSEdison Ai 	uint32_t e = 0;
232f8907bbfSEdison Ai 
2337910f4d8SLars Persson 	mbedtls_ctr_drbg_init(&rngctx);
2347910f4d8SLars Persson 	if (mbedtls_ctr_drbg_seed(&rngctx, mbd_rand, NULL, NULL, 0))
2357910f4d8SLars Persson 		return TEE_ERROR_BAD_STATE;
2367910f4d8SLars Persson 
237f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
238f8907bbfSEdison Ai 	mbedtls_rsa_init(&rsa, 0, 0);
239f8907bbfSEdison Ai 
240f8907bbfSEdison Ai 	/* get the public exponent */
241f8907bbfSEdison Ai 	mbedtls_mpi_write_binary((mbedtls_mpi *)key->e,
242f8907bbfSEdison Ai 				 (unsigned char *)&e, sizeof(uint32_t));
243f8907bbfSEdison Ai 
244f8907bbfSEdison Ai 	e = TEE_U32_FROM_BIG_ENDIAN(e);
2457910f4d8SLars Persson 	lmd_res = mbedtls_rsa_gen_key(&rsa, mbedtls_ctr_drbg_random, &rngctx,
2467910f4d8SLars Persson 				      key_size, (int)e);
2477910f4d8SLars Persson 	mbedtls_ctr_drbg_free(&rngctx);
248f8907bbfSEdison Ai 	if (lmd_res != 0) {
249f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
250f8907bbfSEdison Ai 	} else if ((size_t)mbedtls_mpi_bitlen(&rsa.N) != key_size) {
251f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
252f8907bbfSEdison Ai 	} else {
253f8907bbfSEdison Ai 		/* Copy the key */
254f8907bbfSEdison Ai 		crypto_bignum_copy(key->e, (void *)&rsa.E);
255f8907bbfSEdison Ai 		crypto_bignum_copy(key->d, (void *)&rsa.D);
256f8907bbfSEdison Ai 		crypto_bignum_copy(key->n, (void *)&rsa.N);
257f8907bbfSEdison Ai 		crypto_bignum_copy(key->p, (void *)&rsa.P);
258f8907bbfSEdison Ai 
259f8907bbfSEdison Ai 		crypto_bignum_copy(key->q, (void *)&rsa.Q);
260f8907bbfSEdison Ai 		crypto_bignum_copy(key->qp, (void *)&rsa.QP);
261f8907bbfSEdison Ai 		crypto_bignum_copy(key->dp, (void *)&rsa.DP);
262f8907bbfSEdison Ai 		crypto_bignum_copy(key->dq, (void *)&rsa.DQ);
263f8907bbfSEdison Ai 
264f8907bbfSEdison Ai 		res = TEE_SUCCESS;
265f8907bbfSEdison Ai 	}
266f8907bbfSEdison Ai 
267f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
268f8907bbfSEdison Ai 
269f8907bbfSEdison Ai 	return res;
270f8907bbfSEdison Ai }
271f8907bbfSEdison Ai 
272f8907bbfSEdison Ai TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
273eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src,
274eac16613SJorge Ramirez-Ortiz 					   size_t src_len, uint8_t *dst,
275eac16613SJorge Ramirez-Ortiz 					   size_t *dst_len)
276eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_encrypt");
277eac16613SJorge Ramirez-Ortiz 
278eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
279eac16613SJorge Ramirez-Ortiz 					      const uint8_t *src,
280eac16613SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
281eac16613SJorge Ramirez-Ortiz 					      size_t *dst_len)
282f8907bbfSEdison Ai {
283f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
284f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
285f8907bbfSEdison Ai 	int lmd_res = 0;
286f8907bbfSEdison Ai 	uint8_t *buf = NULL;
287f8907bbfSEdison Ai 	unsigned long blen = 0;
288f8907bbfSEdison Ai 	unsigned long offset = 0;
289f8907bbfSEdison Ai 
290f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
291f8907bbfSEdison Ai 	mbedtls_rsa_init(&rsa, 0, 0);
292f8907bbfSEdison Ai 
293f8907bbfSEdison Ai 	rsa.E = *(mbedtls_mpi *)key->e;
294f8907bbfSEdison Ai 	rsa.N = *(mbedtls_mpi *)key->n;
295f8907bbfSEdison Ai 
296f8907bbfSEdison Ai 	rsa.len = crypto_bignum_num_bytes((void *)&rsa.N);
297f8907bbfSEdison Ai 
298f8907bbfSEdison Ai 	blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
299f8907bbfSEdison Ai 	buf = malloc(blen);
300f8907bbfSEdison Ai 	if (!buf) {
301f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
302f8907bbfSEdison Ai 		goto out;
303f8907bbfSEdison Ai 	}
304f8907bbfSEdison Ai 
305f8907bbfSEdison Ai 	memset(buf, 0, blen);
306f8907bbfSEdison Ai 	memcpy(buf + rsa.len - src_len, src, src_len);
307f8907bbfSEdison Ai 
308f8907bbfSEdison Ai 	lmd_res = mbedtls_rsa_public(&rsa, buf, buf);
309f8907bbfSEdison Ai 	if (lmd_res != 0) {
310f8907bbfSEdison Ai 		FMSG("mbedtls_rsa_public() returned 0x%x", -lmd_res);
311f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
312f8907bbfSEdison Ai 		goto out;
313f8907bbfSEdison Ai 	}
314f8907bbfSEdison Ai 
315f8907bbfSEdison Ai 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
316f8907bbfSEdison Ai 	offset = 0;
317f8907bbfSEdison Ai 	while ((offset < rsa.len - 1) && (buf[offset] == 0))
318f8907bbfSEdison Ai 		offset++;
319f8907bbfSEdison Ai 
320f8907bbfSEdison Ai 	if (*dst_len < rsa.len - offset) {
321f8907bbfSEdison Ai 		*dst_len = rsa.len - offset;
322f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
323f8907bbfSEdison Ai 		goto out;
324f8907bbfSEdison Ai 	}
325f8907bbfSEdison Ai 	*dst_len = rsa.len - offset;
326f8907bbfSEdison Ai 	memcpy(dst, buf + offset, *dst_len);
327f8907bbfSEdison Ai out:
328f8907bbfSEdison Ai 	free(buf);
329f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
330f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.E);
331f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.N);
332f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
333f8907bbfSEdison Ai 
334f8907bbfSEdison Ai 	return res;
335f8907bbfSEdison Ai }
336f8907bbfSEdison Ai 
337f8907bbfSEdison Ai TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *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)
341eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsanopad_decrypt");
342eac16613SJorge Ramirez-Ortiz 
343eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
344eac16613SJorge Ramirez-Ortiz 					      const uint8_t *src,
345eac16613SJorge Ramirez-Ortiz 					      size_t src_len, uint8_t *dst,
346eac16613SJorge Ramirez-Ortiz 					      size_t *dst_len)
347f8907bbfSEdison Ai {
348f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
349f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
350f8907bbfSEdison Ai 	int lmd_res = 0;
351f8907bbfSEdison Ai 	uint8_t *buf = NULL;
352f8907bbfSEdison Ai 	unsigned long blen = 0;
353f8907bbfSEdison Ai 	unsigned long offset = 0;
354f8907bbfSEdison Ai 
355f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
356f8907bbfSEdison Ai 	rsa_init_from_key_pair(&rsa, key);
357f8907bbfSEdison Ai 
358f8907bbfSEdison Ai 	blen = CFG_CORE_BIGNUM_MAX_BITS / 8;
359f8907bbfSEdison Ai 	buf = malloc(blen);
360f8907bbfSEdison Ai 	if (!buf) {
361f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
362f8907bbfSEdison Ai 		goto out;
363f8907bbfSEdison Ai 	}
364f8907bbfSEdison Ai 
365f8907bbfSEdison Ai 	memset(buf, 0, blen);
366f8907bbfSEdison Ai 	memcpy(buf + rsa.len - src_len, src, src_len);
367f8907bbfSEdison Ai 
368f8907bbfSEdison Ai 	lmd_res = mbedtls_rsa_private(&rsa, NULL, NULL, buf, buf);
369f8907bbfSEdison Ai 	if (lmd_res != 0) {
370f8907bbfSEdison Ai 		FMSG("mbedtls_rsa_private() returned 0x%x", -lmd_res);
371f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
372f8907bbfSEdison Ai 		goto out;
373f8907bbfSEdison Ai 	}
374f8907bbfSEdison Ai 
375f8907bbfSEdison Ai 	/* Remove the zero-padding (leave one zero if buff is all zeroes) */
376f8907bbfSEdison Ai 	offset = 0;
377f8907bbfSEdison Ai 	while ((offset < rsa.len - 1) && (buf[offset] == 0))
378f8907bbfSEdison Ai 		offset++;
379f8907bbfSEdison Ai 
380f8907bbfSEdison Ai 	if (*dst_len < rsa.len - offset) {
381f8907bbfSEdison Ai 		*dst_len = rsa.len - offset;
382f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
383f8907bbfSEdison Ai 		goto out;
384f8907bbfSEdison Ai 	}
385f8907bbfSEdison Ai 	*dst_len = rsa.len - offset;
386f8907bbfSEdison Ai 	memcpy(dst, (char *)buf + offset, *dst_len);
387f8907bbfSEdison Ai out:
388f8907bbfSEdison Ai 	if (buf)
389f8907bbfSEdison Ai 		free(buf);
390f8907bbfSEdison Ai 	mbd_rsa_free(&rsa);
391f8907bbfSEdison Ai 	return res;
392f8907bbfSEdison Ai }
393f8907bbfSEdison Ai 
394eac16613SJorge Ramirez-Ortiz TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo,
395eac16613SJorge Ramirez-Ortiz 					struct rsa_keypair *key,
396eac16613SJorge Ramirez-Ortiz 					const uint8_t *label __unused,
397eac16613SJorge Ramirez-Ortiz 					size_t label_len __unused,
398eac16613SJorge Ramirez-Ortiz 					const uint8_t *src, size_t src_len,
399eac16613SJorge Ramirez-Ortiz 					uint8_t *dst, size_t *dst_len)
400eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_decrypt");
401eac16613SJorge Ramirez-Ortiz 
402eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
403eac16613SJorge Ramirez-Ortiz 					   struct rsa_keypair *key,
404f8907bbfSEdison Ai 					   const uint8_t *label __unused,
405f8907bbfSEdison Ai 					   size_t label_len __unused,
406f8907bbfSEdison Ai 					   const uint8_t *src, size_t src_len,
407f8907bbfSEdison Ai 					   uint8_t *dst, size_t *dst_len)
408f8907bbfSEdison Ai {
409f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
410f8907bbfSEdison Ai 	int lmd_res = 0;
411f8907bbfSEdison Ai 	int lmd_padding = 0;
412f8907bbfSEdison Ai 	size_t blen = 0;
413f8907bbfSEdison Ai 	size_t mod_size = 0;
414f8907bbfSEdison Ai 	void *buf = NULL;
415f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
416f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
417f8907bbfSEdison Ai 	uint32_t md_algo = MBEDTLS_MD_NONE;
418f8907bbfSEdison Ai 
419f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
420f8907bbfSEdison Ai 	rsa_init_from_key_pair(&rsa, key);
421f8907bbfSEdison Ai 
422f8907bbfSEdison Ai 	/*
423f8907bbfSEdison Ai 	 * Use a temporary buffer since we don't know exactly how large
424f8907bbfSEdison Ai 	 * the required size of the out buffer without doing a partial
425f8907bbfSEdison Ai 	 * decrypt. We know the upper bound though.
426f8907bbfSEdison Ai 	 */
427f8907bbfSEdison Ai 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
428f8907bbfSEdison Ai 		mod_size = crypto_bignum_num_bytes(key->n);
429f8907bbfSEdison Ai 		blen = mod_size - 11;
430f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
431f8907bbfSEdison Ai 	} else {
432f8907bbfSEdison Ai 		/* Decoded message is always shorter than encrypted message */
433f8907bbfSEdison Ai 		blen = src_len;
434f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
435f8907bbfSEdison Ai 	}
436f8907bbfSEdison Ai 
437f8907bbfSEdison Ai 	buf = malloc(blen);
438f8907bbfSEdison Ai 	if (!buf) {
439f8907bbfSEdison Ai 		res = TEE_ERROR_OUT_OF_MEMORY;
440f8907bbfSEdison Ai 		goto out;
441f8907bbfSEdison Ai 	}
442f8907bbfSEdison Ai 
443f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
444f8907bbfSEdison Ai 	if (!pk_info) {
445f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
446f8907bbfSEdison Ai 		goto out;
447f8907bbfSEdison Ai 	}
448f8907bbfSEdison Ai 
449f8907bbfSEdison Ai 	/*
450f8907bbfSEdison Ai 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
451f8907bbfSEdison Ai 	 * not be used in rsa, so skip it here.
452f8907bbfSEdison Ai 	 */
453f8907bbfSEdison Ai 	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
454f8907bbfSEdison Ai 		md_algo = tee_algo_to_mbedtls_hash_algo(algo);
455f8907bbfSEdison Ai 		if (md_algo == MBEDTLS_MD_NONE) {
456f8907bbfSEdison Ai 			res = TEE_ERROR_NOT_SUPPORTED;
457f8907bbfSEdison Ai 			goto out;
458f8907bbfSEdison Ai 		}
459f8907bbfSEdison Ai 	}
460f8907bbfSEdison Ai 
461f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
462f8907bbfSEdison Ai 
463f8907bbfSEdison Ai 	if (lmd_padding == MBEDTLS_RSA_PKCS_V15)
464f8907bbfSEdison Ai 		lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen,
465f8907bbfSEdison Ai 						blen, NULL, NULL);
466f8907bbfSEdison Ai 	else
467f8907bbfSEdison Ai 		lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen,
468f8907bbfSEdison Ai 						blen, mbd_rand, NULL);
469f8907bbfSEdison Ai 	if (lmd_res != 0) {
470f8907bbfSEdison Ai 		FMSG("decrypt_func() returned 0x%x", -lmd_res);
471f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
472f8907bbfSEdison Ai 		goto out;
473f8907bbfSEdison Ai 	}
474f8907bbfSEdison Ai 
475f8907bbfSEdison Ai 	if (*dst_len < blen) {
476f8907bbfSEdison Ai 		*dst_len = blen;
477f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
478f8907bbfSEdison Ai 		goto out;
479f8907bbfSEdison Ai 	}
480f8907bbfSEdison Ai 
481f8907bbfSEdison Ai 	res = TEE_SUCCESS;
482f8907bbfSEdison Ai 	*dst_len = blen;
483f8907bbfSEdison Ai 	memcpy(dst, buf, blen);
484f8907bbfSEdison Ai out:
485f8907bbfSEdison Ai 	if (buf)
486f8907bbfSEdison Ai 		free(buf);
487f8907bbfSEdison Ai 	mbd_rsa_free(&rsa);
488f8907bbfSEdison Ai 	return res;
489f8907bbfSEdison Ai }
490f8907bbfSEdison Ai 
491f8907bbfSEdison Ai TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
492f8907bbfSEdison Ai 					struct rsa_public_key *key,
493f8907bbfSEdison Ai 					const uint8_t *label __unused,
494f8907bbfSEdison Ai 					size_t label_len __unused,
495f8907bbfSEdison Ai 					const uint8_t *src, size_t src_len,
496f8907bbfSEdison Ai 					uint8_t *dst, size_t *dst_len)
497eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsaes_encrypt");
498eac16613SJorge Ramirez-Ortiz 
499eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
500eac16613SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
501eac16613SJorge Ramirez-Ortiz 					   const uint8_t *label __unused,
502eac16613SJorge Ramirez-Ortiz 					   size_t label_len __unused,
503eac16613SJorge Ramirez-Ortiz 					   const uint8_t *src, size_t src_len,
504eac16613SJorge Ramirez-Ortiz 					   uint8_t *dst, size_t *dst_len)
505f8907bbfSEdison Ai {
506f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
507f8907bbfSEdison Ai 	int lmd_res = 0;
508f8907bbfSEdison Ai 	int lmd_padding = 0;
509f8907bbfSEdison Ai 	size_t mod_size = 0;
510f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
511f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
512f8907bbfSEdison Ai 	uint32_t md_algo = MBEDTLS_MD_NONE;
513f8907bbfSEdison Ai 
514f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
515f8907bbfSEdison Ai 	mbedtls_rsa_init(&rsa, 0, 0);
516f8907bbfSEdison Ai 
517f8907bbfSEdison Ai 	rsa.E = *(mbedtls_mpi *)key->e;
518f8907bbfSEdison Ai 	rsa.N = *(mbedtls_mpi *)key->n;
519f8907bbfSEdison Ai 
520f8907bbfSEdison Ai 	mod_size = crypto_bignum_num_bytes(key->n);
521f8907bbfSEdison Ai 	if (*dst_len < mod_size) {
522f8907bbfSEdison Ai 		*dst_len = mod_size;
523f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
524f8907bbfSEdison Ai 		goto out;
525f8907bbfSEdison Ai 	}
526f8907bbfSEdison Ai 	*dst_len = mod_size;
527f8907bbfSEdison Ai 	rsa.len = mod_size;
528f8907bbfSEdison Ai 
529f8907bbfSEdison Ai 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
530f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
531f8907bbfSEdison Ai 	else
532f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
533f8907bbfSEdison Ai 
534f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
535f8907bbfSEdison Ai 	if (!pk_info) {
536f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
537f8907bbfSEdison Ai 		goto out;
538f8907bbfSEdison Ai 	}
539f8907bbfSEdison Ai 
540f8907bbfSEdison Ai 	/*
541f8907bbfSEdison Ai 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
542f8907bbfSEdison Ai 	 * not be used in rsa, so skip it here.
543f8907bbfSEdison Ai 	 */
544f8907bbfSEdison Ai 	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
545f8907bbfSEdison Ai 		md_algo = tee_algo_to_mbedtls_hash_algo(algo);
546f8907bbfSEdison Ai 		if (md_algo == MBEDTLS_MD_NONE) {
547f8907bbfSEdison Ai 			res = TEE_ERROR_NOT_SUPPORTED;
548f8907bbfSEdison Ai 			goto out;
549f8907bbfSEdison Ai 		}
550f8907bbfSEdison Ai 	}
551f8907bbfSEdison Ai 
552f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
553f8907bbfSEdison Ai 
554f8907bbfSEdison Ai 	lmd_res = pk_info->encrypt_func(&rsa, src, src_len, dst, dst_len,
555f8907bbfSEdison Ai 					*dst_len, mbd_rand, NULL);
556f8907bbfSEdison Ai 	if (lmd_res != 0) {
557f8907bbfSEdison Ai 		FMSG("encrypt_func() returned 0x%x", -lmd_res);
558f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
559f8907bbfSEdison Ai 		goto out;
560f8907bbfSEdison Ai 	}
561f8907bbfSEdison Ai 	res = TEE_SUCCESS;
562f8907bbfSEdison Ai out:
563f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
564f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.E);
565f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.N);
566f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
567f8907bbfSEdison Ai 	return res;
568f8907bbfSEdison Ai }
569f8907bbfSEdison Ai 
570f8907bbfSEdison Ai TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
571eac16613SJorge Ramirez-Ortiz 				      int salt_len __unused,
572eac16613SJorge Ramirez-Ortiz 				      const uint8_t *msg, size_t msg_len,
573eac16613SJorge Ramirez-Ortiz 				      uint8_t *sig, size_t *sig_len)
574eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_sign");
575eac16613SJorge Ramirez-Ortiz 
576eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
577eac16613SJorge Ramirez-Ortiz 					 int salt_len __unused,
578eac16613SJorge Ramirez-Ortiz 					 const uint8_t *msg, size_t msg_len,
579eac16613SJorge Ramirez-Ortiz 					 uint8_t *sig, size_t *sig_len)
580f8907bbfSEdison Ai {
581f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
582f8907bbfSEdison Ai 	int lmd_res = 0;
583f8907bbfSEdison Ai 	int lmd_padding = 0;
584f8907bbfSEdison Ai 	size_t mod_size = 0;
585f8907bbfSEdison Ai 	size_t hash_size = 0;
586f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
587f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
588f8907bbfSEdison Ai 	uint32_t md_algo = 0;
589f8907bbfSEdison Ai 
590f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
591f8907bbfSEdison Ai 	rsa_init_from_key_pair(&rsa, key);
592f8907bbfSEdison Ai 
593f8907bbfSEdison Ai 	switch (algo) {
594f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
595f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
596f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
597f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
598f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
599f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
600f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
601f8907bbfSEdison Ai 		break;
602f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
603f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
604f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
605f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
606f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
607f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
608f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
609f8907bbfSEdison Ai 		break;
610f8907bbfSEdison Ai 	default:
611f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
612f8907bbfSEdison Ai 		goto err;
613f8907bbfSEdison Ai 	}
614f8907bbfSEdison Ai 
6157c767434SAlbert Schwarzkopf 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
616f8907bbfSEdison Ai 				      &hash_size);
617f8907bbfSEdison Ai 	if (res != TEE_SUCCESS)
618f8907bbfSEdison Ai 		goto err;
619f8907bbfSEdison Ai 
620f8907bbfSEdison Ai 	if (msg_len != hash_size) {
621f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
622f8907bbfSEdison Ai 		goto err;
623f8907bbfSEdison Ai 	}
624f8907bbfSEdison Ai 
625f8907bbfSEdison Ai 	mod_size = crypto_bignum_num_bytes(key->n);
626f8907bbfSEdison Ai 	if (*sig_len < mod_size) {
627f8907bbfSEdison Ai 		*sig_len = mod_size;
628f8907bbfSEdison Ai 		res = TEE_ERROR_SHORT_BUFFER;
629f8907bbfSEdison Ai 		goto err;
630f8907bbfSEdison Ai 	}
631f8907bbfSEdison Ai 	rsa.len = mod_size;
632f8907bbfSEdison Ai 
633f8907bbfSEdison Ai 	md_algo = tee_algo_to_mbedtls_hash_algo(algo);
634f8907bbfSEdison Ai 	if (md_algo == MBEDTLS_MD_NONE) {
635f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
636f8907bbfSEdison Ai 		goto err;
637f8907bbfSEdison Ai 	}
638f8907bbfSEdison Ai 
639f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
640f8907bbfSEdison Ai 	if (!pk_info) {
641f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
642f8907bbfSEdison Ai 		goto err;
643f8907bbfSEdison Ai 	}
644f8907bbfSEdison Ai 
645f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
646f8907bbfSEdison Ai 
647f8907bbfSEdison Ai 	if (lmd_padding == MBEDTLS_RSA_PKCS_V15)
648f8907bbfSEdison Ai 		lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig,
649f8907bbfSEdison Ai 					     sig_len, NULL, NULL);
650f8907bbfSEdison Ai 	else
651f8907bbfSEdison Ai 		lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig,
652f8907bbfSEdison Ai 					     sig_len, mbd_rand, NULL);
653f8907bbfSEdison Ai 	if (lmd_res != 0) {
654f8907bbfSEdison Ai 		FMSG("sign_func failed, returned 0x%x", -lmd_res);
655f8907bbfSEdison Ai 		res = get_tee_result(lmd_res);
656f8907bbfSEdison Ai 		goto err;
657f8907bbfSEdison Ai 	}
658f8907bbfSEdison Ai 	res = TEE_SUCCESS;
659f8907bbfSEdison Ai err:
660f8907bbfSEdison Ai 	mbd_rsa_free(&rsa);
661f8907bbfSEdison Ai 	return res;
662f8907bbfSEdison Ai }
663f8907bbfSEdison Ai 
664f8907bbfSEdison Ai TEE_Result crypto_acipher_rsassa_verify(uint32_t algo,
665f8907bbfSEdison Ai 					struct rsa_public_key *key,
666f8907bbfSEdison Ai 					int salt_len __unused,
667f8907bbfSEdison Ai 					const uint8_t *msg,
668f8907bbfSEdison Ai 					size_t msg_len, const uint8_t *sig,
669f8907bbfSEdison Ai 					size_t sig_len)
670eac16613SJorge Ramirez-Ortiz __weak __alias("sw_crypto_acipher_rsassa_verify");
671eac16613SJorge Ramirez-Ortiz 
672eac16613SJorge Ramirez-Ortiz TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
673eac16613SJorge Ramirez-Ortiz 					   struct rsa_public_key *key,
674eac16613SJorge Ramirez-Ortiz 					   int salt_len __unused,
675eac16613SJorge Ramirez-Ortiz 					   const uint8_t *msg,
676eac16613SJorge Ramirez-Ortiz 					   size_t msg_len, const uint8_t *sig,
677eac16613SJorge Ramirez-Ortiz 					   size_t sig_len)
678f8907bbfSEdison Ai {
679f8907bbfSEdison Ai 	TEE_Result res = TEE_SUCCESS;
680f8907bbfSEdison Ai 	int lmd_res = 0;
681f8907bbfSEdison Ai 	int lmd_padding = 0;
682f8907bbfSEdison Ai 	size_t hash_size = 0;
683f8907bbfSEdison Ai 	size_t bigint_size = 0;
684f8907bbfSEdison Ai 	mbedtls_rsa_context rsa;
685f8907bbfSEdison Ai 	const mbedtls_pk_info_t *pk_info = NULL;
686f8907bbfSEdison Ai 	uint32_t md_algo = 0;
68798ada65eSJens Wiklander 	struct ftmn ftmn = { };
68898ada65eSJens Wiklander 	unsigned long arg_hash = 0;
68998ada65eSJens Wiklander 
69098ada65eSJens Wiklander 	/*
69198ada65eSJens Wiklander 	 * The caller expects to call crypto_acipher_rsassa_verify(),
69298ada65eSJens Wiklander 	 * update the hash as needed.
69398ada65eSJens Wiklander 	 */
69498ada65eSJens Wiklander 	FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify"));
695f8907bbfSEdison Ai 
696f8907bbfSEdison Ai 	memset(&rsa, 0, sizeof(rsa));
697f8907bbfSEdison Ai 	mbedtls_rsa_init(&rsa, 0, 0);
698f8907bbfSEdison Ai 
699f8907bbfSEdison Ai 	rsa.E = *(mbedtls_mpi *)key->e;
700f8907bbfSEdison Ai 	rsa.N = *(mbedtls_mpi *)key->n;
701f8907bbfSEdison Ai 
7027c767434SAlbert Schwarzkopf 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
703f8907bbfSEdison Ai 				      &hash_size);
704f8907bbfSEdison Ai 	if (res != TEE_SUCCESS)
705f8907bbfSEdison Ai 		goto err;
706f8907bbfSEdison Ai 
707f8907bbfSEdison Ai 	if (msg_len != hash_size) {
708f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
709f8907bbfSEdison Ai 		goto err;
710f8907bbfSEdison Ai 	}
711f8907bbfSEdison Ai 
712f8907bbfSEdison Ai 	bigint_size = crypto_bignum_num_bytes(key->n);
713f8907bbfSEdison Ai 	if (sig_len < bigint_size) {
714c282ebd6Slubing 		res = TEE_ERROR_SIGNATURE_INVALID;
715f8907bbfSEdison Ai 		goto err;
716f8907bbfSEdison Ai 	}
717f8907bbfSEdison Ai 
718f8907bbfSEdison Ai 	rsa.len = bigint_size;
719f8907bbfSEdison Ai 
720f8907bbfSEdison Ai 	switch (algo) {
721f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
722f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
723f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
724f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
725f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
726f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
72798ada65eSJens Wiklander 		arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pkcs1_v15_verify");
728f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
729f8907bbfSEdison Ai 		break;
730f5c3d85aSJulien Masson 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
731f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
732f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
733f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
734f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
735f8907bbfSEdison Ai 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
73698ada65eSJens Wiklander 		arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pss_verify_ext");
737f8907bbfSEdison Ai 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
738f8907bbfSEdison Ai 		break;
739f8907bbfSEdison Ai 	default:
740f8907bbfSEdison Ai 		res = TEE_ERROR_BAD_PARAMETERS;
741f8907bbfSEdison Ai 		goto err;
742f8907bbfSEdison Ai 	}
743f8907bbfSEdison Ai 
744f8907bbfSEdison Ai 	md_algo = tee_algo_to_mbedtls_hash_algo(algo);
745f8907bbfSEdison Ai 	if (md_algo == MBEDTLS_MD_NONE) {
746f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
747f8907bbfSEdison Ai 		goto err;
748f8907bbfSEdison Ai 	}
749f8907bbfSEdison Ai 
750f8907bbfSEdison Ai 	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
751f8907bbfSEdison Ai 	if (!pk_info) {
752f8907bbfSEdison Ai 		res = TEE_ERROR_NOT_SUPPORTED;
753f8907bbfSEdison Ai 		goto err;
754f8907bbfSEdison Ai 	}
755f8907bbfSEdison Ai 
756f8907bbfSEdison Ai 	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
757f8907bbfSEdison Ai 
75898ada65eSJens Wiklander 	FTMN_PUSH_LINKED_CALL(&ftmn, arg_hash);
759f8907bbfSEdison Ai 	lmd_res = pk_info->verify_func(&rsa, md_algo, msg, msg_len,
760f8907bbfSEdison Ai 				       sig, sig_len);
76198ada65eSJens Wiklander 	if (!lmd_res)
76298ada65eSJens Wiklander 		FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, lmd_res);
76398ada65eSJens Wiklander 	FTMN_POP_LINKED_CALL(&ftmn);
764f8907bbfSEdison Ai 	if (lmd_res != 0) {
765f8907bbfSEdison Ai 		FMSG("verify_func failed, returned 0x%x", -lmd_res);
766f8907bbfSEdison Ai 		res = TEE_ERROR_SIGNATURE_INVALID;
767f8907bbfSEdison Ai 		goto err;
768f8907bbfSEdison Ai 	}
769f8907bbfSEdison Ai 	res = TEE_SUCCESS;
77098ada65eSJens Wiklander 	goto out;
77198ada65eSJens Wiklander 
772f8907bbfSEdison Ai err:
77398ada65eSJens Wiklander 	FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res);
77498ada65eSJens Wiklander out:
77598ada65eSJens Wiklander 	FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res);
776f8907bbfSEdison Ai 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
777f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.E);
778f8907bbfSEdison Ai 	mbedtls_mpi_init(&rsa.N);
779f8907bbfSEdison Ai 	mbedtls_rsa_free(&rsa);
780f8907bbfSEdison Ai 	return res;
781f8907bbfSEdison Ai }
782