1062e3d01SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2062e3d01SJens Wiklander /*
3062e3d01SJens Wiklander * Copyright (c) 2018, Linaro limited
4062e3d01SJens Wiklander */
5062e3d01SJens Wiklander #include <assert.h>
6062e3d01SJens Wiklander #include <mbedtls/bignum.h>
7062e3d01SJens Wiklander #include <mempool.h>
8062e3d01SJens Wiklander #include <stdio.h>
9062e3d01SJens Wiklander #include <string.h>
10062e3d01SJens Wiklander #include <tee_api.h>
11062e3d01SJens Wiklander #include <tee_arith_internal.h>
12062e3d01SJens Wiklander #include <utee_defines.h>
13062e3d01SJens Wiklander #include <utee_syscalls.h>
14062e3d01SJens Wiklander #include <util.h>
15062e3d01SJens Wiklander
1628849defSJeffrey Kardatzke #define MPI_MEMPOOL_SIZE (14 * 1024)
17062e3d01SJens Wiklander
api_panic(const char * func,int line,const char * msg)18062e3d01SJens Wiklander static void __noreturn api_panic(const char *func, int line, const char *msg)
19062e3d01SJens Wiklander {
20062e3d01SJens Wiklander printf("Panic function %s, line %d: %s\n", func, line, msg);
21062e3d01SJens Wiklander TEE_Panic(0xB16127 /*BIGINT*/);
22062e3d01SJens Wiklander while (1)
23062e3d01SJens Wiklander ; /* Panic will crash the thread */
24062e3d01SJens Wiklander }
25062e3d01SJens Wiklander
26062e3d01SJens Wiklander #define API_PANIC(x) api_panic(__func__, __LINE__, x)
27062e3d01SJens Wiklander
mpi_panic(const char * func,int line,int rc)28062e3d01SJens Wiklander static void __noreturn mpi_panic(const char *func, int line, int rc)
29062e3d01SJens Wiklander {
30062e3d01SJens Wiklander printf("Panic function %s, line %d, code %d\n", func, line, rc);
31062e3d01SJens Wiklander TEE_Panic(0xB16127 /*BIGINT*/);
32062e3d01SJens Wiklander while (1)
33062e3d01SJens Wiklander ; /* Panic will crash the thread */
34062e3d01SJens Wiklander }
35062e3d01SJens Wiklander
36062e3d01SJens Wiklander #define MPI_CHECK(x) do { \
37062e3d01SJens Wiklander int _rc = (x); \
38062e3d01SJens Wiklander \
39062e3d01SJens Wiklander if (_rc) \
40062e3d01SJens Wiklander mpi_panic(__func__, __LINE__, _rc); \
41062e3d01SJens Wiklander } while (0)
42062e3d01SJens Wiklander
_TEE_MathAPI_Init(void)43062e3d01SJens Wiklander void _TEE_MathAPI_Init(void)
44062e3d01SJens Wiklander {
45b2dd8747SJens Wiklander static uint8_t data[MPI_MEMPOOL_SIZE] __aligned(MEMPOOL_ALIGN);
46062e3d01SJens Wiklander
47062e3d01SJens Wiklander mbedtls_mpi_mempool = mempool_alloc_pool(data, sizeof(data), NULL);
48062e3d01SJens Wiklander if (!mbedtls_mpi_mempool)
49062e3d01SJens Wiklander API_PANIC("Failed to initialize memory pool");
50062e3d01SJens Wiklander }
51062e3d01SJens Wiklander
52062e3d01SJens Wiklander struct bigint_hdr {
53062e3d01SJens Wiklander int32_t sign;
54062e3d01SJens Wiklander uint16_t alloc_size;
55062e3d01SJens Wiklander uint16_t nblimbs;
56062e3d01SJens Wiklander };
57062e3d01SJens Wiklander
58062e3d01SJens Wiklander #define BIGINT_HDR_SIZE_IN_U32 2
59062e3d01SJens Wiklander
copy_mpi_to_bigint(mbedtls_mpi * mpi,TEE_BigInt * bigInt)607696ab7fSJens Wiklander static TEE_Result copy_mpi_to_bigint(mbedtls_mpi *mpi, TEE_BigInt *bigInt)
61062e3d01SJens Wiklander {
62062e3d01SJens Wiklander struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt;
637696ab7fSJens Wiklander size_t n = mpi->n;
64062e3d01SJens Wiklander
657696ab7fSJens Wiklander /* Trim of eventual insignificant zeroes */
667696ab7fSJens Wiklander while (n && !mpi->p[n - 1])
677696ab7fSJens Wiklander n--;
687696ab7fSJens Wiklander
697696ab7fSJens Wiklander if (hdr->alloc_size < n)
707696ab7fSJens Wiklander return TEE_ERROR_OVERFLOW;
717696ab7fSJens Wiklander
727696ab7fSJens Wiklander hdr->nblimbs = n;
737696ab7fSJens Wiklander hdr->sign = mpi->s;
747696ab7fSJens Wiklander memcpy(hdr + 1, mpi->p, mpi->n * sizeof(mbedtls_mpi_uint));
757696ab7fSJens Wiklander
767696ab7fSJens Wiklander return TEE_SUCCESS;
77062e3d01SJens Wiklander }
78062e3d01SJens Wiklander
79062e3d01SJens Wiklander /*
80062e3d01SJens Wiklander * Initializes a MPI.
81062e3d01SJens Wiklander *
827696ab7fSJens Wiklander * A temporary MPI is allocated and if a bigInt is supplied the MPI is
837696ab7fSJens Wiklander * initialized with the value of the bigInt.
84062e3d01SJens Wiklander */
get_mpi(mbedtls_mpi * mpi,const TEE_BigInt * bigInt)857696ab7fSJens Wiklander static void get_mpi(mbedtls_mpi *mpi, const TEE_BigInt *bigInt)
86062e3d01SJens Wiklander {
87062e3d01SJens Wiklander /*
88062e3d01SJens Wiklander * The way the GP spec is defining the bignums it's
89062e3d01SJens Wiklander * difficult/tricky to do it using 64-bit arithmetics given that
90062e3d01SJens Wiklander * we'd need 64-bit alignment of the data as well.
91062e3d01SJens Wiklander */
92062e3d01SJens Wiklander COMPILE_TIME_ASSERT(sizeof(mbedtls_mpi_uint) == sizeof(uint32_t));
93062e3d01SJens Wiklander
94062e3d01SJens Wiklander /*
95062e3d01SJens Wiklander * The struct bigint_hdr is the overhead added to the bigint and
96062e3d01SJens Wiklander * is required to take exactly 2 uint32_t.
97062e3d01SJens Wiklander */
98062e3d01SJens Wiklander COMPILE_TIME_ASSERT(sizeof(struct bigint_hdr) ==
99062e3d01SJens Wiklander sizeof(uint32_t) * BIGINT_HDR_SIZE_IN_U32);
100062e3d01SJens Wiklander
101062e3d01SJens Wiklander mbedtls_mpi_init_mempool(mpi);
102062e3d01SJens Wiklander
1037696ab7fSJens Wiklander if (bigInt) {
1047696ab7fSJens Wiklander const struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt;
1057696ab7fSJens Wiklander const mbedtls_mpi_uint *p = (const mbedtls_mpi_uint *)(hdr + 1);
1067696ab7fSJens Wiklander size_t n = hdr->nblimbs;
107062e3d01SJens Wiklander
1087696ab7fSJens Wiklander /* Trim of eventual insignificant zeroes */
1097696ab7fSJens Wiklander while (n && !p[n - 1])
1107696ab7fSJens Wiklander n--;
111062e3d01SJens Wiklander
1127696ab7fSJens Wiklander MPI_CHECK(mbedtls_mpi_grow(mpi, n));
1137696ab7fSJens Wiklander mpi->s = hdr->sign;
1147696ab7fSJens Wiklander memcpy(mpi->p, p, n * sizeof(mbedtls_mpi_uint));
115062e3d01SJens Wiklander }
116062e3d01SJens Wiklander }
117062e3d01SJens Wiklander
TEE_BigIntInit(TEE_BigInt * bigInt,size_t len)118fe03ed8bSJens Wiklander void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len)
119062e3d01SJens Wiklander {
120062e3d01SJens Wiklander struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt;
121062e3d01SJens Wiklander
122fe03ed8bSJens Wiklander static_assert(MBEDTLS_MPI_MAX_LIMBS + BIGINT_HDR_SIZE_IN_U32 >=
123fe03ed8bSJens Wiklander CFG_TA_BIGNUM_MAX_BITS / 32);
124fe03ed8bSJens Wiklander
125e6e7781fSJens Wiklander memset(bigInt, 0, len * sizeof(uint32_t));
126062e3d01SJens Wiklander hdr->sign = 1;
127fe03ed8bSJens Wiklander
128fe03ed8bSJens Wiklander /* "gpd.tee.arith.maxBigIntSize" is assigned CFG_TA_BIGNUM_MAX_BITS */
129fe03ed8bSJens Wiklander if (len > CFG_TA_BIGNUM_MAX_BITS / 4)
130062e3d01SJens Wiklander API_PANIC("Too large bigint");
131062e3d01SJens Wiklander hdr->alloc_size = len - BIGINT_HDR_SIZE_IN_U32;
132062e3d01SJens Wiklander }
133062e3d01SJens Wiklander
__GP11_TEE_BigIntInit(TEE_BigInt * bigInt,uint32_t len)134fe03ed8bSJens Wiklander void __GP11_TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len)
135fe03ed8bSJens Wiklander {
136fe03ed8bSJens Wiklander TEE_BigIntInit(bigInt, len);
137fe03ed8bSJens Wiklander }
138fe03ed8bSJens Wiklander
TEE_BigIntConvertFromOctetString(TEE_BigInt * dest,const uint8_t * buffer,size_t bufferLen,int32_t sign)139062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest,
140062e3d01SJens Wiklander const uint8_t *buffer,
141fe03ed8bSJens Wiklander size_t bufferLen, int32_t sign)
142062e3d01SJens Wiklander {
143062e3d01SJens Wiklander TEE_Result res;
144062e3d01SJens Wiklander mbedtls_mpi mpi_dest;
145062e3d01SJens Wiklander
1467696ab7fSJens Wiklander get_mpi(&mpi_dest, NULL);
147062e3d01SJens Wiklander
148062e3d01SJens Wiklander if (mbedtls_mpi_read_binary(&mpi_dest, buffer, bufferLen))
149062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW;
150062e3d01SJens Wiklander else
151062e3d01SJens Wiklander res = TEE_SUCCESS;
152062e3d01SJens Wiklander
153062e3d01SJens Wiklander if (sign < 0)
154062e3d01SJens Wiklander mpi_dest.s = -1;
155062e3d01SJens Wiklander
1567696ab7fSJens Wiklander if (!res)
1577696ab7fSJens Wiklander res = copy_mpi_to_bigint(&mpi_dest, dest);
1587696ab7fSJens Wiklander
1597696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest);
160062e3d01SJens Wiklander
161062e3d01SJens Wiklander return res;
162062e3d01SJens Wiklander }
163062e3d01SJens Wiklander
__GP11_TEE_BigIntConvertFromOctetString(TEE_BigInt * dest,const uint8_t * buffer,uint32_t bufferLen,int32_t sign)164fe03ed8bSJens Wiklander TEE_Result __GP11_TEE_BigIntConvertFromOctetString(TEE_BigInt *dest,
165fe03ed8bSJens Wiklander const uint8_t *buffer,
166fe03ed8bSJens Wiklander uint32_t bufferLen,
167fe03ed8bSJens Wiklander int32_t sign)
168fe03ed8bSJens Wiklander {
169fe03ed8bSJens Wiklander return TEE_BigIntConvertFromOctetString(dest, buffer, bufferLen, sign);
170fe03ed8bSJens Wiklander }
171fe03ed8bSJens Wiklander
TEE_BigIntConvertToOctetString(uint8_t * buffer,size_t * bufferLen,const TEE_BigInt * bigInt)172fe03ed8bSJens Wiklander TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, size_t *bufferLen,
173062e3d01SJens Wiklander const TEE_BigInt *bigInt)
174062e3d01SJens Wiklander {
175062e3d01SJens Wiklander TEE_Result res = TEE_SUCCESS;
176062e3d01SJens Wiklander mbedtls_mpi mpi;
177062e3d01SJens Wiklander size_t sz;
178062e3d01SJens Wiklander
1797696ab7fSJens Wiklander get_mpi(&mpi, bigInt);
180062e3d01SJens Wiklander
181062e3d01SJens Wiklander sz = mbedtls_mpi_size(&mpi);
182062e3d01SJens Wiklander if (sz <= *bufferLen)
183062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_write_binary(&mpi, buffer, sz));
184062e3d01SJens Wiklander else
185062e3d01SJens Wiklander res = TEE_ERROR_SHORT_BUFFER;
186062e3d01SJens Wiklander
187062e3d01SJens Wiklander *bufferLen = sz;
188062e3d01SJens Wiklander
1897696ab7fSJens Wiklander mbedtls_mpi_free(&mpi);
190062e3d01SJens Wiklander
191062e3d01SJens Wiklander return res;
192062e3d01SJens Wiklander }
193062e3d01SJens Wiklander
__GP11_TEE_BigIntConvertToOctetString(uint8_t * buffer,uint32_t * bufferLen,const TEE_BigInt * bigInt)194fe03ed8bSJens Wiklander TEE_Result __GP11_TEE_BigIntConvertToOctetString(uint8_t *buffer,
195fe03ed8bSJens Wiklander uint32_t *bufferLen,
196fe03ed8bSJens Wiklander const TEE_BigInt *bigInt)
197fe03ed8bSJens Wiklander {
198fe03ed8bSJens Wiklander TEE_Result res = TEE_SUCCESS;
199fe03ed8bSJens Wiklander size_t l = *bufferLen;
200fe03ed8bSJens Wiklander
201fe03ed8bSJens Wiklander res = TEE_BigIntConvertToOctetString(buffer, &l, bigInt);
202fe03ed8bSJens Wiklander *bufferLen = l;
203fe03ed8bSJens Wiklander return res;
204fe03ed8bSJens Wiklander }
205fe03ed8bSJens Wiklander
TEE_BigIntConvertFromS32(TEE_BigInt * dest,int32_t shortVal)206062e3d01SJens Wiklander void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal)
207062e3d01SJens Wiklander {
208062e3d01SJens Wiklander mbedtls_mpi mpi;
209062e3d01SJens Wiklander
210062e3d01SJens Wiklander get_mpi(&mpi, dest);
211062e3d01SJens Wiklander
212062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi, shortVal));
213062e3d01SJens Wiklander
2147696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi, dest));
2157696ab7fSJens Wiklander mbedtls_mpi_free(&mpi);
216062e3d01SJens Wiklander }
217062e3d01SJens Wiklander
TEE_BigIntConvertToS32(int32_t * dest,const TEE_BigInt * src)218062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src)
219062e3d01SJens Wiklander {
220062e3d01SJens Wiklander TEE_Result res = TEE_SUCCESS;
221062e3d01SJens Wiklander mbedtls_mpi mpi;
222062e3d01SJens Wiklander uint32_t v;
223062e3d01SJens Wiklander
2247696ab7fSJens Wiklander get_mpi(&mpi, src);
225062e3d01SJens Wiklander
226062e3d01SJens Wiklander if (mbedtls_mpi_write_binary(&mpi, (void *)&v, sizeof(v))) {
227062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW;
228062e3d01SJens Wiklander goto out;
229062e3d01SJens Wiklander }
230062e3d01SJens Wiklander
231062e3d01SJens Wiklander if (mpi.s > 0) {
232062e3d01SJens Wiklander if (ADD_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest))
233062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW;
234062e3d01SJens Wiklander } else {
235062e3d01SJens Wiklander if (SUB_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest))
236062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW;
237062e3d01SJens Wiklander }
238062e3d01SJens Wiklander
239062e3d01SJens Wiklander out:
2407696ab7fSJens Wiklander mbedtls_mpi_free(&mpi);
241062e3d01SJens Wiklander
242062e3d01SJens Wiklander return res;
243062e3d01SJens Wiklander }
244062e3d01SJens Wiklander
TEE_BigIntCmp(const TEE_BigInt * op1,const TEE_BigInt * op2)245062e3d01SJens Wiklander int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2)
246062e3d01SJens Wiklander {
247062e3d01SJens Wiklander mbedtls_mpi mpi1;
248062e3d01SJens Wiklander mbedtls_mpi mpi2;
249062e3d01SJens Wiklander int32_t rc;
250062e3d01SJens Wiklander
2517696ab7fSJens Wiklander get_mpi(&mpi1, op1);
2527696ab7fSJens Wiklander get_mpi(&mpi2, op2);
253062e3d01SJens Wiklander
254062e3d01SJens Wiklander rc = mbedtls_mpi_cmp_mpi(&mpi1, &mpi2);
255062e3d01SJens Wiklander
2567696ab7fSJens Wiklander mbedtls_mpi_free(&mpi1);
2577696ab7fSJens Wiklander mbedtls_mpi_free(&mpi2);
258062e3d01SJens Wiklander
259062e3d01SJens Wiklander return rc;
260062e3d01SJens Wiklander }
261062e3d01SJens Wiklander
TEE_BigIntCmpS32(const TEE_BigInt * op,int32_t shortVal)262062e3d01SJens Wiklander int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal)
263062e3d01SJens Wiklander {
264062e3d01SJens Wiklander mbedtls_mpi mpi;
265062e3d01SJens Wiklander int32_t rc;
266062e3d01SJens Wiklander
2677696ab7fSJens Wiklander get_mpi(&mpi, op);
268062e3d01SJens Wiklander
269062e3d01SJens Wiklander rc = mbedtls_mpi_cmp_int(&mpi, shortVal);
270062e3d01SJens Wiklander
2717696ab7fSJens Wiklander mbedtls_mpi_free(&mpi);
272062e3d01SJens Wiklander
273062e3d01SJens Wiklander return rc;
274062e3d01SJens Wiklander }
275062e3d01SJens Wiklander
TEE_BigIntShiftRight(TEE_BigInt * dest,const TEE_BigInt * op,size_t bits)276062e3d01SJens Wiklander void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits)
277062e3d01SJens Wiklander {
278062e3d01SJens Wiklander mbedtls_mpi mpi_dest;
279062e3d01SJens Wiklander mbedtls_mpi mpi_op;
280062e3d01SJens Wiklander
281062e3d01SJens Wiklander get_mpi(&mpi_dest, dest);
282062e3d01SJens Wiklander
283062e3d01SJens Wiklander if (dest == op) {
284062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits));
285062e3d01SJens Wiklander goto out;
286062e3d01SJens Wiklander }
287062e3d01SJens Wiklander
2887696ab7fSJens Wiklander get_mpi(&mpi_op, op);
289062e3d01SJens Wiklander
290062e3d01SJens Wiklander if (mbedtls_mpi_size(&mpi_dest) >= mbedtls_mpi_size(&mpi_op)) {
291062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_op));
292062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits));
293062e3d01SJens Wiklander } else {
294062e3d01SJens Wiklander mbedtls_mpi mpi_t;
295062e3d01SJens Wiklander
296062e3d01SJens Wiklander get_mpi(&mpi_t, NULL);
297062e3d01SJens Wiklander
298062e3d01SJens Wiklander /*
299062e3d01SJens Wiklander * We're using a temporary buffer to avoid the corner case
300062e3d01SJens Wiklander * where destination is unexpectedly overflowed by up to
301062e3d01SJens Wiklander * @bits number of bits.
302062e3d01SJens Wiklander */
303062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_t, &mpi_op));
304062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&mpi_t, bits));
305062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_t));
306062e3d01SJens Wiklander
3077696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_t);
308062e3d01SJens Wiklander }
309062e3d01SJens Wiklander
3107696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op);
311062e3d01SJens Wiklander
312062e3d01SJens Wiklander out:
3137696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest));
3147696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest);
315062e3d01SJens Wiklander }
316062e3d01SJens Wiklander
__GP11_TEE_BigIntShiftRight(TEE_BigInt * dest,const TEE_BigInt * op,uint32_t bits)317fe03ed8bSJens Wiklander void __GP11_TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op,
318fe03ed8bSJens Wiklander uint32_t bits)
319fe03ed8bSJens Wiklander {
320fe03ed8bSJens Wiklander TEE_BigIntShiftRight(dest, op, bits);
321fe03ed8bSJens Wiklander }
322fe03ed8bSJens Wiklander
TEE_BigIntGetBit(const TEE_BigInt * src,uint32_t bitIndex)323062e3d01SJens Wiklander bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex)
324062e3d01SJens Wiklander {
325062e3d01SJens Wiklander bool rc;
326062e3d01SJens Wiklander mbedtls_mpi mpi;
327062e3d01SJens Wiklander
3287696ab7fSJens Wiklander get_mpi(&mpi, src);
329062e3d01SJens Wiklander
330062e3d01SJens Wiklander rc = mbedtls_mpi_get_bit(&mpi, bitIndex);
331062e3d01SJens Wiklander
3327696ab7fSJens Wiklander mbedtls_mpi_free(&mpi);
333062e3d01SJens Wiklander
334062e3d01SJens Wiklander return rc;
335062e3d01SJens Wiklander }
336062e3d01SJens Wiklander
TEE_BigIntGetBitCount(const TEE_BigInt * src)337062e3d01SJens Wiklander uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src)
338062e3d01SJens Wiklander {
339062e3d01SJens Wiklander uint32_t rc;
340062e3d01SJens Wiklander mbedtls_mpi mpi;
341062e3d01SJens Wiklander
3427696ab7fSJens Wiklander get_mpi(&mpi, src);
343062e3d01SJens Wiklander
344062e3d01SJens Wiklander rc = mbedtls_mpi_bitlen(&mpi);
345062e3d01SJens Wiklander
3467696ab7fSJens Wiklander mbedtls_mpi_free(&mpi);
347062e3d01SJens Wiklander
348062e3d01SJens Wiklander return rc;
349062e3d01SJens Wiklander }
350062e3d01SJens Wiklander
TEE_BigIntSetBit(TEE_BigInt * op,uint32_t bitIndex,bool value)35142023295SJens Wiklander TEE_Result TEE_BigIntSetBit(TEE_BigInt *op, uint32_t bitIndex, bool value)
35242023295SJens Wiklander {
35342023295SJens Wiklander TEE_Result res = TEE_SUCCESS;
35442023295SJens Wiklander mbedtls_mpi mpi = { };
35542023295SJens Wiklander int rc = 0;
35642023295SJens Wiklander
35742023295SJens Wiklander get_mpi(&mpi, op);
35842023295SJens Wiklander
35942023295SJens Wiklander rc = mbedtls_mpi_set_bit(&mpi, bitIndex, value);
36042023295SJens Wiklander if (rc)
36142023295SJens Wiklander res = TEE_ERROR_OVERFLOW;
36242023295SJens Wiklander else
36342023295SJens Wiklander res = copy_mpi_to_bigint(&mpi, op);
36442023295SJens Wiklander
36542023295SJens Wiklander mbedtls_mpi_free(&mpi);
36642023295SJens Wiklander
36742023295SJens Wiklander return res;
36842023295SJens Wiklander }
36942023295SJens Wiklander
TEE_BigIntAssign(TEE_BigInt * dest,const TEE_BigInt * src)370af4bcf34SJens Wiklander TEE_Result TEE_BigIntAssign(TEE_BigInt *dest, const TEE_BigInt *src)
371af4bcf34SJens Wiklander {
372af4bcf34SJens Wiklander const struct bigint_hdr *src_hdr = (struct bigint_hdr *)src;
373af4bcf34SJens Wiklander struct bigint_hdr *dst_hdr = (struct bigint_hdr *)dest;
374af4bcf34SJens Wiklander
375af4bcf34SJens Wiklander if (dst_hdr == src_hdr)
376af4bcf34SJens Wiklander return TEE_SUCCESS;
377af4bcf34SJens Wiklander
378af4bcf34SJens Wiklander if (dst_hdr->alloc_size < src_hdr->nblimbs)
379af4bcf34SJens Wiklander return TEE_ERROR_OVERFLOW;
380af4bcf34SJens Wiklander
381af4bcf34SJens Wiklander dst_hdr->nblimbs = src_hdr->nblimbs;
382af4bcf34SJens Wiklander dst_hdr->sign = src_hdr->sign;
383af4bcf34SJens Wiklander memcpy(dst_hdr + 1, src_hdr + 1, src_hdr->nblimbs * sizeof(uint32_t));
384af4bcf34SJens Wiklander
385af4bcf34SJens Wiklander return TEE_SUCCESS;
386af4bcf34SJens Wiklander }
387af4bcf34SJens Wiklander
TEE_BigIntAbs(TEE_BigInt * dest,const TEE_BigInt * src)3883be980f7SJens Wiklander TEE_Result TEE_BigIntAbs(TEE_BigInt *dest, const TEE_BigInt *src)
3893be980f7SJens Wiklander {
3903be980f7SJens Wiklander TEE_Result res = TEE_BigIntAssign(dest, src);
3913be980f7SJens Wiklander
3923be980f7SJens Wiklander if (!res)
3933be980f7SJens Wiklander ((struct bigint_hdr *)dest)->sign = 1;
3943be980f7SJens Wiklander
3953be980f7SJens Wiklander return res;
3963be980f7SJens Wiklander }
3973be980f7SJens Wiklander
bigint_binary(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2,int (* func)(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * B))398062e3d01SJens Wiklander static void bigint_binary(TEE_BigInt *dest, const TEE_BigInt *op1,
399062e3d01SJens Wiklander const TEE_BigInt *op2,
400062e3d01SJens Wiklander int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A,
401062e3d01SJens Wiklander const mbedtls_mpi *B))
402062e3d01SJens Wiklander {
403062e3d01SJens Wiklander mbedtls_mpi mpi_dest;
404062e3d01SJens Wiklander mbedtls_mpi mpi_op1;
405062e3d01SJens Wiklander mbedtls_mpi mpi_op2;
406062e3d01SJens Wiklander mbedtls_mpi *pop1 = &mpi_op1;
407062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2;
408062e3d01SJens Wiklander
409062e3d01SJens Wiklander get_mpi(&mpi_dest, dest);
410062e3d01SJens Wiklander
411062e3d01SJens Wiklander if (op1 == dest)
412062e3d01SJens Wiklander pop1 = &mpi_dest;
413062e3d01SJens Wiklander else
4147696ab7fSJens Wiklander get_mpi(&mpi_op1, op1);
415062e3d01SJens Wiklander
416062e3d01SJens Wiklander if (op2 == dest)
417062e3d01SJens Wiklander pop2 = &mpi_dest;
418062e3d01SJens Wiklander else if (op2 == op1)
419062e3d01SJens Wiklander pop2 = pop1;
420062e3d01SJens Wiklander else
4217696ab7fSJens Wiklander get_mpi(&mpi_op2, op2);
422062e3d01SJens Wiklander
423062e3d01SJens Wiklander MPI_CHECK(func(&mpi_dest, pop1, pop2));
424062e3d01SJens Wiklander
4257696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest));
4267696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest);
427062e3d01SJens Wiklander if (pop1 == &mpi_op1)
4287696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1);
429062e3d01SJens Wiklander if (pop2 == &mpi_op2)
4307696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2);
431062e3d01SJens Wiklander }
432062e3d01SJens Wiklander
bigint_binary_mod(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2,const TEE_BigInt * n,int (* func)(mbedtls_mpi * X,const mbedtls_mpi * A,const mbedtls_mpi * B))433062e3d01SJens Wiklander static void bigint_binary_mod(TEE_BigInt *dest, const TEE_BigInt *op1,
434062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n,
435062e3d01SJens Wiklander int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A,
436062e3d01SJens Wiklander const mbedtls_mpi *B))
437062e3d01SJens Wiklander {
438062e3d01SJens Wiklander mbedtls_mpi mpi_dest;
439062e3d01SJens Wiklander mbedtls_mpi mpi_op1;
440062e3d01SJens Wiklander mbedtls_mpi mpi_op2;
441062e3d01SJens Wiklander mbedtls_mpi mpi_n;
442062e3d01SJens Wiklander mbedtls_mpi *pop1 = &mpi_op1;
443062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2;
444062e3d01SJens Wiklander mbedtls_mpi mpi_t;
445062e3d01SJens Wiklander
44666e18280SJens Wiklander if (TEE_BigIntCmpS32(n, 2) < 0)
44766e18280SJens Wiklander API_PANIC("Modulus is too short");
44866e18280SJens Wiklander
449062e3d01SJens Wiklander get_mpi(&mpi_dest, dest);
4507696ab7fSJens Wiklander get_mpi(&mpi_n, n);
451062e3d01SJens Wiklander
452062e3d01SJens Wiklander if (op1 == dest)
453062e3d01SJens Wiklander pop1 = &mpi_dest;
454062e3d01SJens Wiklander else
4557696ab7fSJens Wiklander get_mpi(&mpi_op1, op1);
456062e3d01SJens Wiklander
457062e3d01SJens Wiklander if (op2 == dest)
458062e3d01SJens Wiklander pop2 = &mpi_dest;
459062e3d01SJens Wiklander else if (op2 == op1)
460062e3d01SJens Wiklander pop2 = pop1;
461062e3d01SJens Wiklander else
4627696ab7fSJens Wiklander get_mpi(&mpi_op2, op2);
463062e3d01SJens Wiklander
464062e3d01SJens Wiklander get_mpi(&mpi_t, NULL);
465062e3d01SJens Wiklander
466062e3d01SJens Wiklander MPI_CHECK(func(&mpi_t, pop1, pop2));
467062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dest, &mpi_t, &mpi_n));
468062e3d01SJens Wiklander
4697696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest));
4707696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest);
471062e3d01SJens Wiklander if (pop1 == &mpi_op1)
4727696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1);
473062e3d01SJens Wiklander if (pop2 == &mpi_op2)
4747696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2);
4757696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_t);
47613218059SMatthieu BERTIN mbedtls_mpi_free(&mpi_n);
477062e3d01SJens Wiklander }
478062e3d01SJens Wiklander
TEE_BigIntAdd(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2)479062e3d01SJens Wiklander void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1,
480062e3d01SJens Wiklander const TEE_BigInt *op2)
481062e3d01SJens Wiklander {
482062e3d01SJens Wiklander bigint_binary(dest, op1, op2, mbedtls_mpi_add_mpi);
483062e3d01SJens Wiklander }
484062e3d01SJens Wiklander
TEE_BigIntSub(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2)485062e3d01SJens Wiklander void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1,
486062e3d01SJens Wiklander const TEE_BigInt *op2)
487062e3d01SJens Wiklander {
488062e3d01SJens Wiklander bigint_binary(dest, op1, op2, mbedtls_mpi_sub_mpi);
489062e3d01SJens Wiklander }
490062e3d01SJens Wiklander
TEE_BigIntNeg(TEE_BigInt * dest,const TEE_BigInt * src)491062e3d01SJens Wiklander void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src)
492062e3d01SJens Wiklander {
493062e3d01SJens Wiklander mbedtls_mpi mpi_dest;
494062e3d01SJens Wiklander
495062e3d01SJens Wiklander get_mpi(&mpi_dest, dest);
496062e3d01SJens Wiklander
497062e3d01SJens Wiklander if (dest != src) {
498062e3d01SJens Wiklander mbedtls_mpi mpi_src;
499062e3d01SJens Wiklander
5007696ab7fSJens Wiklander get_mpi(&mpi_src, src);
501062e3d01SJens Wiklander
502062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_src));
503062e3d01SJens Wiklander
5047696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_src);
505062e3d01SJens Wiklander }
506062e3d01SJens Wiklander
507062e3d01SJens Wiklander mpi_dest.s *= -1;
508062e3d01SJens Wiklander
5097696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest));
5107696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest);
511062e3d01SJens Wiklander }
512062e3d01SJens Wiklander
TEE_BigIntMul(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2)513062e3d01SJens Wiklander void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1,
514062e3d01SJens Wiklander const TEE_BigInt *op2)
515062e3d01SJens Wiklander {
51698efc118SJerome Forissier size_t bs1 = TEE_BigIntGetBitCount(op1);
51798efc118SJerome Forissier size_t bs2 = TEE_BigIntGetBitCount(op2);
51898efc118SJerome Forissier size_t s = TEE_BigIntSizeInU32(bs1) + TEE_BigIntSizeInU32(bs2);
51998efc118SJerome Forissier TEE_BigInt zero[TEE_BigIntSizeInU32(1)] = { 0 };
52098efc118SJerome Forissier TEE_BigInt *tmp = NULL;
52198efc118SJerome Forissier
52298efc118SJerome Forissier tmp = mempool_alloc(mbedtls_mpi_mempool, sizeof(uint32_t) * s);
52398efc118SJerome Forissier if (!tmp)
52498efc118SJerome Forissier TEE_Panic(TEE_ERROR_OUT_OF_MEMORY);
52598efc118SJerome Forissier
52698efc118SJerome Forissier TEE_BigIntInit(tmp, s);
52798efc118SJerome Forissier TEE_BigIntInit(zero, TEE_BigIntSizeInU32(1));
52898efc118SJerome Forissier
52998efc118SJerome Forissier bigint_binary(tmp, op1, op2, mbedtls_mpi_mul_mpi);
53098efc118SJerome Forissier
53198efc118SJerome Forissier TEE_BigIntAdd(dest, tmp, zero);
53298efc118SJerome Forissier
53398efc118SJerome Forissier mempool_free(mbedtls_mpi_mempool, tmp);
534062e3d01SJens Wiklander }
535062e3d01SJens Wiklander
TEE_BigIntSquare(TEE_BigInt * dest,const TEE_BigInt * op)536062e3d01SJens Wiklander void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op)
537062e3d01SJens Wiklander {
538062e3d01SJens Wiklander TEE_BigIntMul(dest, op, op);
539062e3d01SJens Wiklander }
540062e3d01SJens Wiklander
TEE_BigIntDiv(TEE_BigInt * dest_q,TEE_BigInt * dest_r,const TEE_BigInt * op1,const TEE_BigInt * op2)541062e3d01SJens Wiklander void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r,
542062e3d01SJens Wiklander const TEE_BigInt *op1, const TEE_BigInt *op2)
543062e3d01SJens Wiklander {
544062e3d01SJens Wiklander mbedtls_mpi mpi_dest_q;
545062e3d01SJens Wiklander mbedtls_mpi mpi_dest_r;
546062e3d01SJens Wiklander mbedtls_mpi mpi_op1;
547062e3d01SJens Wiklander mbedtls_mpi mpi_op2;
548062e3d01SJens Wiklander mbedtls_mpi *pop1 = &mpi_op1;
549062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2;
550062e3d01SJens Wiklander
551062e3d01SJens Wiklander get_mpi(&mpi_dest_q, dest_q);
552062e3d01SJens Wiklander get_mpi(&mpi_dest_r, dest_r);
553062e3d01SJens Wiklander
554062e3d01SJens Wiklander if (op1 == dest_q)
555062e3d01SJens Wiklander pop1 = &mpi_dest_q;
556062e3d01SJens Wiklander else if (op1 == dest_r)
557062e3d01SJens Wiklander pop1 = &mpi_dest_r;
558062e3d01SJens Wiklander else
5597696ab7fSJens Wiklander get_mpi(&mpi_op1, op1);
560062e3d01SJens Wiklander
561062e3d01SJens Wiklander if (op2 == dest_q)
562062e3d01SJens Wiklander pop2 = &mpi_dest_q;
563062e3d01SJens Wiklander else if (op2 == dest_r)
564062e3d01SJens Wiklander pop2 = &mpi_dest_r;
565062e3d01SJens Wiklander else if (op2 == op1)
566062e3d01SJens Wiklander pop2 = pop1;
567062e3d01SJens Wiklander else
5687696ab7fSJens Wiklander get_mpi(&mpi_op2, op2);
569062e3d01SJens Wiklander
570062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_div_mpi(&mpi_dest_q, &mpi_dest_r, pop1, pop2));
571062e3d01SJens Wiklander
572a874dbbdSJens Wiklander if (dest_q)
5737696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_q, dest_q));
574a874dbbdSJens Wiklander if (dest_r)
5757696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_r, dest_r));
5767696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest_q);
5777696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest_r);
578062e3d01SJens Wiklander if (pop1 == &mpi_op1)
5797696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1);
580062e3d01SJens Wiklander if (pop2 == &mpi_op2)
5817696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2);
582062e3d01SJens Wiklander }
583062e3d01SJens Wiklander
TEE_BigIntMod(TEE_BigInt * dest,const TEE_BigInt * op,const TEE_BigInt * n)584062e3d01SJens Wiklander void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n)
585062e3d01SJens Wiklander {
586062e3d01SJens Wiklander if (TEE_BigIntCmpS32(n, 2) < 0)
587062e3d01SJens Wiklander API_PANIC("Modulus is too short");
588062e3d01SJens Wiklander
589062e3d01SJens Wiklander bigint_binary(dest, op, n, mbedtls_mpi_mod_mpi);
590062e3d01SJens Wiklander }
591062e3d01SJens Wiklander
TEE_BigIntAddMod(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2,const TEE_BigInt * n)592062e3d01SJens Wiklander void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1,
593062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n)
594062e3d01SJens Wiklander {
595062e3d01SJens Wiklander bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_add_mpi);
596062e3d01SJens Wiklander }
597062e3d01SJens Wiklander
TEE_BigIntSubMod(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2,const TEE_BigInt * n)598062e3d01SJens Wiklander void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1,
599062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n)
600062e3d01SJens Wiklander {
601062e3d01SJens Wiklander bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_sub_mpi);
602062e3d01SJens Wiklander }
603062e3d01SJens Wiklander
TEE_BigIntMulMod(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2,const TEE_BigInt * n)604062e3d01SJens Wiklander void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1,
605062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n)
606062e3d01SJens Wiklander {
607062e3d01SJens Wiklander bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_mul_mpi);
608062e3d01SJens Wiklander }
609062e3d01SJens Wiklander
TEE_BigIntSquareMod(TEE_BigInt * dest,const TEE_BigInt * op,const TEE_BigInt * n)610062e3d01SJens Wiklander void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op,
611062e3d01SJens Wiklander const TEE_BigInt *n)
612062e3d01SJens Wiklander {
613062e3d01SJens Wiklander TEE_BigIntMulMod(dest, op, op, n);
614062e3d01SJens Wiklander }
615062e3d01SJens Wiklander
TEE_BigIntInvMod(TEE_BigInt * dest,const TEE_BigInt * op,const TEE_BigInt * n)616062e3d01SJens Wiklander void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op,
617062e3d01SJens Wiklander const TEE_BigInt *n)
618062e3d01SJens Wiklander {
619062e3d01SJens Wiklander mbedtls_mpi mpi_dest;
620062e3d01SJens Wiklander mbedtls_mpi mpi_op;
621062e3d01SJens Wiklander mbedtls_mpi mpi_n;
622062e3d01SJens Wiklander mbedtls_mpi *pop = &mpi_op;
623062e3d01SJens Wiklander
6245bb4e062SJens Wiklander if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0)
6255bb4e062SJens Wiklander API_PANIC("too small modulus or trying to invert zero");
6265bb4e062SJens Wiklander
627062e3d01SJens Wiklander get_mpi(&mpi_dest, dest);
6287696ab7fSJens Wiklander get_mpi(&mpi_n, n);
629062e3d01SJens Wiklander
630062e3d01SJens Wiklander if (op == dest)
631062e3d01SJens Wiklander pop = &mpi_dest;
632062e3d01SJens Wiklander else
6337696ab7fSJens Wiklander get_mpi(&mpi_op, op);
634062e3d01SJens Wiklander
635062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_inv_mod(&mpi_dest, pop, &mpi_n));
636062e3d01SJens Wiklander
6377696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest));
6387696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dest);
6397696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_n);
640062e3d01SJens Wiklander if (pop == &mpi_op)
6417696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op);
642062e3d01SJens Wiklander }
643062e3d01SJens Wiklander
TEE_BigIntRelativePrime(const TEE_BigInt * op1,const TEE_BigInt * op2)644062e3d01SJens Wiklander bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2)
645062e3d01SJens Wiklander {
646062e3d01SJens Wiklander bool rc;
647062e3d01SJens Wiklander mbedtls_mpi mpi_op1;
648062e3d01SJens Wiklander mbedtls_mpi mpi_op2;
649062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2;
650062e3d01SJens Wiklander mbedtls_mpi gcd;
651062e3d01SJens Wiklander
6527696ab7fSJens Wiklander get_mpi(&mpi_op1, op1);
653062e3d01SJens Wiklander
654062e3d01SJens Wiklander if (op2 == op1)
655062e3d01SJens Wiklander pop2 = &mpi_op1;
656062e3d01SJens Wiklander else
6577696ab7fSJens Wiklander get_mpi(&mpi_op2, op2);
658062e3d01SJens Wiklander
659062e3d01SJens Wiklander get_mpi(&gcd, NULL);
660062e3d01SJens Wiklander
661062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_gcd(&gcd, &mpi_op1, &mpi_op2));
662062e3d01SJens Wiklander
663062e3d01SJens Wiklander rc = !mbedtls_mpi_cmp_int(&gcd, 1);
664062e3d01SJens Wiklander
6657696ab7fSJens Wiklander mbedtls_mpi_free(&gcd);
6667696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1);
667062e3d01SJens Wiklander if (pop2 == &mpi_op2)
6687696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2);
669062e3d01SJens Wiklander
670062e3d01SJens Wiklander return rc;
671062e3d01SJens Wiklander }
672062e3d01SJens Wiklander
mpi_is_odd(mbedtls_mpi * x)673062e3d01SJens Wiklander static bool mpi_is_odd(mbedtls_mpi *x)
674062e3d01SJens Wiklander {
675062e3d01SJens Wiklander return mbedtls_mpi_get_bit(x, 0);
676062e3d01SJens Wiklander }
677062e3d01SJens Wiklander
mpi_is_even(mbedtls_mpi * x)678062e3d01SJens Wiklander static bool mpi_is_even(mbedtls_mpi *x)
679062e3d01SJens Wiklander {
680062e3d01SJens Wiklander return !mpi_is_odd(x);
681062e3d01SJens Wiklander }
682062e3d01SJens Wiklander
TEE_BigIntExpMod(TEE_BigInt * dest,const TEE_BigInt * op1,const TEE_BigInt * op2,const TEE_BigInt * n,const TEE_BigIntFMMContext * context __unused)6836214424fSJens Wiklander TEE_Result TEE_BigIntExpMod(TEE_BigInt *dest, const TEE_BigInt *op1,
6846214424fSJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n,
6856214424fSJens Wiklander const TEE_BigIntFMMContext *context __unused)
6866214424fSJens Wiklander {
6876214424fSJens Wiklander TEE_Result res = TEE_SUCCESS;
6886214424fSJens Wiklander mbedtls_mpi mpi_dest = { };
6896214424fSJens Wiklander mbedtls_mpi mpi_op1 = { };
6906214424fSJens Wiklander mbedtls_mpi mpi_op2 = { };
6916214424fSJens Wiklander mbedtls_mpi mpi_n = { };
6926214424fSJens Wiklander mbedtls_mpi *pop1 = &mpi_op1;
6936214424fSJens Wiklander mbedtls_mpi *pop2 = &mpi_op2;
6946214424fSJens Wiklander
6956214424fSJens Wiklander get_mpi(&mpi_dest, dest);
6966214424fSJens Wiklander get_mpi(&mpi_n, n);
6976214424fSJens Wiklander if (op1 == dest)
6986214424fSJens Wiklander pop1 = &mpi_dest;
6996214424fSJens Wiklander else
7006214424fSJens Wiklander get_mpi(&mpi_op1, op1);
7016214424fSJens Wiklander
7026214424fSJens Wiklander if (op2 == dest)
7036214424fSJens Wiklander pop2 = &mpi_dest;
7046214424fSJens Wiklander else if (op2 == op1)
7056214424fSJens Wiklander pop2 = pop1;
7066214424fSJens Wiklander else
7076214424fSJens Wiklander get_mpi(&mpi_op2, op2);
7086214424fSJens Wiklander
7096214424fSJens Wiklander if (mbedtls_mpi_cmp_int(&mpi_n, 2) <= 0)
7106214424fSJens Wiklander API_PANIC("too small modulus");
7116214424fSJens Wiklander if (!mpi_is_odd(&mpi_n)) {
7126214424fSJens Wiklander res = TEE_ERROR_NOT_SUPPORTED;
7136214424fSJens Wiklander goto out;
7146214424fSJens Wiklander }
7156214424fSJens Wiklander
7166214424fSJens Wiklander MPI_CHECK(mbedtls_mpi_exp_mod(&mpi_dest, pop1, pop2, &mpi_n, NULL));
7176214424fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest));
7186214424fSJens Wiklander out:
7196214424fSJens Wiklander mbedtls_mpi_free(&mpi_dest);
7206214424fSJens Wiklander mbedtls_mpi_free(&mpi_n);
7216214424fSJens Wiklander if (pop1 == &mpi_op1)
7226214424fSJens Wiklander mbedtls_mpi_free(&mpi_op1);
7236214424fSJens Wiklander if (pop2 == &mpi_op2)
7246214424fSJens Wiklander mbedtls_mpi_free(&mpi_op2);
7256214424fSJens Wiklander
7266214424fSJens Wiklander return res;
7276214424fSJens Wiklander }
7286214424fSJens Wiklander
mpi_egcd(mbedtls_mpi * gcd,mbedtls_mpi * a,mbedtls_mpi * b,mbedtls_mpi * x_in,mbedtls_mpi * y_in)729062e3d01SJens Wiklander static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b,
730062e3d01SJens Wiklander mbedtls_mpi *x_in, mbedtls_mpi *y_in)
731062e3d01SJens Wiklander {
732062e3d01SJens Wiklander mbedtls_mpi_uint k;
733062e3d01SJens Wiklander mbedtls_mpi A;
734062e3d01SJens Wiklander mbedtls_mpi B;
735062e3d01SJens Wiklander mbedtls_mpi C;
736062e3d01SJens Wiklander mbedtls_mpi D;
737062e3d01SJens Wiklander mbedtls_mpi x;
738062e3d01SJens Wiklander mbedtls_mpi y;
739062e3d01SJens Wiklander mbedtls_mpi u;
740062e3d01SJens Wiklander
741062e3d01SJens Wiklander get_mpi(&A, NULL);
742062e3d01SJens Wiklander get_mpi(&B, NULL);
743062e3d01SJens Wiklander get_mpi(&C, NULL);
744062e3d01SJens Wiklander get_mpi(&D, NULL);
745062e3d01SJens Wiklander get_mpi(&x, NULL);
746062e3d01SJens Wiklander get_mpi(&y, NULL);
747062e3d01SJens Wiklander get_mpi(&u, NULL);
748062e3d01SJens Wiklander
749062e3d01SJens Wiklander /* have y < x from assumption */
750062e3d01SJens Wiklander if (!mbedtls_mpi_cmp_int(y_in, 0)) {
751062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(a, 1));
752062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(b, 0));
753062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(gcd, x_in));
754062e3d01SJens Wiklander goto out;
755062e3d01SJens Wiklander }
756062e3d01SJens Wiklander
757062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&x, x_in));
758062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&y, y_in));
759062e3d01SJens Wiklander
760062e3d01SJens Wiklander k = 0;
761062e3d01SJens Wiklander while (mpi_is_even(&x) && mpi_is_even(&y)) {
762062e3d01SJens Wiklander k++;
763062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&x, 1));
764062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&y, 1));
765062e3d01SJens Wiklander }
766062e3d01SJens Wiklander
767062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&u, &x));
768062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(gcd, &y));
769062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&A, 1));
770062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&B, 0));
771062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&C, 0));
772062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&D, 1));
773062e3d01SJens Wiklander
774062e3d01SJens Wiklander while (mbedtls_mpi_cmp_int(&u, 0)) {
775062e3d01SJens Wiklander while (mpi_is_even(&u)) {
776062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&u, 1));
777062e3d01SJens Wiklander if (mpi_is_odd(&A) || mpi_is_odd(&B)) {
778062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_add_mpi(&A, &A, &y));
779062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &x));
780062e3d01SJens Wiklander }
781062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&A, 1));
782062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&B, 1));
783062e3d01SJens Wiklander }
784062e3d01SJens Wiklander
785062e3d01SJens Wiklander while (mpi_is_even(gcd)) {
786062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(gcd, 1));
787062e3d01SJens Wiklander if (mpi_is_odd(&C) || mpi_is_odd(&D)) {
788062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_add_mpi(&C, &C, &y));
789062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &x));
790062e3d01SJens Wiklander }
791062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&C, 1));
792062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&D, 1));
793062e3d01SJens Wiklander
794062e3d01SJens Wiklander }
795062e3d01SJens Wiklander
796062e3d01SJens Wiklander if (mbedtls_mpi_cmp_mpi(&u, gcd) >= 0) {
797062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&u, &u, gcd));
798062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&A, &A, &C));
799062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &D));
800062e3d01SJens Wiklander } else {
801062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(gcd, gcd, &u));
802062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&C, &C, &A));
803062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &B));
804062e3d01SJens Wiklander }
805062e3d01SJens Wiklander }
806062e3d01SJens Wiklander
807062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(a, &C));
808062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(b, &D));
809062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_l(gcd, k));
810062e3d01SJens Wiklander
811062e3d01SJens Wiklander out:
8127696ab7fSJens Wiklander mbedtls_mpi_free(&A);
8137696ab7fSJens Wiklander mbedtls_mpi_free(&B);
8147696ab7fSJens Wiklander mbedtls_mpi_free(&C);
8157696ab7fSJens Wiklander mbedtls_mpi_free(&D);
8167696ab7fSJens Wiklander mbedtls_mpi_free(&x);
8177696ab7fSJens Wiklander mbedtls_mpi_free(&y);
8187696ab7fSJens Wiklander mbedtls_mpi_free(&u);
819062e3d01SJens Wiklander }
820062e3d01SJens Wiklander
TEE_BigIntComputeExtendedGcd(TEE_BigInt * gcd,TEE_BigInt * u,TEE_BigInt * v,const TEE_BigInt * op1,const TEE_BigInt * op2)821062e3d01SJens Wiklander void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u,
822062e3d01SJens Wiklander TEE_BigInt *v, const TEE_BigInt *op1,
823062e3d01SJens Wiklander const TEE_BigInt *op2)
824062e3d01SJens Wiklander {
825062e3d01SJens Wiklander mbedtls_mpi mpi_gcd_res;
826062e3d01SJens Wiklander mbedtls_mpi mpi_op1;
827062e3d01SJens Wiklander mbedtls_mpi mpi_op2;
828062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2;
829062e3d01SJens Wiklander
830062e3d01SJens Wiklander get_mpi(&mpi_gcd_res, gcd);
8317696ab7fSJens Wiklander get_mpi(&mpi_op1, op1);
832062e3d01SJens Wiklander
833062e3d01SJens Wiklander if (op2 == op1)
834062e3d01SJens Wiklander pop2 = &mpi_op1;
835062e3d01SJens Wiklander else
8367696ab7fSJens Wiklander get_mpi(&mpi_op2, op2);
837062e3d01SJens Wiklander
838062e3d01SJens Wiklander if (!u && !v) {
839b6fa905fSJens Wiklander MPI_CHECK(mbedtls_mpi_gcd(&mpi_gcd_res, &mpi_op1, pop2));
840062e3d01SJens Wiklander } else {
841062e3d01SJens Wiklander mbedtls_mpi mpi_u;
842062e3d01SJens Wiklander mbedtls_mpi mpi_v;
843062e3d01SJens Wiklander int8_t s1 = mpi_op1.s;
844062e3d01SJens Wiklander int8_t s2 = pop2->s;
845062e3d01SJens Wiklander int cmp;
846062e3d01SJens Wiklander
847062e3d01SJens Wiklander mpi_op1.s = 1;
848062e3d01SJens Wiklander pop2->s = 1;
849062e3d01SJens Wiklander
850062e3d01SJens Wiklander get_mpi(&mpi_u, u);
851062e3d01SJens Wiklander get_mpi(&mpi_v, v);
852062e3d01SJens Wiklander
853062e3d01SJens Wiklander cmp = mbedtls_mpi_cmp_abs(&mpi_op1, pop2);
854062e3d01SJens Wiklander if (cmp == 0) {
855062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_gcd_res, &mpi_op1));
856062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi_u, 1));
857062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi_v, 0));
858062e3d01SJens Wiklander } else if (cmp > 0) {
859062e3d01SJens Wiklander mpi_egcd(&mpi_gcd_res, &mpi_u, &mpi_v, &mpi_op1, pop2);
860062e3d01SJens Wiklander } else {
861062e3d01SJens Wiklander mpi_egcd(&mpi_gcd_res, &mpi_v, &mpi_u, pop2, &mpi_op1);
862062e3d01SJens Wiklander }
863062e3d01SJens Wiklander
864062e3d01SJens Wiklander mpi_u.s *= s1;
865062e3d01SJens Wiklander mpi_v.s *= s2;
866062e3d01SJens Wiklander
867*703ebb79SEtienne Carriere if (u)
8687696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_u, u));
869*703ebb79SEtienne Carriere if (v)
8707696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_v, v));
8717696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_u);
8727696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_v);
873062e3d01SJens Wiklander }
874062e3d01SJens Wiklander
8757696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_gcd_res, gcd));
8767696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_gcd_res);
8777696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1);
878062e3d01SJens Wiklander if (pop2 == &mpi_op2)
8797696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2);
880062e3d01SJens Wiklander }
881062e3d01SJens Wiklander
rng_read(void * ignored __unused,unsigned char * buf,size_t blen)882062e3d01SJens Wiklander static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen)
883062e3d01SJens Wiklander {
8842c028fdeSJerome Forissier if (_utee_cryp_random_number_generate(buf, blen))
885062e3d01SJens Wiklander return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
886062e3d01SJens Wiklander return 0;
887062e3d01SJens Wiklander }
888062e3d01SJens Wiklander
TEE_BigIntIsProbablePrime(const TEE_BigInt * op,uint32_t confidenceLevel)889062e3d01SJens Wiklander int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op,
89032b31808SJens Wiklander uint32_t confidenceLevel)
891062e3d01SJens Wiklander {
892062e3d01SJens Wiklander int rc;
893062e3d01SJens Wiklander mbedtls_mpi mpi_op;
894062e3d01SJens Wiklander
8957696ab7fSJens Wiklander get_mpi(&mpi_op, op);
896062e3d01SJens Wiklander
89732b31808SJens Wiklander rc = mbedtls_mpi_is_prime_ext(&mpi_op, MAX(confidenceLevel, 80U),
89832b31808SJens Wiklander rng_read, NULL);
899062e3d01SJens Wiklander
9007696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op);
901062e3d01SJens Wiklander
902062e3d01SJens Wiklander if (rc)
903062e3d01SJens Wiklander return 0;
904062e3d01SJens Wiklander
905062e3d01SJens Wiklander return 1;
906062e3d01SJens Wiklander }
907062e3d01SJens Wiklander
908062e3d01SJens Wiklander /*
909062e3d01SJens Wiklander * Not so fast FMM implementation based on the normal big int functions.
910062e3d01SJens Wiklander *
911062e3d01SJens Wiklander * Note that these functions (along with all the other functions in this
912062e3d01SJens Wiklander * file) only are used directly by the TA doing bigint arithmetics on its
913062e3d01SJens Wiklander * own. Performance of RSA operations in TEE Internal API are not affected
914062e3d01SJens Wiklander * by this.
915062e3d01SJens Wiklander */
TEE_BigIntInitFMM(TEE_BigIntFMM * bigIntFMM,size_t len)916fe03ed8bSJens Wiklander void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len)
917062e3d01SJens Wiklander {
918062e3d01SJens Wiklander TEE_BigIntInit(bigIntFMM, len);
919062e3d01SJens Wiklander }
920062e3d01SJens Wiklander
__GP11_TEE_BigIntInitFMM(TEE_BigIntFMM * bigIntFMM,uint32_t len)921fe03ed8bSJens Wiklander void __GP11_TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len)
922fe03ed8bSJens Wiklander {
923fe03ed8bSJens Wiklander TEE_BigIntInitFMM(bigIntFMM, len);
924fe03ed8bSJens Wiklander }
925fe03ed8bSJens Wiklander
TEE_BigIntInitFMMContext(TEE_BigIntFMMContext * context __unused,size_t len __unused,const TEE_BigInt * modulus __unused)926062e3d01SJens Wiklander void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context __unused,
927fe03ed8bSJens Wiklander size_t len __unused,
928062e3d01SJens Wiklander const TEE_BigInt *modulus __unused)
929062e3d01SJens Wiklander {
930062e3d01SJens Wiklander }
931062e3d01SJens Wiklander
__GP11_TEE_BigIntInitFMMContext(TEE_BigIntFMMContext * context,uint32_t len,const TEE_BigInt * modulus)932fe03ed8bSJens Wiklander void __GP11_TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context,
933fe03ed8bSJens Wiklander uint32_t len, const TEE_BigInt *modulus)
934fe03ed8bSJens Wiklander {
935fe03ed8bSJens Wiklander TEE_BigIntInitFMMContext(context, len, modulus);
936fe03ed8bSJens Wiklander }
937fe03ed8bSJens Wiklander
TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext * context __unused,size_t len __unused,const TEE_BigInt * modulus __unused)938fe03ed8bSJens Wiklander TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context __unused,
939fe03ed8bSJens Wiklander size_t len __unused,
940fe03ed8bSJens Wiklander const TEE_BigInt *modulus __unused)
941fe03ed8bSJens Wiklander {
942fe03ed8bSJens Wiklander return TEE_SUCCESS;
943fe03ed8bSJens Wiklander }
944fe03ed8bSJens Wiklander
TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits)945fe03ed8bSJens Wiklander size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits)
946062e3d01SJens Wiklander {
947062e3d01SJens Wiklander return TEE_BigIntSizeInU32(modulusSizeInBits);
948062e3d01SJens Wiklander }
949062e3d01SJens Wiklander
__GP11_TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits)950fe03ed8bSJens Wiklander uint32_t __GP11_TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits)
951fe03ed8bSJens Wiklander {
952fe03ed8bSJens Wiklander return TEE_BigIntFMMSizeInU32(modulusSizeInBits);
953fe03ed8bSJens Wiklander }
954fe03ed8bSJens Wiklander
TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits __unused)955fe03ed8bSJens Wiklander size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits __unused)
956062e3d01SJens Wiklander {
957062e3d01SJens Wiklander /* Return something larger than 0 to keep malloc() and friends happy */
958062e3d01SJens Wiklander return 1;
959062e3d01SJens Wiklander }
960062e3d01SJens Wiklander
__GP11_TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits)961fe03ed8bSJens Wiklander uint32_t __GP11_TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits)
962fe03ed8bSJens Wiklander {
963fe03ed8bSJens Wiklander return TEE_BigIntFMMContextSizeInU32(modulusSizeInBits);
964fe03ed8bSJens Wiklander }
965fe03ed8bSJens Wiklander
TEE_BigIntConvertToFMM(TEE_BigIntFMM * dest,const TEE_BigInt * src,const TEE_BigInt * n,const TEE_BigIntFMMContext * context __unused)966062e3d01SJens Wiklander void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src,
967062e3d01SJens Wiklander const TEE_BigInt *n,
968062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused)
969062e3d01SJens Wiklander {
970062e3d01SJens Wiklander TEE_BigIntMod(dest, src, n);
971062e3d01SJens Wiklander }
972062e3d01SJens Wiklander
TEE_BigIntConvertFromFMM(TEE_BigInt * dest,const TEE_BigIntFMM * src,const TEE_BigInt * n __unused,const TEE_BigIntFMMContext * context __unused)973062e3d01SJens Wiklander void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src,
974062e3d01SJens Wiklander const TEE_BigInt *n __unused,
975062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused)
976062e3d01SJens Wiklander {
977062e3d01SJens Wiklander mbedtls_mpi mpi_dst;
978062e3d01SJens Wiklander mbedtls_mpi mpi_src;
979062e3d01SJens Wiklander
980062e3d01SJens Wiklander get_mpi(&mpi_dst, dest);
9817696ab7fSJens Wiklander get_mpi(&mpi_src, src);
982062e3d01SJens Wiklander
983062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dst, &mpi_src));
984062e3d01SJens Wiklander
9857696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest));
9867696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dst);
9877696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_src);
988062e3d01SJens Wiklander }
989062e3d01SJens Wiklander
TEE_BigIntComputeFMM(TEE_BigIntFMM * dest,const TEE_BigIntFMM * op1,const TEE_BigIntFMM * op2,const TEE_BigInt * n,const TEE_BigIntFMMContext * context __unused)990062e3d01SJens Wiklander void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1,
991062e3d01SJens Wiklander const TEE_BigIntFMM *op2, const TEE_BigInt *n,
992062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused)
993062e3d01SJens Wiklander {
994062e3d01SJens Wiklander mbedtls_mpi mpi_dst;
995062e3d01SJens Wiklander mbedtls_mpi mpi_op1;
996062e3d01SJens Wiklander mbedtls_mpi mpi_op2;
997062e3d01SJens Wiklander mbedtls_mpi mpi_n;
998062e3d01SJens Wiklander mbedtls_mpi mpi_t;
999062e3d01SJens Wiklander
1000062e3d01SJens Wiklander get_mpi(&mpi_dst, dest);
10017696ab7fSJens Wiklander get_mpi(&mpi_op1, op1);
10027696ab7fSJens Wiklander get_mpi(&mpi_op2, op2);
10037696ab7fSJens Wiklander get_mpi(&mpi_n, n);
1004062e3d01SJens Wiklander get_mpi(&mpi_t, NULL);
1005062e3d01SJens Wiklander
1006062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mul_mpi(&mpi_t, &mpi_op1, &mpi_op2));
1007062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dst, &mpi_t, &mpi_n));
1008062e3d01SJens Wiklander
10097696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_t);
10107696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_n);
10117696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2);
10127696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1);
10137696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest));
10147696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dst);
1015062e3d01SJens Wiklander }
1016