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