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 16062e3d01SJens Wiklander #define MPI_MEMPOOL_SIZE (8 * 1024) 17062e3d01SJens Wiklander 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 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 43062e3d01SJens Wiklander void _TEE_MathAPI_Init(void) 44062e3d01SJens Wiklander { 45062e3d01SJens Wiklander static uint8_t data[MPI_MEMPOOL_SIZE] 46062e3d01SJens Wiklander __aligned(__alignof__(mbedtls_mpi_uint)); 47062e3d01SJens Wiklander 48062e3d01SJens Wiklander mbedtls_mpi_mempool = mempool_alloc_pool(data, sizeof(data), NULL); 49062e3d01SJens Wiklander if (!mbedtls_mpi_mempool) 50062e3d01SJens Wiklander API_PANIC("Failed to initialize memory pool"); 51062e3d01SJens Wiklander } 52062e3d01SJens Wiklander 53062e3d01SJens Wiklander struct bigint_hdr { 54062e3d01SJens Wiklander int32_t sign; 55062e3d01SJens Wiklander uint16_t alloc_size; 56062e3d01SJens Wiklander uint16_t nblimbs; 57062e3d01SJens Wiklander }; 58062e3d01SJens Wiklander 59062e3d01SJens Wiklander #define BIGINT_HDR_SIZE_IN_U32 2 60062e3d01SJens Wiklander 61062e3d01SJens Wiklander static void init_static_mpi(mbedtls_mpi *mpi, TEE_BigInt *bigInt) 62062e3d01SJens Wiklander { 63062e3d01SJens Wiklander struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; 64062e3d01SJens Wiklander 65062e3d01SJens Wiklander mbedtls_mpi_init_static(mpi, (mbedtls_mpi_uint *)(hdr + 1), 66062e3d01SJens Wiklander hdr->sign, hdr->alloc_size, hdr->nblimbs); 67062e3d01SJens Wiklander } 68062e3d01SJens Wiklander 69062e3d01SJens Wiklander /* 70062e3d01SJens Wiklander * Initializes a MPI. 71062e3d01SJens Wiklander * 72062e3d01SJens Wiklander * If a bigint is supplied it's initialized with the value of the bigint 73062e3d01SJens Wiklander * and changes will be written back completely with a call to put_mpi(). 74062e3d01SJens Wiklander * The bigint dictates the size of the MPI which will be fixed to this 75062e3d01SJens Wiklander * size. 76062e3d01SJens Wiklander * 77062e3d01SJens Wiklander * If no bigint is supplied a temporary MPI is allocated instead which will 78062e3d01SJens Wiklander * be freed by put_mpi(). 79062e3d01SJens Wiklander */ 80062e3d01SJens Wiklander static void get_mpi(mbedtls_mpi *mpi, TEE_BigInt *bigInt) 81062e3d01SJens Wiklander { 82062e3d01SJens Wiklander /* 83062e3d01SJens Wiklander * The way the GP spec is defining the bignums it's 84062e3d01SJens Wiklander * difficult/tricky to do it using 64-bit arithmetics given that 85062e3d01SJens Wiklander * we'd need 64-bit alignment of the data as well. 86062e3d01SJens Wiklander */ 87062e3d01SJens Wiklander COMPILE_TIME_ASSERT(sizeof(mbedtls_mpi_uint) == sizeof(uint32_t)); 88062e3d01SJens Wiklander 89062e3d01SJens Wiklander /* 90062e3d01SJens Wiklander * The struct bigint_hdr is the overhead added to the bigint and 91062e3d01SJens Wiklander * is required to take exactly 2 uint32_t. 92062e3d01SJens Wiklander */ 93062e3d01SJens Wiklander COMPILE_TIME_ASSERT(sizeof(struct bigint_hdr) == 94062e3d01SJens Wiklander sizeof(uint32_t) * BIGINT_HDR_SIZE_IN_U32); 95062e3d01SJens Wiklander 96062e3d01SJens Wiklander if (bigInt) 97062e3d01SJens Wiklander init_static_mpi(mpi, bigInt); 98062e3d01SJens Wiklander else 99062e3d01SJens Wiklander mbedtls_mpi_init_mempool(mpi); 100062e3d01SJens Wiklander } 101062e3d01SJens Wiklander 102062e3d01SJens Wiklander /* 103062e3d01SJens Wiklander * Initializes a MPI from a constant bigint. 104062e3d01SJens Wiklander * 105062e3d01SJens Wiklander * A MPI is allocated and given an initial value based on the supplied 106062e3d01SJens Wiklander * bigint. When the MPI is freed with put_mpi() no changes are propagated 107062e3d01SJens Wiklander * back. 108062e3d01SJens Wiklander */ 109062e3d01SJens Wiklander static void get_const_mpi(mbedtls_mpi *mpi, const TEE_BigInt *bigInt) 110062e3d01SJens Wiklander { 111062e3d01SJens Wiklander mbedtls_mpi mpi_const; 112062e3d01SJens Wiklander 113062e3d01SJens Wiklander init_static_mpi(&mpi_const, (TEE_BigInt *)bigInt); 114062e3d01SJens Wiklander get_mpi(mpi, NULL); 115062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(mpi, &mpi_const)); 116062e3d01SJens Wiklander } 117062e3d01SJens Wiklander 118062e3d01SJens Wiklander /* 119062e3d01SJens Wiklander * Uninitialize a MPI. 120062e3d01SJens Wiklander * 121062e3d01SJens Wiklander * If the MPI is linked to a bigint the final changes (size and sign) will 122062e3d01SJens Wiklander * be copied back. 123062e3d01SJens Wiklander * 124062e3d01SJens Wiklander * If the MPI isn't linked to bigint it's only freed. 125062e3d01SJens Wiklander */ 126062e3d01SJens Wiklander static void put_mpi(mbedtls_mpi *mpi) 127062e3d01SJens Wiklander { 128062e3d01SJens Wiklander if (mpi->alloc_type == MBEDTLS_MPI_ALLOC_TYPE_STATIC) { 129062e3d01SJens Wiklander struct bigint_hdr *hdr = ((struct bigint_hdr *)mpi->p) - 1; 130062e3d01SJens Wiklander 131062e3d01SJens Wiklander hdr->sign = mpi->s; 132062e3d01SJens Wiklander hdr->nblimbs = mpi->n; 133062e3d01SJens Wiklander } else { 134062e3d01SJens Wiklander mbedtls_mpi_free(mpi); 135062e3d01SJens Wiklander } 136062e3d01SJens Wiklander } 137062e3d01SJens Wiklander 138062e3d01SJens Wiklander void TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len) 139062e3d01SJens Wiklander { 140062e3d01SJens Wiklander memset(bigInt, 0, TEE_BigIntSizeInU32(len) * sizeof(uint32_t)); 141062e3d01SJens Wiklander 142062e3d01SJens Wiklander struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; 143062e3d01SJens Wiklander 144062e3d01SJens Wiklander 145062e3d01SJens Wiklander hdr->sign = 1; 146062e3d01SJens Wiklander if ((len - BIGINT_HDR_SIZE_IN_U32) > MBEDTLS_MPI_MAX_LIMBS) 147062e3d01SJens Wiklander API_PANIC("Too large bigint"); 148062e3d01SJens Wiklander hdr->alloc_size = len - BIGINT_HDR_SIZE_IN_U32; 149062e3d01SJens Wiklander } 150062e3d01SJens Wiklander 151062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, 152062e3d01SJens Wiklander const uint8_t *buffer, 153062e3d01SJens Wiklander uint32_t bufferLen, int32_t sign) 154062e3d01SJens Wiklander { 155062e3d01SJens Wiklander TEE_Result res; 156062e3d01SJens Wiklander mbedtls_mpi mpi_dest; 157062e3d01SJens Wiklander 158062e3d01SJens Wiklander get_mpi(&mpi_dest, dest); 159062e3d01SJens Wiklander 160062e3d01SJens Wiklander if (mbedtls_mpi_read_binary(&mpi_dest, buffer, bufferLen)) 161062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW; 162062e3d01SJens Wiklander else 163062e3d01SJens Wiklander res = TEE_SUCCESS; 164062e3d01SJens Wiklander 165062e3d01SJens Wiklander if (sign < 0) 166062e3d01SJens Wiklander mpi_dest.s = -1; 167062e3d01SJens Wiklander 168062e3d01SJens Wiklander put_mpi(&mpi_dest); 169062e3d01SJens Wiklander 170062e3d01SJens Wiklander return res; 171062e3d01SJens Wiklander } 172062e3d01SJens Wiklander 173062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, uint32_t *bufferLen, 174062e3d01SJens Wiklander const TEE_BigInt *bigInt) 175062e3d01SJens Wiklander { 176062e3d01SJens Wiklander TEE_Result res = TEE_SUCCESS; 177062e3d01SJens Wiklander mbedtls_mpi mpi; 178062e3d01SJens Wiklander size_t sz; 179062e3d01SJens Wiklander 180062e3d01SJens Wiklander get_const_mpi(&mpi, bigInt); 181062e3d01SJens Wiklander 182062e3d01SJens Wiklander sz = mbedtls_mpi_size(&mpi); 183062e3d01SJens Wiklander if (sz <= *bufferLen) 184062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_write_binary(&mpi, buffer, sz)); 185062e3d01SJens Wiklander else 186062e3d01SJens Wiklander res = TEE_ERROR_SHORT_BUFFER; 187062e3d01SJens Wiklander 188062e3d01SJens Wiklander *bufferLen = sz; 189062e3d01SJens Wiklander 190062e3d01SJens Wiklander put_mpi(&mpi); 191062e3d01SJens Wiklander 192062e3d01SJens Wiklander return res; 193062e3d01SJens Wiklander } 194062e3d01SJens Wiklander 195062e3d01SJens Wiklander void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal) 196062e3d01SJens Wiklander { 197062e3d01SJens Wiklander mbedtls_mpi mpi; 198062e3d01SJens Wiklander 199062e3d01SJens Wiklander get_mpi(&mpi, dest); 200062e3d01SJens Wiklander 201062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi, shortVal)); 202062e3d01SJens Wiklander 203062e3d01SJens Wiklander put_mpi(&mpi); 204062e3d01SJens Wiklander } 205062e3d01SJens Wiklander 206062e3d01SJens Wiklander TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src) 207062e3d01SJens Wiklander { 208062e3d01SJens Wiklander TEE_Result res = TEE_SUCCESS; 209062e3d01SJens Wiklander mbedtls_mpi mpi; 210062e3d01SJens Wiklander uint32_t v; 211062e3d01SJens Wiklander 212062e3d01SJens Wiklander get_const_mpi(&mpi, src); 213062e3d01SJens Wiklander 214062e3d01SJens Wiklander if (mbedtls_mpi_write_binary(&mpi, (void *)&v, sizeof(v))) { 215062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW; 216062e3d01SJens Wiklander goto out; 217062e3d01SJens Wiklander } 218062e3d01SJens Wiklander 219062e3d01SJens Wiklander if (mpi.s > 0) { 220062e3d01SJens Wiklander if (ADD_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) 221062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW; 222062e3d01SJens Wiklander } else { 223062e3d01SJens Wiklander if (SUB_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) 224062e3d01SJens Wiklander res = TEE_ERROR_OVERFLOW; 225062e3d01SJens Wiklander } 226062e3d01SJens Wiklander 227062e3d01SJens Wiklander out: 228062e3d01SJens Wiklander put_mpi(&mpi); 229062e3d01SJens Wiklander 230062e3d01SJens Wiklander return res; 231062e3d01SJens Wiklander } 232062e3d01SJens Wiklander 233062e3d01SJens Wiklander int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2) 234062e3d01SJens Wiklander { 235062e3d01SJens Wiklander mbedtls_mpi mpi1; 236062e3d01SJens Wiklander mbedtls_mpi mpi2; 237062e3d01SJens Wiklander int32_t rc; 238062e3d01SJens Wiklander 239062e3d01SJens Wiklander get_const_mpi(&mpi1, op1); 240062e3d01SJens Wiklander get_const_mpi(&mpi2, op2); 241062e3d01SJens Wiklander 242062e3d01SJens Wiklander rc = mbedtls_mpi_cmp_mpi(&mpi1, &mpi2); 243062e3d01SJens Wiklander 244062e3d01SJens Wiklander put_mpi(&mpi1); 245062e3d01SJens Wiklander put_mpi(&mpi2); 246062e3d01SJens Wiklander 247062e3d01SJens Wiklander return rc; 248062e3d01SJens Wiklander } 249062e3d01SJens Wiklander 250062e3d01SJens Wiklander int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal) 251062e3d01SJens Wiklander { 252062e3d01SJens Wiklander mbedtls_mpi mpi; 253062e3d01SJens Wiklander int32_t rc; 254062e3d01SJens Wiklander 255062e3d01SJens Wiklander get_const_mpi(&mpi, op); 256062e3d01SJens Wiklander 257062e3d01SJens Wiklander rc = mbedtls_mpi_cmp_int(&mpi, shortVal); 258062e3d01SJens Wiklander 259062e3d01SJens Wiklander put_mpi(&mpi); 260062e3d01SJens Wiklander 261062e3d01SJens Wiklander return rc; 262062e3d01SJens Wiklander } 263062e3d01SJens Wiklander 264062e3d01SJens Wiklander void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits) 265062e3d01SJens Wiklander { 266062e3d01SJens Wiklander mbedtls_mpi mpi_dest; 267062e3d01SJens Wiklander mbedtls_mpi mpi_op; 268062e3d01SJens Wiklander 269062e3d01SJens Wiklander get_mpi(&mpi_dest, dest); 270062e3d01SJens Wiklander 271062e3d01SJens Wiklander if (dest == op) { 272062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); 273062e3d01SJens Wiklander goto out; 274062e3d01SJens Wiklander } 275062e3d01SJens Wiklander 276062e3d01SJens Wiklander get_const_mpi(&mpi_op, op); 277062e3d01SJens Wiklander 278062e3d01SJens Wiklander if (mbedtls_mpi_size(&mpi_dest) >= mbedtls_mpi_size(&mpi_op)) { 279062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_op)); 280062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); 281062e3d01SJens Wiklander } else { 282062e3d01SJens Wiklander mbedtls_mpi mpi_t; 283062e3d01SJens Wiklander 284062e3d01SJens Wiklander get_mpi(&mpi_t, NULL); 285062e3d01SJens Wiklander 286062e3d01SJens Wiklander /* 287062e3d01SJens Wiklander * We're using a temporary buffer to avoid the corner case 288062e3d01SJens Wiklander * where destination is unexpectedly overflowed by up to 289062e3d01SJens Wiklander * @bits number of bits. 290062e3d01SJens Wiklander */ 291062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_t, &mpi_op)); 292062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&mpi_t, bits)); 293062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_t)); 294062e3d01SJens Wiklander 295062e3d01SJens Wiklander put_mpi(&mpi_t); 296062e3d01SJens Wiklander } 297062e3d01SJens Wiklander 298062e3d01SJens Wiklander put_mpi(&mpi_op); 299062e3d01SJens Wiklander 300062e3d01SJens Wiklander out: 301062e3d01SJens Wiklander put_mpi(&mpi_dest); 302062e3d01SJens Wiklander } 303062e3d01SJens Wiklander 304062e3d01SJens Wiklander bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex) 305062e3d01SJens Wiklander { 306062e3d01SJens Wiklander bool rc; 307062e3d01SJens Wiklander mbedtls_mpi mpi; 308062e3d01SJens Wiklander 309062e3d01SJens Wiklander get_const_mpi(&mpi, src); 310062e3d01SJens Wiklander 311062e3d01SJens Wiklander rc = mbedtls_mpi_get_bit(&mpi, bitIndex); 312062e3d01SJens Wiklander 313062e3d01SJens Wiklander put_mpi(&mpi); 314062e3d01SJens Wiklander 315062e3d01SJens Wiklander return rc; 316062e3d01SJens Wiklander } 317062e3d01SJens Wiklander 318062e3d01SJens Wiklander uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src) 319062e3d01SJens Wiklander { 320062e3d01SJens Wiklander uint32_t rc; 321062e3d01SJens Wiklander mbedtls_mpi mpi; 322062e3d01SJens Wiklander 323062e3d01SJens Wiklander get_const_mpi(&mpi, src); 324062e3d01SJens Wiklander 325062e3d01SJens Wiklander rc = mbedtls_mpi_bitlen(&mpi); 326062e3d01SJens Wiklander 327062e3d01SJens Wiklander put_mpi(&mpi); 328062e3d01SJens Wiklander 329062e3d01SJens Wiklander return rc; 330062e3d01SJens Wiklander } 331062e3d01SJens Wiklander 332062e3d01SJens Wiklander static void bigint_binary(TEE_BigInt *dest, const TEE_BigInt *op1, 333062e3d01SJens Wiklander const TEE_BigInt *op2, 334062e3d01SJens Wiklander int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, 335062e3d01SJens Wiklander const mbedtls_mpi *B)) 336062e3d01SJens Wiklander { 337062e3d01SJens Wiklander mbedtls_mpi mpi_dest; 338062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 339062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 340062e3d01SJens Wiklander mbedtls_mpi *pop1 = &mpi_op1; 341062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2; 342062e3d01SJens Wiklander 343062e3d01SJens Wiklander get_mpi(&mpi_dest, dest); 344062e3d01SJens Wiklander 345062e3d01SJens Wiklander if (op1 == dest) 346062e3d01SJens Wiklander pop1 = &mpi_dest; 347062e3d01SJens Wiklander else 348062e3d01SJens Wiklander get_const_mpi(&mpi_op1, op1); 349062e3d01SJens Wiklander 350062e3d01SJens Wiklander if (op2 == dest) 351062e3d01SJens Wiklander pop2 = &mpi_dest; 352062e3d01SJens Wiklander else if (op2 == op1) 353062e3d01SJens Wiklander pop2 = pop1; 354062e3d01SJens Wiklander else 355062e3d01SJens Wiklander get_const_mpi(&mpi_op2, op2); 356062e3d01SJens Wiklander 357062e3d01SJens Wiklander MPI_CHECK(func(&mpi_dest, pop1, pop2)); 358062e3d01SJens Wiklander 359062e3d01SJens Wiklander put_mpi(&mpi_dest); 360062e3d01SJens Wiklander if (pop1 == &mpi_op1) 361062e3d01SJens Wiklander put_mpi(&mpi_op1); 362062e3d01SJens Wiklander if (pop2 == &mpi_op2) 363062e3d01SJens Wiklander put_mpi(&mpi_op2); 364062e3d01SJens Wiklander } 365062e3d01SJens Wiklander 366062e3d01SJens Wiklander static void bigint_binary_mod(TEE_BigInt *dest, const TEE_BigInt *op1, 367062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n, 368062e3d01SJens Wiklander int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, 369062e3d01SJens Wiklander const mbedtls_mpi *B)) 370062e3d01SJens Wiklander { 371062e3d01SJens Wiklander if (TEE_BigIntCmpS32(n, 2) < 0) 372062e3d01SJens Wiklander API_PANIC("Modulus is too short"); 373062e3d01SJens Wiklander 374062e3d01SJens Wiklander mbedtls_mpi mpi_dest; 375062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 376062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 377062e3d01SJens Wiklander mbedtls_mpi mpi_n; 378062e3d01SJens Wiklander mbedtls_mpi *pop1 = &mpi_op1; 379062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2; 380062e3d01SJens Wiklander mbedtls_mpi mpi_t; 381062e3d01SJens Wiklander 382062e3d01SJens Wiklander get_mpi(&mpi_dest, dest); 383062e3d01SJens Wiklander get_const_mpi(&mpi_n, n); 384062e3d01SJens Wiklander 385062e3d01SJens Wiklander if (op1 == dest) 386062e3d01SJens Wiklander pop1 = &mpi_dest; 387062e3d01SJens Wiklander else 388062e3d01SJens Wiklander get_const_mpi(&mpi_op1, op1); 389062e3d01SJens Wiklander 390062e3d01SJens Wiklander if (op2 == dest) 391062e3d01SJens Wiklander pop2 = &mpi_dest; 392062e3d01SJens Wiklander else if (op2 == op1) 393062e3d01SJens Wiklander pop2 = pop1; 394062e3d01SJens Wiklander else 395062e3d01SJens Wiklander get_const_mpi(&mpi_op2, op2); 396062e3d01SJens Wiklander 397062e3d01SJens Wiklander get_mpi(&mpi_t, NULL); 398062e3d01SJens Wiklander 399062e3d01SJens Wiklander MPI_CHECK(func(&mpi_t, pop1, pop2)); 400062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dest, &mpi_t, &mpi_n)); 401062e3d01SJens Wiklander 402062e3d01SJens Wiklander put_mpi(&mpi_dest); 403062e3d01SJens Wiklander if (pop1 == &mpi_op1) 404062e3d01SJens Wiklander put_mpi(&mpi_op1); 405062e3d01SJens Wiklander if (pop2 == &mpi_op2) 406062e3d01SJens Wiklander put_mpi(&mpi_op2); 407062e3d01SJens Wiklander put_mpi(&mpi_t); 408062e3d01SJens Wiklander } 409062e3d01SJens Wiklander 410062e3d01SJens Wiklander void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, 411062e3d01SJens Wiklander const TEE_BigInt *op2) 412062e3d01SJens Wiklander { 413062e3d01SJens Wiklander bigint_binary(dest, op1, op2, mbedtls_mpi_add_mpi); 414062e3d01SJens Wiklander } 415062e3d01SJens Wiklander 416062e3d01SJens Wiklander void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, 417062e3d01SJens Wiklander const TEE_BigInt *op2) 418062e3d01SJens Wiklander { 419062e3d01SJens Wiklander bigint_binary(dest, op1, op2, mbedtls_mpi_sub_mpi); 420062e3d01SJens Wiklander } 421062e3d01SJens Wiklander 422062e3d01SJens Wiklander void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src) 423062e3d01SJens Wiklander { 424062e3d01SJens Wiklander mbedtls_mpi mpi_dest; 425062e3d01SJens Wiklander 426062e3d01SJens Wiklander get_mpi(&mpi_dest, dest); 427062e3d01SJens Wiklander 428062e3d01SJens Wiklander if (dest != src) { 429062e3d01SJens Wiklander mbedtls_mpi mpi_src; 430062e3d01SJens Wiklander 431062e3d01SJens Wiklander get_const_mpi(&mpi_src, src); 432062e3d01SJens Wiklander 433062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_src)); 434062e3d01SJens Wiklander 435062e3d01SJens Wiklander put_mpi(&mpi_src); 436062e3d01SJens Wiklander } 437062e3d01SJens Wiklander 438062e3d01SJens Wiklander mpi_dest.s *= -1; 439062e3d01SJens Wiklander 440062e3d01SJens Wiklander put_mpi(&mpi_dest); 441062e3d01SJens Wiklander } 442062e3d01SJens Wiklander 443062e3d01SJens Wiklander void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, 444062e3d01SJens Wiklander const TEE_BigInt *op2) 445062e3d01SJens Wiklander { 446*98efc118SJerome Forissier size_t bs1 = TEE_BigIntGetBitCount(op1); 447*98efc118SJerome Forissier size_t bs2 = TEE_BigIntGetBitCount(op2); 448*98efc118SJerome Forissier size_t s = TEE_BigIntSizeInU32(bs1) + TEE_BigIntSizeInU32(bs2); 449*98efc118SJerome Forissier TEE_BigInt zero[TEE_BigIntSizeInU32(1)] = { 0 }; 450*98efc118SJerome Forissier TEE_BigInt *tmp = NULL; 451*98efc118SJerome Forissier 452*98efc118SJerome Forissier tmp = mempool_alloc(mbedtls_mpi_mempool, sizeof(uint32_t) * s); 453*98efc118SJerome Forissier if (!tmp) 454*98efc118SJerome Forissier TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); 455*98efc118SJerome Forissier 456*98efc118SJerome Forissier TEE_BigIntInit(tmp, s); 457*98efc118SJerome Forissier TEE_BigIntInit(zero, TEE_BigIntSizeInU32(1)); 458*98efc118SJerome Forissier 459*98efc118SJerome Forissier bigint_binary(tmp, op1, op2, mbedtls_mpi_mul_mpi); 460*98efc118SJerome Forissier 461*98efc118SJerome Forissier TEE_BigIntAdd(dest, tmp, zero); 462*98efc118SJerome Forissier 463*98efc118SJerome Forissier mempool_free(mbedtls_mpi_mempool, tmp); 464062e3d01SJens Wiklander } 465062e3d01SJens Wiklander 466062e3d01SJens Wiklander void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op) 467062e3d01SJens Wiklander { 468062e3d01SJens Wiklander TEE_BigIntMul(dest, op, op); 469062e3d01SJens Wiklander } 470062e3d01SJens Wiklander 471062e3d01SJens Wiklander void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, 472062e3d01SJens Wiklander const TEE_BigInt *op1, const TEE_BigInt *op2) 473062e3d01SJens Wiklander { 474062e3d01SJens Wiklander mbedtls_mpi mpi_dest_q; 475062e3d01SJens Wiklander mbedtls_mpi mpi_dest_r; 476062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 477062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 478062e3d01SJens Wiklander mbedtls_mpi *pop1 = &mpi_op1; 479062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2; 480062e3d01SJens Wiklander 481062e3d01SJens Wiklander get_mpi(&mpi_dest_q, dest_q); 482062e3d01SJens Wiklander get_mpi(&mpi_dest_r, dest_r); 483062e3d01SJens Wiklander 484062e3d01SJens Wiklander if (op1 == dest_q) 485062e3d01SJens Wiklander pop1 = &mpi_dest_q; 486062e3d01SJens Wiklander else if (op1 == dest_r) 487062e3d01SJens Wiklander pop1 = &mpi_dest_r; 488062e3d01SJens Wiklander else 489062e3d01SJens Wiklander get_const_mpi(&mpi_op1, op1); 490062e3d01SJens Wiklander 491062e3d01SJens Wiklander if (op2 == dest_q) 492062e3d01SJens Wiklander pop2 = &mpi_dest_q; 493062e3d01SJens Wiklander else if (op2 == dest_r) 494062e3d01SJens Wiklander pop2 = &mpi_dest_r; 495062e3d01SJens Wiklander else if (op2 == op1) 496062e3d01SJens Wiklander pop2 = pop1; 497062e3d01SJens Wiklander else 498062e3d01SJens Wiklander get_const_mpi(&mpi_op2, op2); 499062e3d01SJens Wiklander 500062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_div_mpi(&mpi_dest_q, &mpi_dest_r, pop1, pop2)); 501062e3d01SJens Wiklander 502062e3d01SJens Wiklander put_mpi(&mpi_dest_q); 503062e3d01SJens Wiklander put_mpi(&mpi_dest_r); 504062e3d01SJens Wiklander if (pop1 == &mpi_op1) 505062e3d01SJens Wiklander put_mpi(&mpi_op1); 506062e3d01SJens Wiklander if (pop2 == &mpi_op2) 507062e3d01SJens Wiklander put_mpi(&mpi_op2); 508062e3d01SJens Wiklander } 509062e3d01SJens Wiklander 510062e3d01SJens Wiklander void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n) 511062e3d01SJens Wiklander { 512062e3d01SJens Wiklander if (TEE_BigIntCmpS32(n, 2) < 0) 513062e3d01SJens Wiklander API_PANIC("Modulus is too short"); 514062e3d01SJens Wiklander 515062e3d01SJens Wiklander bigint_binary(dest, op, n, mbedtls_mpi_mod_mpi); 516062e3d01SJens Wiklander } 517062e3d01SJens Wiklander 518062e3d01SJens Wiklander void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, 519062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n) 520062e3d01SJens Wiklander { 521062e3d01SJens Wiklander bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_add_mpi); 522062e3d01SJens Wiklander } 523062e3d01SJens Wiklander 524062e3d01SJens Wiklander void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, 525062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n) 526062e3d01SJens Wiklander { 527062e3d01SJens Wiklander bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_sub_mpi); 528062e3d01SJens Wiklander } 529062e3d01SJens Wiklander 530062e3d01SJens Wiklander void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, 531062e3d01SJens Wiklander const TEE_BigInt *op2, const TEE_BigInt *n) 532062e3d01SJens Wiklander { 533062e3d01SJens Wiklander bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_mul_mpi); 534062e3d01SJens Wiklander } 535062e3d01SJens Wiklander 536062e3d01SJens Wiklander void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, 537062e3d01SJens Wiklander const TEE_BigInt *n) 538062e3d01SJens Wiklander { 539062e3d01SJens Wiklander TEE_BigIntMulMod(dest, op, op, n); 540062e3d01SJens Wiklander } 541062e3d01SJens Wiklander 542062e3d01SJens Wiklander void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, 543062e3d01SJens Wiklander const TEE_BigInt *n) 544062e3d01SJens Wiklander { 545062e3d01SJens Wiklander if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0) 546062e3d01SJens Wiklander API_PANIC("too small modulus or trying to invert zero"); 547062e3d01SJens Wiklander 548062e3d01SJens Wiklander mbedtls_mpi mpi_dest; 549062e3d01SJens Wiklander mbedtls_mpi mpi_op; 550062e3d01SJens Wiklander mbedtls_mpi mpi_n; 551062e3d01SJens Wiklander mbedtls_mpi *pop = &mpi_op; 552062e3d01SJens Wiklander 553062e3d01SJens Wiklander get_mpi(&mpi_dest, dest); 554062e3d01SJens Wiklander get_const_mpi(&mpi_n, n); 555062e3d01SJens Wiklander 556062e3d01SJens Wiklander if (op == dest) 557062e3d01SJens Wiklander pop = &mpi_dest; 558062e3d01SJens Wiklander else 559062e3d01SJens Wiklander get_const_mpi(&mpi_op, op); 560062e3d01SJens Wiklander 561062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_inv_mod(&mpi_dest, pop, &mpi_n)); 562062e3d01SJens Wiklander 563062e3d01SJens Wiklander put_mpi(&mpi_dest); 564062e3d01SJens Wiklander put_mpi(&mpi_n); 565062e3d01SJens Wiklander if (pop == &mpi_op) 566062e3d01SJens Wiklander put_mpi(&mpi_op); 567062e3d01SJens Wiklander } 568062e3d01SJens Wiklander 569062e3d01SJens Wiklander bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2) 570062e3d01SJens Wiklander { 571062e3d01SJens Wiklander bool rc; 572062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 573062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 574062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2; 575062e3d01SJens Wiklander mbedtls_mpi gcd; 576062e3d01SJens Wiklander 577062e3d01SJens Wiklander get_const_mpi(&mpi_op1, op1); 578062e3d01SJens Wiklander 579062e3d01SJens Wiklander if (op2 == op1) 580062e3d01SJens Wiklander pop2 = &mpi_op1; 581062e3d01SJens Wiklander else 582062e3d01SJens Wiklander get_const_mpi(&mpi_op2, op2); 583062e3d01SJens Wiklander 584062e3d01SJens Wiklander get_mpi(&gcd, NULL); 585062e3d01SJens Wiklander 586062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_gcd(&gcd, &mpi_op1, &mpi_op2)); 587062e3d01SJens Wiklander 588062e3d01SJens Wiklander rc = !mbedtls_mpi_cmp_int(&gcd, 1); 589062e3d01SJens Wiklander 590062e3d01SJens Wiklander put_mpi(&gcd); 591062e3d01SJens Wiklander put_mpi(&mpi_op1); 592062e3d01SJens Wiklander if (pop2 == &mpi_op2) 593062e3d01SJens Wiklander put_mpi(&mpi_op2); 594062e3d01SJens Wiklander 595062e3d01SJens Wiklander return rc; 596062e3d01SJens Wiklander } 597062e3d01SJens Wiklander 598062e3d01SJens Wiklander static bool mpi_is_odd(mbedtls_mpi *x) 599062e3d01SJens Wiklander { 600062e3d01SJens Wiklander return mbedtls_mpi_get_bit(x, 0); 601062e3d01SJens Wiklander } 602062e3d01SJens Wiklander 603062e3d01SJens Wiklander static bool mpi_is_even(mbedtls_mpi *x) 604062e3d01SJens Wiklander { 605062e3d01SJens Wiklander return !mpi_is_odd(x); 606062e3d01SJens Wiklander } 607062e3d01SJens Wiklander 608062e3d01SJens Wiklander /* 609062e3d01SJens Wiklander * Based on libmpa implementation __mpa_egcd(), modified to work with MPI 610062e3d01SJens Wiklander * instead. 611062e3d01SJens Wiklander */ 612062e3d01SJens Wiklander static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b, 613062e3d01SJens Wiklander mbedtls_mpi *x_in, mbedtls_mpi *y_in) 614062e3d01SJens Wiklander { 615062e3d01SJens Wiklander mbedtls_mpi_uint k; 616062e3d01SJens Wiklander mbedtls_mpi A; 617062e3d01SJens Wiklander mbedtls_mpi B; 618062e3d01SJens Wiklander mbedtls_mpi C; 619062e3d01SJens Wiklander mbedtls_mpi D; 620062e3d01SJens Wiklander mbedtls_mpi x; 621062e3d01SJens Wiklander mbedtls_mpi y; 622062e3d01SJens Wiklander mbedtls_mpi u; 623062e3d01SJens Wiklander 624062e3d01SJens Wiklander get_mpi(&A, NULL); 625062e3d01SJens Wiklander get_mpi(&B, NULL); 626062e3d01SJens Wiklander get_mpi(&C, NULL); 627062e3d01SJens Wiklander get_mpi(&D, NULL); 628062e3d01SJens Wiklander get_mpi(&x, NULL); 629062e3d01SJens Wiklander get_mpi(&y, NULL); 630062e3d01SJens Wiklander get_mpi(&u, NULL); 631062e3d01SJens Wiklander 632062e3d01SJens Wiklander /* have y < x from assumption */ 633062e3d01SJens Wiklander if (!mbedtls_mpi_cmp_int(y_in, 0)) { 634062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(a, 1)); 635062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(b, 0)); 636062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(gcd, x_in)); 637062e3d01SJens Wiklander goto out; 638062e3d01SJens Wiklander } 639062e3d01SJens Wiklander 640062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&x, x_in)); 641062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&y, y_in)); 642062e3d01SJens Wiklander 643062e3d01SJens Wiklander k = 0; 644062e3d01SJens Wiklander while (mpi_is_even(&x) && mpi_is_even(&y)) { 645062e3d01SJens Wiklander k++; 646062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&x, 1)); 647062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&y, 1)); 648062e3d01SJens Wiklander } 649062e3d01SJens Wiklander 650062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&u, &x)); 651062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(gcd, &y)); 652062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&A, 1)); 653062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&B, 0)); 654062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&C, 0)); 655062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&D, 1)); 656062e3d01SJens Wiklander 657062e3d01SJens Wiklander while (mbedtls_mpi_cmp_int(&u, 0)) { 658062e3d01SJens Wiklander while (mpi_is_even(&u)) { 659062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&u, 1)); 660062e3d01SJens Wiklander if (mpi_is_odd(&A) || mpi_is_odd(&B)) { 661062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_add_mpi(&A, &A, &y)); 662062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &x)); 663062e3d01SJens Wiklander } 664062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&A, 1)); 665062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&B, 1)); 666062e3d01SJens Wiklander } 667062e3d01SJens Wiklander 668062e3d01SJens Wiklander while (mpi_is_even(gcd)) { 669062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(gcd, 1)); 670062e3d01SJens Wiklander if (mpi_is_odd(&C) || mpi_is_odd(&D)) { 671062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_add_mpi(&C, &C, &y)); 672062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &x)); 673062e3d01SJens Wiklander } 674062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&C, 1)); 675062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&D, 1)); 676062e3d01SJens Wiklander 677062e3d01SJens Wiklander } 678062e3d01SJens Wiklander 679062e3d01SJens Wiklander if (mbedtls_mpi_cmp_mpi(&u, gcd) >= 0) { 680062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&u, &u, gcd)); 681062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&A, &A, &C)); 682062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &D)); 683062e3d01SJens Wiklander } else { 684062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(gcd, gcd, &u)); 685062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&C, &C, &A)); 686062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &B)); 687062e3d01SJens Wiklander } 688062e3d01SJens Wiklander } 689062e3d01SJens Wiklander 690062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(a, &C)); 691062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(b, &D)); 692062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_l(gcd, k)); 693062e3d01SJens Wiklander 694062e3d01SJens Wiklander out: 695062e3d01SJens Wiklander put_mpi(&A); 696062e3d01SJens Wiklander put_mpi(&B); 697062e3d01SJens Wiklander put_mpi(&C); 698062e3d01SJens Wiklander put_mpi(&D); 699062e3d01SJens Wiklander put_mpi(&x); 700062e3d01SJens Wiklander put_mpi(&y); 701062e3d01SJens Wiklander put_mpi(&u); 702062e3d01SJens Wiklander } 703062e3d01SJens Wiklander 704062e3d01SJens Wiklander void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, 705062e3d01SJens Wiklander TEE_BigInt *v, const TEE_BigInt *op1, 706062e3d01SJens Wiklander const TEE_BigInt *op2) 707062e3d01SJens Wiklander { 708062e3d01SJens Wiklander mbedtls_mpi mpi_gcd_res; 709062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 710062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 711062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2; 712062e3d01SJens Wiklander 713062e3d01SJens Wiklander get_mpi(&mpi_gcd_res, gcd); 714062e3d01SJens Wiklander get_const_mpi(&mpi_op1, op1); 715062e3d01SJens Wiklander 716062e3d01SJens Wiklander if (op2 == op1) 717062e3d01SJens Wiklander pop2 = &mpi_op1; 718062e3d01SJens Wiklander else 719062e3d01SJens Wiklander get_const_mpi(&mpi_op2, op2); 720062e3d01SJens Wiklander 721062e3d01SJens Wiklander if (!u && !v) { 722062e3d01SJens Wiklander if (gcd) 723062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_gcd(&mpi_gcd_res, &mpi_op1, 724062e3d01SJens Wiklander pop2)); 725062e3d01SJens Wiklander } else { 726062e3d01SJens Wiklander mbedtls_mpi mpi_u; 727062e3d01SJens Wiklander mbedtls_mpi mpi_v; 728062e3d01SJens Wiklander int8_t s1 = mpi_op1.s; 729062e3d01SJens Wiklander int8_t s2 = pop2->s; 730062e3d01SJens Wiklander int cmp; 731062e3d01SJens Wiklander 732062e3d01SJens Wiklander mpi_op1.s = 1; 733062e3d01SJens Wiklander pop2->s = 1; 734062e3d01SJens Wiklander 735062e3d01SJens Wiklander get_mpi(&mpi_u, u); 736062e3d01SJens Wiklander get_mpi(&mpi_v, v); 737062e3d01SJens Wiklander 738062e3d01SJens Wiklander cmp = mbedtls_mpi_cmp_abs(&mpi_op1, pop2); 739062e3d01SJens Wiklander if (cmp == 0) { 740062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_gcd_res, &mpi_op1)); 741062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi_u, 1)); 742062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi_v, 0)); 743062e3d01SJens Wiklander } else if (cmp > 0) { 744062e3d01SJens Wiklander mpi_egcd(&mpi_gcd_res, &mpi_u, &mpi_v, &mpi_op1, pop2); 745062e3d01SJens Wiklander } else { 746062e3d01SJens Wiklander mpi_egcd(&mpi_gcd_res, &mpi_v, &mpi_u, pop2, &mpi_op1); 747062e3d01SJens Wiklander } 748062e3d01SJens Wiklander 749062e3d01SJens Wiklander mpi_u.s *= s1; 750062e3d01SJens Wiklander mpi_v.s *= s2; 751062e3d01SJens Wiklander 752062e3d01SJens Wiklander put_mpi(&mpi_u); 753062e3d01SJens Wiklander put_mpi(&mpi_v); 754062e3d01SJens Wiklander } 755062e3d01SJens Wiklander 756062e3d01SJens Wiklander put_mpi(&mpi_gcd_res); 757062e3d01SJens Wiklander put_mpi(&mpi_op1); 758062e3d01SJens Wiklander if (pop2 == &mpi_op2) 759062e3d01SJens Wiklander put_mpi(&mpi_op2); 760062e3d01SJens Wiklander } 761062e3d01SJens Wiklander 762062e3d01SJens Wiklander static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen) 763062e3d01SJens Wiklander { 764062e3d01SJens Wiklander if (utee_cryp_random_number_generate(buf, blen)) 765062e3d01SJens Wiklander return MBEDTLS_ERR_MPI_FILE_IO_ERROR; 766062e3d01SJens Wiklander return 0; 767062e3d01SJens Wiklander } 768062e3d01SJens Wiklander 769062e3d01SJens Wiklander int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, 770062e3d01SJens Wiklander uint32_t confidenceLevel __unused) 771062e3d01SJens Wiklander { 772062e3d01SJens Wiklander int rc; 773062e3d01SJens Wiklander mbedtls_mpi mpi_op; 774062e3d01SJens Wiklander 775062e3d01SJens Wiklander get_const_mpi(&mpi_op, op); 776062e3d01SJens Wiklander 777062e3d01SJens Wiklander rc = mbedtls_mpi_is_prime(&mpi_op, rng_read, NULL); 778062e3d01SJens Wiklander 779062e3d01SJens Wiklander put_mpi(&mpi_op); 780062e3d01SJens Wiklander 781062e3d01SJens Wiklander if (rc) 782062e3d01SJens Wiklander return 0; 783062e3d01SJens Wiklander 784062e3d01SJens Wiklander return 1; 785062e3d01SJens Wiklander } 786062e3d01SJens Wiklander 787062e3d01SJens Wiklander /* 788062e3d01SJens Wiklander * Not so fast FMM implementation based on the normal big int functions. 789062e3d01SJens Wiklander * 790062e3d01SJens Wiklander * Note that these functions (along with all the other functions in this 791062e3d01SJens Wiklander * file) only are used directly by the TA doing bigint arithmetics on its 792062e3d01SJens Wiklander * own. Performance of RSA operations in TEE Internal API are not affected 793062e3d01SJens Wiklander * by this. 794062e3d01SJens Wiklander */ 795062e3d01SJens Wiklander void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len) 796062e3d01SJens Wiklander { 797062e3d01SJens Wiklander TEE_BigIntInit(bigIntFMM, len); 798062e3d01SJens Wiklander } 799062e3d01SJens Wiklander 800062e3d01SJens Wiklander void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context __unused, 801062e3d01SJens Wiklander uint32_t len __unused, 802062e3d01SJens Wiklander const TEE_BigInt *modulus __unused) 803062e3d01SJens Wiklander { 804062e3d01SJens Wiklander } 805062e3d01SJens Wiklander 806062e3d01SJens Wiklander uint32_t TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits) 807062e3d01SJens Wiklander { 808062e3d01SJens Wiklander return TEE_BigIntSizeInU32(modulusSizeInBits); 809062e3d01SJens Wiklander } 810062e3d01SJens Wiklander 811062e3d01SJens Wiklander uint32_t TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits __unused) 812062e3d01SJens Wiklander { 813062e3d01SJens Wiklander /* Return something larger than 0 to keep malloc() and friends happy */ 814062e3d01SJens Wiklander return 1; 815062e3d01SJens Wiklander } 816062e3d01SJens Wiklander 817062e3d01SJens Wiklander void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, 818062e3d01SJens Wiklander const TEE_BigInt *n, 819062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused) 820062e3d01SJens Wiklander { 821062e3d01SJens Wiklander TEE_BigIntMod(dest, src, n); 822062e3d01SJens Wiklander } 823062e3d01SJens Wiklander 824062e3d01SJens Wiklander void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, 825062e3d01SJens Wiklander const TEE_BigInt *n __unused, 826062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused) 827062e3d01SJens Wiklander { 828062e3d01SJens Wiklander mbedtls_mpi mpi_dst; 829062e3d01SJens Wiklander mbedtls_mpi mpi_src; 830062e3d01SJens Wiklander 831062e3d01SJens Wiklander get_mpi(&mpi_dst, dest); 832062e3d01SJens Wiklander get_const_mpi(&mpi_src, src); 833062e3d01SJens Wiklander 834062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dst, &mpi_src)); 835062e3d01SJens Wiklander 836062e3d01SJens Wiklander put_mpi(&mpi_dst); 837062e3d01SJens Wiklander put_mpi(&mpi_src); 838062e3d01SJens Wiklander } 839062e3d01SJens Wiklander 840062e3d01SJens Wiklander void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, 841062e3d01SJens Wiklander const TEE_BigIntFMM *op2, const TEE_BigInt *n, 842062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused) 843062e3d01SJens Wiklander { 844062e3d01SJens Wiklander mbedtls_mpi mpi_dst; 845062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 846062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 847062e3d01SJens Wiklander mbedtls_mpi mpi_n; 848062e3d01SJens Wiklander mbedtls_mpi mpi_t; 849062e3d01SJens Wiklander 850062e3d01SJens Wiklander get_mpi(&mpi_dst, dest); 851062e3d01SJens Wiklander get_const_mpi(&mpi_op1, op1); 852062e3d01SJens Wiklander get_const_mpi(&mpi_op2, op2); 853062e3d01SJens Wiklander get_const_mpi(&mpi_n, n); 854062e3d01SJens Wiklander get_mpi(&mpi_t, NULL); 855062e3d01SJens Wiklander 856062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mul_mpi(&mpi_t, &mpi_op1, &mpi_op2)); 857062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dst, &mpi_t, &mpi_n)); 858062e3d01SJens Wiklander 859062e3d01SJens Wiklander put_mpi(&mpi_t); 860062e3d01SJens Wiklander put_mpi(&mpi_n); 861062e3d01SJens Wiklander put_mpi(&mpi_op2); 862062e3d01SJens Wiklander put_mpi(&mpi_op1); 863062e3d01SJens Wiklander put_mpi(&mpi_dst); 864062e3d01SJens Wiklander } 865