xref: /optee_os/lib/libutee/tee_api_arith_mpi.c (revision 062e3d01c039dac541b9fc9eaa1d6c4497435474)
1*062e3d01SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*062e3d01SJens Wiklander /*
3*062e3d01SJens Wiklander  * Copyright (c) 2018, Linaro limited
4*062e3d01SJens Wiklander  */
5*062e3d01SJens Wiklander #include <assert.h>
6*062e3d01SJens Wiklander #include <mbedtls/bignum.h>
7*062e3d01SJens Wiklander #include <mempool.h>
8*062e3d01SJens Wiklander #include <stdio.h>
9*062e3d01SJens Wiklander #include <string.h>
10*062e3d01SJens Wiklander #include <tee_api.h>
11*062e3d01SJens Wiklander #include <tee_arith_internal.h>
12*062e3d01SJens Wiklander #include <utee_defines.h>
13*062e3d01SJens Wiklander #include <utee_syscalls.h>
14*062e3d01SJens Wiklander #include <util.h>
15*062e3d01SJens Wiklander 
16*062e3d01SJens Wiklander #define MPI_MEMPOOL_SIZE	(8 * 1024)
17*062e3d01SJens Wiklander 
18*062e3d01SJens Wiklander static void __noreturn api_panic(const char *func, int line, const char *msg)
19*062e3d01SJens Wiklander {
20*062e3d01SJens Wiklander 	printf("Panic function %s, line %d: %s\n", func, line, msg);
21*062e3d01SJens Wiklander 	TEE_Panic(0xB16127 /*BIGINT*/);
22*062e3d01SJens Wiklander 	while (1)
23*062e3d01SJens Wiklander 		; /* Panic will crash the thread */
24*062e3d01SJens Wiklander }
25*062e3d01SJens Wiklander 
26*062e3d01SJens Wiklander #define API_PANIC(x) api_panic(__func__, __LINE__, x)
27*062e3d01SJens Wiklander 
28*062e3d01SJens Wiklander static void __noreturn mpi_panic(const char *func, int line, int rc)
29*062e3d01SJens Wiklander {
30*062e3d01SJens Wiklander 	printf("Panic function %s, line %d, code %d\n", func, line, rc);
31*062e3d01SJens Wiklander 	TEE_Panic(0xB16127 /*BIGINT*/);
32*062e3d01SJens Wiklander 	while (1)
33*062e3d01SJens Wiklander 		; /* Panic will crash the thread */
34*062e3d01SJens Wiklander }
35*062e3d01SJens Wiklander 
36*062e3d01SJens Wiklander #define MPI_CHECK(x) do { \
37*062e3d01SJens Wiklander 		int _rc = (x); \
38*062e3d01SJens Wiklander 		 \
39*062e3d01SJens Wiklander 		if (_rc) \
40*062e3d01SJens Wiklander 			mpi_panic(__func__, __LINE__, _rc); \
41*062e3d01SJens Wiklander 	} while (0)
42*062e3d01SJens Wiklander 
43*062e3d01SJens Wiklander void _TEE_MathAPI_Init(void)
44*062e3d01SJens Wiklander {
45*062e3d01SJens Wiklander 	static uint8_t data[MPI_MEMPOOL_SIZE]
46*062e3d01SJens Wiklander 		__aligned(__alignof__(mbedtls_mpi_uint));
47*062e3d01SJens Wiklander 
48*062e3d01SJens Wiklander 	mbedtls_mpi_mempool = mempool_alloc_pool(data, sizeof(data), NULL);
49*062e3d01SJens Wiklander 	if (!mbedtls_mpi_mempool)
50*062e3d01SJens Wiklander 		API_PANIC("Failed to initialize memory pool");
51*062e3d01SJens Wiklander }
52*062e3d01SJens Wiklander 
53*062e3d01SJens Wiklander struct bigint_hdr {
54*062e3d01SJens Wiklander 	int32_t sign;
55*062e3d01SJens Wiklander 	uint16_t alloc_size;
56*062e3d01SJens Wiklander 	uint16_t nblimbs;
57*062e3d01SJens Wiklander };
58*062e3d01SJens Wiklander 
59*062e3d01SJens Wiklander #define BIGINT_HDR_SIZE_IN_U32	2
60*062e3d01SJens Wiklander 
61*062e3d01SJens Wiklander static void init_static_mpi(mbedtls_mpi *mpi, TEE_BigInt *bigInt)
62*062e3d01SJens Wiklander {
63*062e3d01SJens Wiklander 	struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt;
64*062e3d01SJens Wiklander 
65*062e3d01SJens Wiklander 	mbedtls_mpi_init_static(mpi, (mbedtls_mpi_uint *)(hdr + 1),
66*062e3d01SJens Wiklander 				hdr->sign, hdr->alloc_size, hdr->nblimbs);
67*062e3d01SJens Wiklander }
68*062e3d01SJens Wiklander 
69*062e3d01SJens Wiklander /*
70*062e3d01SJens Wiklander  * Initializes a MPI.
71*062e3d01SJens Wiklander  *
72*062e3d01SJens Wiklander  * If a bigint is supplied it's initialized with the value of the bigint
73*062e3d01SJens Wiklander  * and changes will be written back completely with a call to put_mpi().
74*062e3d01SJens Wiklander  * The bigint dictates the size of the MPI which will be fixed to this
75*062e3d01SJens Wiklander  * size.
76*062e3d01SJens Wiklander  *
77*062e3d01SJens Wiklander  * If no bigint is supplied a temporary MPI is allocated instead which will
78*062e3d01SJens Wiklander  * be freed by put_mpi().
79*062e3d01SJens Wiklander  */
80*062e3d01SJens Wiklander static void get_mpi(mbedtls_mpi *mpi, TEE_BigInt *bigInt)
81*062e3d01SJens Wiklander {
82*062e3d01SJens Wiklander 	/*
83*062e3d01SJens Wiklander 	 * The way the GP spec is defining the bignums it's
84*062e3d01SJens Wiklander 	 * difficult/tricky to do it using 64-bit arithmetics given that
85*062e3d01SJens Wiklander 	 * we'd need 64-bit alignment of the data as well.
86*062e3d01SJens Wiklander 	 */
87*062e3d01SJens Wiklander 	COMPILE_TIME_ASSERT(sizeof(mbedtls_mpi_uint) == sizeof(uint32_t));
88*062e3d01SJens Wiklander 
89*062e3d01SJens Wiklander 	/*
90*062e3d01SJens Wiklander 	 * The struct bigint_hdr is the overhead added to the bigint and
91*062e3d01SJens Wiklander 	 * is required to take exactly 2 uint32_t.
92*062e3d01SJens Wiklander 	 */
93*062e3d01SJens Wiklander 	COMPILE_TIME_ASSERT(sizeof(struct bigint_hdr) ==
94*062e3d01SJens Wiklander 			    sizeof(uint32_t) * BIGINT_HDR_SIZE_IN_U32);
95*062e3d01SJens Wiklander 
96*062e3d01SJens Wiklander 	if (bigInt)
97*062e3d01SJens Wiklander 		init_static_mpi(mpi, bigInt);
98*062e3d01SJens Wiklander 	else
99*062e3d01SJens Wiklander 		mbedtls_mpi_init_mempool(mpi);
100*062e3d01SJens Wiklander }
101*062e3d01SJens Wiklander 
102*062e3d01SJens Wiklander /*
103*062e3d01SJens Wiklander  * Initializes a MPI from a constant bigint.
104*062e3d01SJens Wiklander  *
105*062e3d01SJens Wiklander  * A MPI is allocated and given an initial value based on the supplied
106*062e3d01SJens Wiklander  * bigint. When the MPI is freed with put_mpi() no changes are propagated
107*062e3d01SJens Wiklander  * back.
108*062e3d01SJens Wiklander  */
109*062e3d01SJens Wiklander static void get_const_mpi(mbedtls_mpi *mpi, const TEE_BigInt *bigInt)
110*062e3d01SJens Wiklander {
111*062e3d01SJens Wiklander 	mbedtls_mpi mpi_const;
112*062e3d01SJens Wiklander 
113*062e3d01SJens Wiklander 	init_static_mpi(&mpi_const, (TEE_BigInt *)bigInt);
114*062e3d01SJens Wiklander 	get_mpi(mpi, NULL);
115*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(mpi, &mpi_const));
116*062e3d01SJens Wiklander }
117*062e3d01SJens Wiklander 
118*062e3d01SJens Wiklander /*
119*062e3d01SJens Wiklander  * Uninitialize a MPI.
120*062e3d01SJens Wiklander  *
121*062e3d01SJens Wiklander  * If the MPI is linked to a bigint the final changes (size and sign) will
122*062e3d01SJens Wiklander  * be copied back.
123*062e3d01SJens Wiklander  *
124*062e3d01SJens Wiklander  * If the MPI isn't linked to bigint it's only freed.
125*062e3d01SJens Wiklander  */
126*062e3d01SJens Wiklander static void put_mpi(mbedtls_mpi *mpi)
127*062e3d01SJens Wiklander {
128*062e3d01SJens Wiklander 	if (mpi->alloc_type == MBEDTLS_MPI_ALLOC_TYPE_STATIC) {
129*062e3d01SJens Wiklander 		struct bigint_hdr *hdr = ((struct bigint_hdr *)mpi->p) - 1;
130*062e3d01SJens Wiklander 
131*062e3d01SJens Wiklander 		hdr->sign = mpi->s;
132*062e3d01SJens Wiklander 		hdr->nblimbs = mpi->n;
133*062e3d01SJens Wiklander 	} else {
134*062e3d01SJens Wiklander 		mbedtls_mpi_free(mpi);
135*062e3d01SJens Wiklander 	}
136*062e3d01SJens Wiklander }
137*062e3d01SJens Wiklander 
138*062e3d01SJens Wiklander void TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len)
139*062e3d01SJens Wiklander {
140*062e3d01SJens Wiklander 	memset(bigInt, 0, TEE_BigIntSizeInU32(len) * sizeof(uint32_t));
141*062e3d01SJens Wiklander 
142*062e3d01SJens Wiklander 	struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt;
143*062e3d01SJens Wiklander 
144*062e3d01SJens Wiklander 
145*062e3d01SJens Wiklander 	hdr->sign = 1;
146*062e3d01SJens Wiklander 	if ((len - BIGINT_HDR_SIZE_IN_U32) > MBEDTLS_MPI_MAX_LIMBS)
147*062e3d01SJens Wiklander 		API_PANIC("Too large bigint");
148*062e3d01SJens Wiklander 	hdr->alloc_size = len - BIGINT_HDR_SIZE_IN_U32;
149*062e3d01SJens Wiklander }
150*062e3d01SJens Wiklander 
151*062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest,
152*062e3d01SJens Wiklander 					    const uint8_t *buffer,
153*062e3d01SJens Wiklander 					    uint32_t bufferLen, int32_t sign)
154*062e3d01SJens Wiklander {
155*062e3d01SJens Wiklander 	TEE_Result res;
156*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest;
157*062e3d01SJens Wiklander 
158*062e3d01SJens Wiklander 	get_mpi(&mpi_dest, dest);
159*062e3d01SJens Wiklander 
160*062e3d01SJens Wiklander 	if (mbedtls_mpi_read_binary(&mpi_dest,  buffer, bufferLen))
161*062e3d01SJens Wiklander 		res = TEE_ERROR_OVERFLOW;
162*062e3d01SJens Wiklander 	else
163*062e3d01SJens Wiklander 		res = TEE_SUCCESS;
164*062e3d01SJens Wiklander 
165*062e3d01SJens Wiklander 	if (sign < 0)
166*062e3d01SJens Wiklander 		mpi_dest.s = -1;
167*062e3d01SJens Wiklander 
168*062e3d01SJens Wiklander 	put_mpi(&mpi_dest);
169*062e3d01SJens Wiklander 
170*062e3d01SJens Wiklander 	return res;
171*062e3d01SJens Wiklander }
172*062e3d01SJens Wiklander 
173*062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, uint32_t *bufferLen,
174*062e3d01SJens Wiklander 					  const TEE_BigInt *bigInt)
175*062e3d01SJens Wiklander {
176*062e3d01SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
177*062e3d01SJens Wiklander 	mbedtls_mpi mpi;
178*062e3d01SJens Wiklander 	size_t sz;
179*062e3d01SJens Wiklander 
180*062e3d01SJens Wiklander 	get_const_mpi(&mpi, bigInt);
181*062e3d01SJens Wiklander 
182*062e3d01SJens Wiklander 	sz = mbedtls_mpi_size(&mpi);
183*062e3d01SJens Wiklander 	if (sz <= *bufferLen)
184*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_write_binary(&mpi, buffer, sz));
185*062e3d01SJens Wiklander 	else
186*062e3d01SJens Wiklander 		res = TEE_ERROR_SHORT_BUFFER;
187*062e3d01SJens Wiklander 
188*062e3d01SJens Wiklander 	*bufferLen = sz;
189*062e3d01SJens Wiklander 
190*062e3d01SJens Wiklander 	put_mpi(&mpi);
191*062e3d01SJens Wiklander 
192*062e3d01SJens Wiklander 	return res;
193*062e3d01SJens Wiklander }
194*062e3d01SJens Wiklander 
195*062e3d01SJens Wiklander void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal)
196*062e3d01SJens Wiklander {
197*062e3d01SJens Wiklander 	mbedtls_mpi mpi;
198*062e3d01SJens Wiklander 
199*062e3d01SJens Wiklander 	get_mpi(&mpi, dest);
200*062e3d01SJens Wiklander 
201*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_lset(&mpi, shortVal));
202*062e3d01SJens Wiklander 
203*062e3d01SJens Wiklander 	put_mpi(&mpi);
204*062e3d01SJens Wiklander }
205*062e3d01SJens Wiklander 
206*062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src)
207*062e3d01SJens Wiklander {
208*062e3d01SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
209*062e3d01SJens Wiklander 	mbedtls_mpi mpi;
210*062e3d01SJens Wiklander 	uint32_t v;
211*062e3d01SJens Wiklander 
212*062e3d01SJens Wiklander 	get_const_mpi(&mpi, src);
213*062e3d01SJens Wiklander 
214*062e3d01SJens Wiklander 	if (mbedtls_mpi_write_binary(&mpi, (void *)&v, sizeof(v))) {
215*062e3d01SJens Wiklander 		res = TEE_ERROR_OVERFLOW;
216*062e3d01SJens Wiklander 		goto out;
217*062e3d01SJens Wiklander 	}
218*062e3d01SJens Wiklander 
219*062e3d01SJens Wiklander 	if (mpi.s > 0) {
220*062e3d01SJens Wiklander 		if (ADD_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest))
221*062e3d01SJens Wiklander 			res = TEE_ERROR_OVERFLOW;
222*062e3d01SJens Wiklander 	} else {
223*062e3d01SJens Wiklander 		if (SUB_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest))
224*062e3d01SJens Wiklander 			res = TEE_ERROR_OVERFLOW;
225*062e3d01SJens Wiklander 	}
226*062e3d01SJens Wiklander 
227*062e3d01SJens Wiklander out:
228*062e3d01SJens Wiklander 	put_mpi(&mpi);
229*062e3d01SJens Wiklander 
230*062e3d01SJens Wiklander 	return res;
231*062e3d01SJens Wiklander }
232*062e3d01SJens Wiklander 
233*062e3d01SJens Wiklander int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2)
234*062e3d01SJens Wiklander {
235*062e3d01SJens Wiklander 	mbedtls_mpi mpi1;
236*062e3d01SJens Wiklander 	mbedtls_mpi mpi2;
237*062e3d01SJens Wiklander 	int32_t rc;
238*062e3d01SJens Wiklander 
239*062e3d01SJens Wiklander 	get_const_mpi(&mpi1, op1);
240*062e3d01SJens Wiklander 	get_const_mpi(&mpi2, op2);
241*062e3d01SJens Wiklander 
242*062e3d01SJens Wiklander 	rc = mbedtls_mpi_cmp_mpi(&mpi1, &mpi2);
243*062e3d01SJens Wiklander 
244*062e3d01SJens Wiklander 	put_mpi(&mpi1);
245*062e3d01SJens Wiklander 	put_mpi(&mpi2);
246*062e3d01SJens Wiklander 
247*062e3d01SJens Wiklander 	return rc;
248*062e3d01SJens Wiklander }
249*062e3d01SJens Wiklander 
250*062e3d01SJens Wiklander int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal)
251*062e3d01SJens Wiklander {
252*062e3d01SJens Wiklander 	mbedtls_mpi mpi;
253*062e3d01SJens Wiklander 	int32_t rc;
254*062e3d01SJens Wiklander 
255*062e3d01SJens Wiklander 	get_const_mpi(&mpi, op);
256*062e3d01SJens Wiklander 
257*062e3d01SJens Wiklander 	rc = mbedtls_mpi_cmp_int(&mpi, shortVal);
258*062e3d01SJens Wiklander 
259*062e3d01SJens Wiklander 	put_mpi(&mpi);
260*062e3d01SJens Wiklander 
261*062e3d01SJens Wiklander 	return rc;
262*062e3d01SJens Wiklander }
263*062e3d01SJens Wiklander 
264*062e3d01SJens Wiklander void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits)
265*062e3d01SJens Wiklander {
266*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest;
267*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op;
268*062e3d01SJens Wiklander 
269*062e3d01SJens Wiklander 	get_mpi(&mpi_dest, dest);
270*062e3d01SJens Wiklander 
271*062e3d01SJens Wiklander 	if (dest == op) {
272*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits));
273*062e3d01SJens Wiklander 		goto out;
274*062e3d01SJens Wiklander 	}
275*062e3d01SJens Wiklander 
276*062e3d01SJens Wiklander 	get_const_mpi(&mpi_op, op);
277*062e3d01SJens Wiklander 
278*062e3d01SJens Wiklander 	if (mbedtls_mpi_size(&mpi_dest) >= mbedtls_mpi_size(&mpi_op)) {
279*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_op));
280*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits));
281*062e3d01SJens Wiklander 	} else {
282*062e3d01SJens Wiklander 		mbedtls_mpi mpi_t;
283*062e3d01SJens Wiklander 
284*062e3d01SJens Wiklander 		get_mpi(&mpi_t, NULL);
285*062e3d01SJens Wiklander 
286*062e3d01SJens Wiklander 		/*
287*062e3d01SJens Wiklander 		 * We're using a temporary buffer to avoid the corner case
288*062e3d01SJens Wiklander 		 * where destination is unexpectedly overflowed by up to
289*062e3d01SJens Wiklander 		 * @bits number of bits.
290*062e3d01SJens Wiklander 		 */
291*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_copy(&mpi_t, &mpi_op));
292*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_shift_r(&mpi_t, bits));
293*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_t));
294*062e3d01SJens Wiklander 
295*062e3d01SJens Wiklander 		put_mpi(&mpi_t);
296*062e3d01SJens Wiklander 	}
297*062e3d01SJens Wiklander 
298*062e3d01SJens Wiklander 	put_mpi(&mpi_op);
299*062e3d01SJens Wiklander 
300*062e3d01SJens Wiklander out:
301*062e3d01SJens Wiklander 	put_mpi(&mpi_dest);
302*062e3d01SJens Wiklander }
303*062e3d01SJens Wiklander 
304*062e3d01SJens Wiklander bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex)
305*062e3d01SJens Wiklander {
306*062e3d01SJens Wiklander 	bool rc;
307*062e3d01SJens Wiklander 	mbedtls_mpi mpi;
308*062e3d01SJens Wiklander 
309*062e3d01SJens Wiklander 	get_const_mpi(&mpi, src);
310*062e3d01SJens Wiklander 
311*062e3d01SJens Wiklander 	rc = mbedtls_mpi_get_bit(&mpi, bitIndex);
312*062e3d01SJens Wiklander 
313*062e3d01SJens Wiklander 	put_mpi(&mpi);
314*062e3d01SJens Wiklander 
315*062e3d01SJens Wiklander 	return rc;
316*062e3d01SJens Wiklander }
317*062e3d01SJens Wiklander 
318*062e3d01SJens Wiklander uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src)
319*062e3d01SJens Wiklander {
320*062e3d01SJens Wiklander 	uint32_t rc;
321*062e3d01SJens Wiklander 	mbedtls_mpi mpi;
322*062e3d01SJens Wiklander 
323*062e3d01SJens Wiklander 	get_const_mpi(&mpi, src);
324*062e3d01SJens Wiklander 
325*062e3d01SJens Wiklander 	rc = mbedtls_mpi_bitlen(&mpi);
326*062e3d01SJens Wiklander 
327*062e3d01SJens Wiklander 	put_mpi(&mpi);
328*062e3d01SJens Wiklander 
329*062e3d01SJens Wiklander 	return rc;
330*062e3d01SJens Wiklander }
331*062e3d01SJens Wiklander 
332*062e3d01SJens Wiklander static void bigint_binary(TEE_BigInt *dest, const TEE_BigInt *op1,
333*062e3d01SJens Wiklander 			  const TEE_BigInt *op2,
334*062e3d01SJens Wiklander 			  int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A,
335*062e3d01SJens Wiklander 				      const mbedtls_mpi *B))
336*062e3d01SJens Wiklander {
337*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest;
338*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op1;
339*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op2;
340*062e3d01SJens Wiklander 	mbedtls_mpi *pop1 = &mpi_op1;
341*062e3d01SJens Wiklander 	mbedtls_mpi *pop2 = &mpi_op2;
342*062e3d01SJens Wiklander 
343*062e3d01SJens Wiklander 	get_mpi(&mpi_dest, dest);
344*062e3d01SJens Wiklander 
345*062e3d01SJens Wiklander 	if (op1 == dest)
346*062e3d01SJens Wiklander 		pop1 = &mpi_dest;
347*062e3d01SJens Wiklander 	else
348*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op1, op1);
349*062e3d01SJens Wiklander 
350*062e3d01SJens Wiklander 	if (op2 == dest)
351*062e3d01SJens Wiklander 		pop2 = &mpi_dest;
352*062e3d01SJens Wiklander 	else if (op2 == op1)
353*062e3d01SJens Wiklander 		pop2 = pop1;
354*062e3d01SJens Wiklander 	else
355*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op2, op2);
356*062e3d01SJens Wiklander 
357*062e3d01SJens Wiklander 	MPI_CHECK(func(&mpi_dest, pop1, pop2));
358*062e3d01SJens Wiklander 
359*062e3d01SJens Wiklander 	put_mpi(&mpi_dest);
360*062e3d01SJens Wiklander 	if (pop1 == &mpi_op1)
361*062e3d01SJens Wiklander 		put_mpi(&mpi_op1);
362*062e3d01SJens Wiklander 	if (pop2 == &mpi_op2)
363*062e3d01SJens Wiklander 		put_mpi(&mpi_op2);
364*062e3d01SJens Wiklander }
365*062e3d01SJens Wiklander 
366*062e3d01SJens Wiklander static void bigint_binary_mod(TEE_BigInt *dest, const TEE_BigInt *op1,
367*062e3d01SJens Wiklander 			      const TEE_BigInt *op2, const TEE_BigInt *n,
368*062e3d01SJens Wiklander 			      int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A,
369*062e3d01SJens Wiklander 					  const mbedtls_mpi *B))
370*062e3d01SJens Wiklander {
371*062e3d01SJens Wiklander 	if (TEE_BigIntCmpS32(n, 2) < 0)
372*062e3d01SJens Wiklander 		API_PANIC("Modulus is too short");
373*062e3d01SJens Wiklander 
374*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest;
375*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op1;
376*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op2;
377*062e3d01SJens Wiklander 	mbedtls_mpi mpi_n;
378*062e3d01SJens Wiklander 	mbedtls_mpi *pop1 = &mpi_op1;
379*062e3d01SJens Wiklander 	mbedtls_mpi *pop2 = &mpi_op2;
380*062e3d01SJens Wiklander 	mbedtls_mpi mpi_t;
381*062e3d01SJens Wiklander 
382*062e3d01SJens Wiklander 	get_mpi(&mpi_dest, dest);
383*062e3d01SJens Wiklander 	get_const_mpi(&mpi_n, n);
384*062e3d01SJens Wiklander 
385*062e3d01SJens Wiklander 	if (op1 == dest)
386*062e3d01SJens Wiklander 		pop1 = &mpi_dest;
387*062e3d01SJens Wiklander 	else
388*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op1, op1);
389*062e3d01SJens Wiklander 
390*062e3d01SJens Wiklander 	if (op2 == dest)
391*062e3d01SJens Wiklander 		pop2 = &mpi_dest;
392*062e3d01SJens Wiklander 	else if (op2 == op1)
393*062e3d01SJens Wiklander 		pop2 = pop1;
394*062e3d01SJens Wiklander 	else
395*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op2, op2);
396*062e3d01SJens Wiklander 
397*062e3d01SJens Wiklander 	get_mpi(&mpi_t, NULL);
398*062e3d01SJens Wiklander 
399*062e3d01SJens Wiklander 	MPI_CHECK(func(&mpi_t, pop1, pop2));
400*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dest, &mpi_t, &mpi_n));
401*062e3d01SJens Wiklander 
402*062e3d01SJens Wiklander 	put_mpi(&mpi_dest);
403*062e3d01SJens Wiklander 	if (pop1 == &mpi_op1)
404*062e3d01SJens Wiklander 		put_mpi(&mpi_op1);
405*062e3d01SJens Wiklander 	if (pop2 == &mpi_op2)
406*062e3d01SJens Wiklander 		put_mpi(&mpi_op2);
407*062e3d01SJens Wiklander 	put_mpi(&mpi_t);
408*062e3d01SJens Wiklander }
409*062e3d01SJens Wiklander 
410*062e3d01SJens Wiklander void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1,
411*062e3d01SJens Wiklander 		   const TEE_BigInt *op2)
412*062e3d01SJens Wiklander {
413*062e3d01SJens Wiklander 	bigint_binary(dest, op1, op2, mbedtls_mpi_add_mpi);
414*062e3d01SJens Wiklander }
415*062e3d01SJens Wiklander 
416*062e3d01SJens Wiklander void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1,
417*062e3d01SJens Wiklander 		   const TEE_BigInt *op2)
418*062e3d01SJens Wiklander {
419*062e3d01SJens Wiklander 	bigint_binary(dest, op1, op2, mbedtls_mpi_sub_mpi);
420*062e3d01SJens Wiklander }
421*062e3d01SJens Wiklander 
422*062e3d01SJens Wiklander void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src)
423*062e3d01SJens Wiklander {
424*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest;
425*062e3d01SJens Wiklander 
426*062e3d01SJens Wiklander 	get_mpi(&mpi_dest, dest);
427*062e3d01SJens Wiklander 
428*062e3d01SJens Wiklander 	if (dest != src) {
429*062e3d01SJens Wiklander 		mbedtls_mpi mpi_src;
430*062e3d01SJens Wiklander 
431*062e3d01SJens Wiklander 		get_const_mpi(&mpi_src, src);
432*062e3d01SJens Wiklander 
433*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_src));
434*062e3d01SJens Wiklander 
435*062e3d01SJens Wiklander 		put_mpi(&mpi_src);
436*062e3d01SJens Wiklander 	}
437*062e3d01SJens Wiklander 
438*062e3d01SJens Wiklander 	mpi_dest.s *= -1;
439*062e3d01SJens Wiklander 
440*062e3d01SJens Wiklander 	put_mpi(&mpi_dest);
441*062e3d01SJens Wiklander }
442*062e3d01SJens Wiklander 
443*062e3d01SJens Wiklander void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1,
444*062e3d01SJens Wiklander 		   const TEE_BigInt *op2)
445*062e3d01SJens Wiklander {
446*062e3d01SJens Wiklander 	bigint_binary(dest, op1, op2, mbedtls_mpi_mul_mpi);
447*062e3d01SJens Wiklander }
448*062e3d01SJens Wiklander 
449*062e3d01SJens Wiklander void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op)
450*062e3d01SJens Wiklander {
451*062e3d01SJens Wiklander 	TEE_BigIntMul(dest, op, op);
452*062e3d01SJens Wiklander }
453*062e3d01SJens Wiklander 
454*062e3d01SJens Wiklander void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r,
455*062e3d01SJens Wiklander 		   const TEE_BigInt *op1, const TEE_BigInt *op2)
456*062e3d01SJens Wiklander {
457*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest_q;
458*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest_r;
459*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op1;
460*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op2;
461*062e3d01SJens Wiklander 	mbedtls_mpi *pop1 = &mpi_op1;
462*062e3d01SJens Wiklander 	mbedtls_mpi *pop2 = &mpi_op2;
463*062e3d01SJens Wiklander 
464*062e3d01SJens Wiklander 	get_mpi(&mpi_dest_q, dest_q);
465*062e3d01SJens Wiklander 	get_mpi(&mpi_dest_r, dest_r);
466*062e3d01SJens Wiklander 
467*062e3d01SJens Wiklander 	if (op1 == dest_q)
468*062e3d01SJens Wiklander 		pop1 = &mpi_dest_q;
469*062e3d01SJens Wiklander 	else if (op1 == dest_r)
470*062e3d01SJens Wiklander 		pop1 = &mpi_dest_r;
471*062e3d01SJens Wiklander 	else
472*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op1, op1);
473*062e3d01SJens Wiklander 
474*062e3d01SJens Wiklander 	if (op2 == dest_q)
475*062e3d01SJens Wiklander 		pop2 = &mpi_dest_q;
476*062e3d01SJens Wiklander 	else if (op2 == dest_r)
477*062e3d01SJens Wiklander 		pop2 = &mpi_dest_r;
478*062e3d01SJens Wiklander 	else if (op2 == op1)
479*062e3d01SJens Wiklander 		pop2 = pop1;
480*062e3d01SJens Wiklander 	else
481*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op2, op2);
482*062e3d01SJens Wiklander 
483*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_div_mpi(&mpi_dest_q, &mpi_dest_r, pop1, pop2));
484*062e3d01SJens Wiklander 
485*062e3d01SJens Wiklander 	put_mpi(&mpi_dest_q);
486*062e3d01SJens Wiklander 	put_mpi(&mpi_dest_r);
487*062e3d01SJens Wiklander 	if (pop1 == &mpi_op1)
488*062e3d01SJens Wiklander 		put_mpi(&mpi_op1);
489*062e3d01SJens Wiklander 	if (pop2 == &mpi_op2)
490*062e3d01SJens Wiklander 		put_mpi(&mpi_op2);
491*062e3d01SJens Wiklander }
492*062e3d01SJens Wiklander 
493*062e3d01SJens Wiklander void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n)
494*062e3d01SJens Wiklander {
495*062e3d01SJens Wiklander 	if (TEE_BigIntCmpS32(n, 2) < 0)
496*062e3d01SJens Wiklander 		API_PANIC("Modulus is too short");
497*062e3d01SJens Wiklander 
498*062e3d01SJens Wiklander 	bigint_binary(dest, op, n, mbedtls_mpi_mod_mpi);
499*062e3d01SJens Wiklander }
500*062e3d01SJens Wiklander 
501*062e3d01SJens Wiklander void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1,
502*062e3d01SJens Wiklander 		      const TEE_BigInt *op2, const TEE_BigInt *n)
503*062e3d01SJens Wiklander {
504*062e3d01SJens Wiklander 	bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_add_mpi);
505*062e3d01SJens Wiklander }
506*062e3d01SJens Wiklander 
507*062e3d01SJens Wiklander void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1,
508*062e3d01SJens Wiklander 		      const TEE_BigInt *op2, const TEE_BigInt *n)
509*062e3d01SJens Wiklander {
510*062e3d01SJens Wiklander 	bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_sub_mpi);
511*062e3d01SJens Wiklander }
512*062e3d01SJens Wiklander 
513*062e3d01SJens Wiklander void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1,
514*062e3d01SJens Wiklander 		      const TEE_BigInt *op2, const TEE_BigInt *n)
515*062e3d01SJens Wiklander {
516*062e3d01SJens Wiklander 	bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_mul_mpi);
517*062e3d01SJens Wiklander }
518*062e3d01SJens Wiklander 
519*062e3d01SJens Wiklander void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op,
520*062e3d01SJens Wiklander 			 const TEE_BigInt *n)
521*062e3d01SJens Wiklander {
522*062e3d01SJens Wiklander 	TEE_BigIntMulMod(dest, op, op, n);
523*062e3d01SJens Wiklander }
524*062e3d01SJens Wiklander 
525*062e3d01SJens Wiklander void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op,
526*062e3d01SJens Wiklander 		      const TEE_BigInt *n)
527*062e3d01SJens Wiklander {
528*062e3d01SJens Wiklander 	if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0)
529*062e3d01SJens Wiklander 		API_PANIC("too small modulus or trying to invert zero");
530*062e3d01SJens Wiklander 
531*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dest;
532*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op;
533*062e3d01SJens Wiklander 	mbedtls_mpi mpi_n;
534*062e3d01SJens Wiklander 	mbedtls_mpi *pop = &mpi_op;
535*062e3d01SJens Wiklander 
536*062e3d01SJens Wiklander 	get_mpi(&mpi_dest, dest);
537*062e3d01SJens Wiklander 	get_const_mpi(&mpi_n, n);
538*062e3d01SJens Wiklander 
539*062e3d01SJens Wiklander 	if (op == dest)
540*062e3d01SJens Wiklander 		pop = &mpi_dest;
541*062e3d01SJens Wiklander 	else
542*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op, op);
543*062e3d01SJens Wiklander 
544*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_inv_mod(&mpi_dest, pop, &mpi_n));
545*062e3d01SJens Wiklander 
546*062e3d01SJens Wiklander 	put_mpi(&mpi_dest);
547*062e3d01SJens Wiklander 	put_mpi(&mpi_n);
548*062e3d01SJens Wiklander 	if (pop == &mpi_op)
549*062e3d01SJens Wiklander 		put_mpi(&mpi_op);
550*062e3d01SJens Wiklander }
551*062e3d01SJens Wiklander 
552*062e3d01SJens Wiklander bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2)
553*062e3d01SJens Wiklander {
554*062e3d01SJens Wiklander 	bool rc;
555*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op1;
556*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op2;
557*062e3d01SJens Wiklander 	mbedtls_mpi *pop2 = &mpi_op2;
558*062e3d01SJens Wiklander 	mbedtls_mpi gcd;
559*062e3d01SJens Wiklander 
560*062e3d01SJens Wiklander 	get_const_mpi(&mpi_op1, op1);
561*062e3d01SJens Wiklander 
562*062e3d01SJens Wiklander 	if (op2 == op1)
563*062e3d01SJens Wiklander 		pop2 = &mpi_op1;
564*062e3d01SJens Wiklander 	else
565*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op2, op2);
566*062e3d01SJens Wiklander 
567*062e3d01SJens Wiklander 	get_mpi(&gcd, NULL);
568*062e3d01SJens Wiklander 
569*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_gcd(&gcd, &mpi_op1, &mpi_op2));
570*062e3d01SJens Wiklander 
571*062e3d01SJens Wiklander 	rc = !mbedtls_mpi_cmp_int(&gcd, 1);
572*062e3d01SJens Wiklander 
573*062e3d01SJens Wiklander 	put_mpi(&gcd);
574*062e3d01SJens Wiklander 	put_mpi(&mpi_op1);
575*062e3d01SJens Wiklander 	if (pop2 == &mpi_op2)
576*062e3d01SJens Wiklander 		put_mpi(&mpi_op2);
577*062e3d01SJens Wiklander 
578*062e3d01SJens Wiklander 	return rc;
579*062e3d01SJens Wiklander }
580*062e3d01SJens Wiklander 
581*062e3d01SJens Wiklander static bool mpi_is_odd(mbedtls_mpi *x)
582*062e3d01SJens Wiklander {
583*062e3d01SJens Wiklander 	return mbedtls_mpi_get_bit(x, 0);
584*062e3d01SJens Wiklander }
585*062e3d01SJens Wiklander 
586*062e3d01SJens Wiklander static bool mpi_is_even(mbedtls_mpi *x)
587*062e3d01SJens Wiklander {
588*062e3d01SJens Wiklander 	return !mpi_is_odd(x);
589*062e3d01SJens Wiklander }
590*062e3d01SJens Wiklander 
591*062e3d01SJens Wiklander /*
592*062e3d01SJens Wiklander  * Based on libmpa implementation __mpa_egcd(), modified to work with MPI
593*062e3d01SJens Wiklander  * instead.
594*062e3d01SJens Wiklander  */
595*062e3d01SJens Wiklander static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b,
596*062e3d01SJens Wiklander 		     mbedtls_mpi *x_in, mbedtls_mpi *y_in)
597*062e3d01SJens Wiklander {
598*062e3d01SJens Wiklander 	mbedtls_mpi_uint k;
599*062e3d01SJens Wiklander 	mbedtls_mpi A;
600*062e3d01SJens Wiklander 	mbedtls_mpi B;
601*062e3d01SJens Wiklander 	mbedtls_mpi C;
602*062e3d01SJens Wiklander 	mbedtls_mpi D;
603*062e3d01SJens Wiklander 	mbedtls_mpi x;
604*062e3d01SJens Wiklander 	mbedtls_mpi y;
605*062e3d01SJens Wiklander 	mbedtls_mpi u;
606*062e3d01SJens Wiklander 
607*062e3d01SJens Wiklander 	get_mpi(&A, NULL);
608*062e3d01SJens Wiklander 	get_mpi(&B, NULL);
609*062e3d01SJens Wiklander 	get_mpi(&C, NULL);
610*062e3d01SJens Wiklander 	get_mpi(&D, NULL);
611*062e3d01SJens Wiklander 	get_mpi(&x, NULL);
612*062e3d01SJens Wiklander 	get_mpi(&y, NULL);
613*062e3d01SJens Wiklander 	get_mpi(&u, NULL);
614*062e3d01SJens Wiklander 
615*062e3d01SJens Wiklander 	/* have y < x from assumption */
616*062e3d01SJens Wiklander 	if (!mbedtls_mpi_cmp_int(y_in, 0)) {
617*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_lset(a, 1));
618*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_lset(b, 0));
619*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_copy(gcd, x_in));
620*062e3d01SJens Wiklander 		goto out;
621*062e3d01SJens Wiklander 	}
622*062e3d01SJens Wiklander 
623*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(&x, x_in));
624*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(&y, y_in));
625*062e3d01SJens Wiklander 
626*062e3d01SJens Wiklander 	k = 0;
627*062e3d01SJens Wiklander 	while (mpi_is_even(&x) && mpi_is_even(&y)) {
628*062e3d01SJens Wiklander 		k++;
629*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_shift_r(&x, 1));
630*062e3d01SJens Wiklander 		MPI_CHECK(mbedtls_mpi_shift_r(&y, 1));
631*062e3d01SJens Wiklander 	}
632*062e3d01SJens Wiklander 
633*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(&u, &x));
634*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(gcd, &y));
635*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_lset(&A, 1));
636*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_lset(&B, 0));
637*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_lset(&C, 0));
638*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_lset(&D, 1));
639*062e3d01SJens Wiklander 
640*062e3d01SJens Wiklander 	while (mbedtls_mpi_cmp_int(&u, 0)) {
641*062e3d01SJens Wiklander 		while (mpi_is_even(&u)) {
642*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_shift_r(&u, 1));
643*062e3d01SJens Wiklander 			if (mpi_is_odd(&A) || mpi_is_odd(&B)) {
644*062e3d01SJens Wiklander 				MPI_CHECK(mbedtls_mpi_add_mpi(&A, &A, &y));
645*062e3d01SJens Wiklander 				MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &x));
646*062e3d01SJens Wiklander 			}
647*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_shift_r(&A, 1));
648*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_shift_r(&B, 1));
649*062e3d01SJens Wiklander 		}
650*062e3d01SJens Wiklander 
651*062e3d01SJens Wiklander 		while (mpi_is_even(gcd)) {
652*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_shift_r(gcd, 1));
653*062e3d01SJens Wiklander 			if (mpi_is_odd(&C) || mpi_is_odd(&D)) {
654*062e3d01SJens Wiklander 				MPI_CHECK(mbedtls_mpi_add_mpi(&C, &C, &y));
655*062e3d01SJens Wiklander 				MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &x));
656*062e3d01SJens Wiklander 			}
657*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_shift_r(&C, 1));
658*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_shift_r(&D, 1));
659*062e3d01SJens Wiklander 
660*062e3d01SJens Wiklander 		}
661*062e3d01SJens Wiklander 
662*062e3d01SJens Wiklander 		if (mbedtls_mpi_cmp_mpi(&u, gcd) >= 0) {
663*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_sub_mpi(&u, &u, gcd));
664*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_sub_mpi(&A, &A, &C));
665*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &D));
666*062e3d01SJens Wiklander 		} else {
667*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_sub_mpi(gcd, gcd, &u));
668*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_sub_mpi(&C, &C, &A));
669*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &B));
670*062e3d01SJens Wiklander 		}
671*062e3d01SJens Wiklander 	}
672*062e3d01SJens Wiklander 
673*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(a, &C));
674*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(b, &D));
675*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_shift_l(gcd, k));
676*062e3d01SJens Wiklander 
677*062e3d01SJens Wiklander out:
678*062e3d01SJens Wiklander 	put_mpi(&A);
679*062e3d01SJens Wiklander 	put_mpi(&B);
680*062e3d01SJens Wiklander 	put_mpi(&C);
681*062e3d01SJens Wiklander 	put_mpi(&D);
682*062e3d01SJens Wiklander 	put_mpi(&x);
683*062e3d01SJens Wiklander 	put_mpi(&y);
684*062e3d01SJens Wiklander 	put_mpi(&u);
685*062e3d01SJens Wiklander }
686*062e3d01SJens Wiklander 
687*062e3d01SJens Wiklander void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u,
688*062e3d01SJens Wiklander 				  TEE_BigInt *v, const TEE_BigInt *op1,
689*062e3d01SJens Wiklander 				  const TEE_BigInt *op2)
690*062e3d01SJens Wiklander {
691*062e3d01SJens Wiklander 	mbedtls_mpi mpi_gcd_res;
692*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op1;
693*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op2;
694*062e3d01SJens Wiklander 	mbedtls_mpi *pop2 = &mpi_op2;
695*062e3d01SJens Wiklander 
696*062e3d01SJens Wiklander 	get_mpi(&mpi_gcd_res, gcd);
697*062e3d01SJens Wiklander 	get_const_mpi(&mpi_op1, op1);
698*062e3d01SJens Wiklander 
699*062e3d01SJens Wiklander 	if (op2 == op1)
700*062e3d01SJens Wiklander 		pop2 = &mpi_op1;
701*062e3d01SJens Wiklander 	else
702*062e3d01SJens Wiklander 		get_const_mpi(&mpi_op2, op2);
703*062e3d01SJens Wiklander 
704*062e3d01SJens Wiklander 	if (!u && !v) {
705*062e3d01SJens Wiklander 		if (gcd)
706*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_gcd(&mpi_gcd_res, &mpi_op1,
707*062e3d01SJens Wiklander 						  pop2));
708*062e3d01SJens Wiklander 	} else {
709*062e3d01SJens Wiklander 		mbedtls_mpi mpi_u;
710*062e3d01SJens Wiklander 		mbedtls_mpi mpi_v;
711*062e3d01SJens Wiklander 		int8_t s1 = mpi_op1.s;
712*062e3d01SJens Wiklander 		int8_t s2 = pop2->s;
713*062e3d01SJens Wiklander 		int cmp;
714*062e3d01SJens Wiklander 
715*062e3d01SJens Wiklander 		mpi_op1.s = 1;
716*062e3d01SJens Wiklander 		pop2->s = 1;
717*062e3d01SJens Wiklander 
718*062e3d01SJens Wiklander 		get_mpi(&mpi_u, u);
719*062e3d01SJens Wiklander 		get_mpi(&mpi_v, v);
720*062e3d01SJens Wiklander 
721*062e3d01SJens Wiklander 		cmp = mbedtls_mpi_cmp_abs(&mpi_op1, pop2);
722*062e3d01SJens Wiklander 		if (cmp == 0) {
723*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_copy(&mpi_gcd_res, &mpi_op1));
724*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_lset(&mpi_u, 1));
725*062e3d01SJens Wiklander 			MPI_CHECK(mbedtls_mpi_lset(&mpi_v, 0));
726*062e3d01SJens Wiklander 		} else if (cmp > 0) {
727*062e3d01SJens Wiklander 			mpi_egcd(&mpi_gcd_res, &mpi_u, &mpi_v, &mpi_op1, pop2);
728*062e3d01SJens Wiklander 		} else {
729*062e3d01SJens Wiklander 			mpi_egcd(&mpi_gcd_res, &mpi_v, &mpi_u, pop2, &mpi_op1);
730*062e3d01SJens Wiklander 		}
731*062e3d01SJens Wiklander 
732*062e3d01SJens Wiklander 		mpi_u.s *= s1;
733*062e3d01SJens Wiklander 		mpi_v.s *= s2;
734*062e3d01SJens Wiklander 
735*062e3d01SJens Wiklander 		put_mpi(&mpi_u);
736*062e3d01SJens Wiklander 		put_mpi(&mpi_v);
737*062e3d01SJens Wiklander 	}
738*062e3d01SJens Wiklander 
739*062e3d01SJens Wiklander 	put_mpi(&mpi_gcd_res);
740*062e3d01SJens Wiklander 	put_mpi(&mpi_op1);
741*062e3d01SJens Wiklander 	if (pop2 == &mpi_op2)
742*062e3d01SJens Wiklander 		put_mpi(&mpi_op2);
743*062e3d01SJens Wiklander }
744*062e3d01SJens Wiklander 
745*062e3d01SJens Wiklander static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen)
746*062e3d01SJens Wiklander {
747*062e3d01SJens Wiklander 	if (utee_cryp_random_number_generate(buf, blen))
748*062e3d01SJens Wiklander 		return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
749*062e3d01SJens Wiklander 	return 0;
750*062e3d01SJens Wiklander }
751*062e3d01SJens Wiklander 
752*062e3d01SJens Wiklander int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op,
753*062e3d01SJens Wiklander 				  uint32_t confidenceLevel __unused)
754*062e3d01SJens Wiklander {
755*062e3d01SJens Wiklander 	int rc;
756*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op;
757*062e3d01SJens Wiklander 
758*062e3d01SJens Wiklander 	get_const_mpi(&mpi_op, op);
759*062e3d01SJens Wiklander 
760*062e3d01SJens Wiklander 	rc = mbedtls_mpi_is_prime(&mpi_op, rng_read, NULL);
761*062e3d01SJens Wiklander 
762*062e3d01SJens Wiklander 	put_mpi(&mpi_op);
763*062e3d01SJens Wiklander 
764*062e3d01SJens Wiklander 	if (rc)
765*062e3d01SJens Wiklander 		return 0;
766*062e3d01SJens Wiklander 
767*062e3d01SJens Wiklander 	return 1;
768*062e3d01SJens Wiklander }
769*062e3d01SJens Wiklander 
770*062e3d01SJens Wiklander /*
771*062e3d01SJens Wiklander  * Not so fast FMM implementation based on the normal big int functions.
772*062e3d01SJens Wiklander  *
773*062e3d01SJens Wiklander  * Note that these functions (along with all the other functions in this
774*062e3d01SJens Wiklander  * file) only are used directly by the TA doing bigint arithmetics on its
775*062e3d01SJens Wiklander  * own. Performance of RSA operations in TEE Internal API are not affected
776*062e3d01SJens Wiklander  * by this.
777*062e3d01SJens Wiklander  */
778*062e3d01SJens Wiklander void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len)
779*062e3d01SJens Wiklander {
780*062e3d01SJens Wiklander 	TEE_BigIntInit(bigIntFMM, len);
781*062e3d01SJens Wiklander }
782*062e3d01SJens Wiklander 
783*062e3d01SJens Wiklander void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context __unused,
784*062e3d01SJens Wiklander 			      uint32_t len __unused,
785*062e3d01SJens Wiklander 			      const TEE_BigInt *modulus __unused)
786*062e3d01SJens Wiklander {
787*062e3d01SJens Wiklander }
788*062e3d01SJens Wiklander 
789*062e3d01SJens Wiklander uint32_t TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits)
790*062e3d01SJens Wiklander {
791*062e3d01SJens Wiklander 	return TEE_BigIntSizeInU32(modulusSizeInBits);
792*062e3d01SJens Wiklander }
793*062e3d01SJens Wiklander 
794*062e3d01SJens Wiklander uint32_t TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits __unused)
795*062e3d01SJens Wiklander {
796*062e3d01SJens Wiklander 	/* Return something larger than 0 to keep malloc() and friends happy */
797*062e3d01SJens Wiklander 	return 1;
798*062e3d01SJens Wiklander }
799*062e3d01SJens Wiklander 
800*062e3d01SJens Wiklander void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src,
801*062e3d01SJens Wiklander 			    const TEE_BigInt *n,
802*062e3d01SJens Wiklander 			    const TEE_BigIntFMMContext *context __unused)
803*062e3d01SJens Wiklander {
804*062e3d01SJens Wiklander 	TEE_BigIntMod(dest, src, n);
805*062e3d01SJens Wiklander }
806*062e3d01SJens Wiklander 
807*062e3d01SJens Wiklander void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src,
808*062e3d01SJens Wiklander 			      const TEE_BigInt *n __unused,
809*062e3d01SJens Wiklander 			      const TEE_BigIntFMMContext *context __unused)
810*062e3d01SJens Wiklander {
811*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dst;
812*062e3d01SJens Wiklander 	mbedtls_mpi mpi_src;
813*062e3d01SJens Wiklander 
814*062e3d01SJens Wiklander 	get_mpi(&mpi_dst, dest);
815*062e3d01SJens Wiklander 	get_const_mpi(&mpi_src, src);
816*062e3d01SJens Wiklander 
817*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_copy(&mpi_dst, &mpi_src));
818*062e3d01SJens Wiklander 
819*062e3d01SJens Wiklander 	put_mpi(&mpi_dst);
820*062e3d01SJens Wiklander 	put_mpi(&mpi_src);
821*062e3d01SJens Wiklander }
822*062e3d01SJens Wiklander 
823*062e3d01SJens Wiklander void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1,
824*062e3d01SJens Wiklander 			  const TEE_BigIntFMM *op2, const TEE_BigInt *n,
825*062e3d01SJens Wiklander 			  const TEE_BigIntFMMContext *context __unused)
826*062e3d01SJens Wiklander {
827*062e3d01SJens Wiklander 	mbedtls_mpi mpi_dst;
828*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op1;
829*062e3d01SJens Wiklander 	mbedtls_mpi mpi_op2;
830*062e3d01SJens Wiklander 	mbedtls_mpi mpi_n;
831*062e3d01SJens Wiklander 	mbedtls_mpi mpi_t;
832*062e3d01SJens Wiklander 
833*062e3d01SJens Wiklander 	get_mpi(&mpi_dst, dest);
834*062e3d01SJens Wiklander 	get_const_mpi(&mpi_op1, op1);
835*062e3d01SJens Wiklander 	get_const_mpi(&mpi_op2, op2);
836*062e3d01SJens Wiklander 	get_const_mpi(&mpi_n, n);
837*062e3d01SJens Wiklander 	get_mpi(&mpi_t, NULL);
838*062e3d01SJens Wiklander 
839*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_mul_mpi(&mpi_t, &mpi_op1, &mpi_op2));
840*062e3d01SJens Wiklander 	MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dst, &mpi_t, &mpi_n));
841*062e3d01SJens Wiklander 
842*062e3d01SJens Wiklander 	put_mpi(&mpi_t);
843*062e3d01SJens Wiklander 	put_mpi(&mpi_n);
844*062e3d01SJens Wiklander 	put_mpi(&mpi_op2);
845*062e3d01SJens Wiklander 	put_mpi(&mpi_op1);
846*062e3d01SJens Wiklander 	put_mpi(&mpi_dst);
847*062e3d01SJens Wiklander }
848