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 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 { 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 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 */ 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 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 134fe03ed8bSJens Wiklander void __GP11_TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len) 135fe03ed8bSJens Wiklander { 136fe03ed8bSJens Wiklander TEE_BigIntInit(bigInt, len); 137fe03ed8bSJens Wiklander } 138fe03ed8bSJens Wiklander 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 678062e3d01SJens Wiklander static bool mpi_is_even(mbedtls_mpi *x) 679062e3d01SJens Wiklander { 680062e3d01SJens Wiklander return !mpi_is_odd(x); 681062e3d01SJens Wiklander } 682062e3d01SJens Wiklander 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 729062e3d01SJens Wiklander /* 730062e3d01SJens Wiklander * Based on libmpa implementation __mpa_egcd(), modified to work with MPI 731062e3d01SJens Wiklander * instead. 732062e3d01SJens Wiklander */ 733062e3d01SJens Wiklander static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b, 734062e3d01SJens Wiklander mbedtls_mpi *x_in, mbedtls_mpi *y_in) 735062e3d01SJens Wiklander { 736062e3d01SJens Wiklander mbedtls_mpi_uint k; 737062e3d01SJens Wiklander mbedtls_mpi A; 738062e3d01SJens Wiklander mbedtls_mpi B; 739062e3d01SJens Wiklander mbedtls_mpi C; 740062e3d01SJens Wiklander mbedtls_mpi D; 741062e3d01SJens Wiklander mbedtls_mpi x; 742062e3d01SJens Wiklander mbedtls_mpi y; 743062e3d01SJens Wiklander mbedtls_mpi u; 744062e3d01SJens Wiklander 745062e3d01SJens Wiklander get_mpi(&A, NULL); 746062e3d01SJens Wiklander get_mpi(&B, NULL); 747062e3d01SJens Wiklander get_mpi(&C, NULL); 748062e3d01SJens Wiklander get_mpi(&D, NULL); 749062e3d01SJens Wiklander get_mpi(&x, NULL); 750062e3d01SJens Wiklander get_mpi(&y, NULL); 751062e3d01SJens Wiklander get_mpi(&u, NULL); 752062e3d01SJens Wiklander 753062e3d01SJens Wiklander /* have y < x from assumption */ 754062e3d01SJens Wiklander if (!mbedtls_mpi_cmp_int(y_in, 0)) { 755062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(a, 1)); 756062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(b, 0)); 757062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(gcd, x_in)); 758062e3d01SJens Wiklander goto out; 759062e3d01SJens Wiklander } 760062e3d01SJens Wiklander 761062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&x, x_in)); 762062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&y, y_in)); 763062e3d01SJens Wiklander 764062e3d01SJens Wiklander k = 0; 765062e3d01SJens Wiklander while (mpi_is_even(&x) && mpi_is_even(&y)) { 766062e3d01SJens Wiklander k++; 767062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&x, 1)); 768062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&y, 1)); 769062e3d01SJens Wiklander } 770062e3d01SJens Wiklander 771062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&u, &x)); 772062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(gcd, &y)); 773062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&A, 1)); 774062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&B, 0)); 775062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&C, 0)); 776062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&D, 1)); 777062e3d01SJens Wiklander 778062e3d01SJens Wiklander while (mbedtls_mpi_cmp_int(&u, 0)) { 779062e3d01SJens Wiklander while (mpi_is_even(&u)) { 780062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&u, 1)); 781062e3d01SJens Wiklander if (mpi_is_odd(&A) || mpi_is_odd(&B)) { 782062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_add_mpi(&A, &A, &y)); 783062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &x)); 784062e3d01SJens Wiklander } 785062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&A, 1)); 786062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&B, 1)); 787062e3d01SJens Wiklander } 788062e3d01SJens Wiklander 789062e3d01SJens Wiklander while (mpi_is_even(gcd)) { 790062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(gcd, 1)); 791062e3d01SJens Wiklander if (mpi_is_odd(&C) || mpi_is_odd(&D)) { 792062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_add_mpi(&C, &C, &y)); 793062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &x)); 794062e3d01SJens Wiklander } 795062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&C, 1)); 796062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_r(&D, 1)); 797062e3d01SJens Wiklander 798062e3d01SJens Wiklander } 799062e3d01SJens Wiklander 800062e3d01SJens Wiklander if (mbedtls_mpi_cmp_mpi(&u, gcd) >= 0) { 801062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&u, &u, gcd)); 802062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&A, &A, &C)); 803062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &D)); 804062e3d01SJens Wiklander } else { 805062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(gcd, gcd, &u)); 806062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&C, &C, &A)); 807062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &B)); 808062e3d01SJens Wiklander } 809062e3d01SJens Wiklander } 810062e3d01SJens Wiklander 811062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(a, &C)); 812062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(b, &D)); 813062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_shift_l(gcd, k)); 814062e3d01SJens Wiklander 815062e3d01SJens Wiklander out: 8167696ab7fSJens Wiklander mbedtls_mpi_free(&A); 8177696ab7fSJens Wiklander mbedtls_mpi_free(&B); 8187696ab7fSJens Wiklander mbedtls_mpi_free(&C); 8197696ab7fSJens Wiklander mbedtls_mpi_free(&D); 8207696ab7fSJens Wiklander mbedtls_mpi_free(&x); 8217696ab7fSJens Wiklander mbedtls_mpi_free(&y); 8227696ab7fSJens Wiklander mbedtls_mpi_free(&u); 823062e3d01SJens Wiklander } 824062e3d01SJens Wiklander 825062e3d01SJens Wiklander void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, 826062e3d01SJens Wiklander TEE_BigInt *v, const TEE_BigInt *op1, 827062e3d01SJens Wiklander const TEE_BigInt *op2) 828062e3d01SJens Wiklander { 829062e3d01SJens Wiklander mbedtls_mpi mpi_gcd_res; 830062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 831062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 832062e3d01SJens Wiklander mbedtls_mpi *pop2 = &mpi_op2; 833062e3d01SJens Wiklander 834062e3d01SJens Wiklander get_mpi(&mpi_gcd_res, gcd); 8357696ab7fSJens Wiklander get_mpi(&mpi_op1, op1); 836062e3d01SJens Wiklander 837062e3d01SJens Wiklander if (op2 == op1) 838062e3d01SJens Wiklander pop2 = &mpi_op1; 839062e3d01SJens Wiklander else 8407696ab7fSJens Wiklander get_mpi(&mpi_op2, op2); 841062e3d01SJens Wiklander 842062e3d01SJens Wiklander if (!u && !v) { 843b6fa905fSJens Wiklander MPI_CHECK(mbedtls_mpi_gcd(&mpi_gcd_res, &mpi_op1, pop2)); 844062e3d01SJens Wiklander } else { 845062e3d01SJens Wiklander mbedtls_mpi mpi_u; 846062e3d01SJens Wiklander mbedtls_mpi mpi_v; 847062e3d01SJens Wiklander int8_t s1 = mpi_op1.s; 848062e3d01SJens Wiklander int8_t s2 = pop2->s; 849062e3d01SJens Wiklander int cmp; 850062e3d01SJens Wiklander 851062e3d01SJens Wiklander mpi_op1.s = 1; 852062e3d01SJens Wiklander pop2->s = 1; 853062e3d01SJens Wiklander 854062e3d01SJens Wiklander get_mpi(&mpi_u, u); 855062e3d01SJens Wiklander get_mpi(&mpi_v, v); 856062e3d01SJens Wiklander 857062e3d01SJens Wiklander cmp = mbedtls_mpi_cmp_abs(&mpi_op1, pop2); 858062e3d01SJens Wiklander if (cmp == 0) { 859062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_gcd_res, &mpi_op1)); 860062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi_u, 1)); 861062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_lset(&mpi_v, 0)); 862062e3d01SJens Wiklander } else if (cmp > 0) { 863062e3d01SJens Wiklander mpi_egcd(&mpi_gcd_res, &mpi_u, &mpi_v, &mpi_op1, pop2); 864062e3d01SJens Wiklander } else { 865062e3d01SJens Wiklander mpi_egcd(&mpi_gcd_res, &mpi_v, &mpi_u, pop2, &mpi_op1); 866062e3d01SJens Wiklander } 867062e3d01SJens Wiklander 868062e3d01SJens Wiklander mpi_u.s *= s1; 869062e3d01SJens Wiklander mpi_v.s *= s2; 870062e3d01SJens Wiklander 8717696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_u, u)); 8727696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_v, v)); 8737696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_u); 8747696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_v); 875062e3d01SJens Wiklander } 876062e3d01SJens Wiklander 8777696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_gcd_res, gcd)); 8787696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_gcd_res); 8797696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1); 880062e3d01SJens Wiklander if (pop2 == &mpi_op2) 8817696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2); 882062e3d01SJens Wiklander } 883062e3d01SJens Wiklander 884062e3d01SJens Wiklander static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen) 885062e3d01SJens Wiklander { 8862c028fdeSJerome Forissier if (_utee_cryp_random_number_generate(buf, blen)) 887062e3d01SJens Wiklander return MBEDTLS_ERR_MPI_FILE_IO_ERROR; 888062e3d01SJens Wiklander return 0; 889062e3d01SJens Wiklander } 890062e3d01SJens Wiklander 891062e3d01SJens Wiklander int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, 892*32b31808SJens Wiklander uint32_t confidenceLevel) 893062e3d01SJens Wiklander { 894062e3d01SJens Wiklander int rc; 895062e3d01SJens Wiklander mbedtls_mpi mpi_op; 896062e3d01SJens Wiklander 8977696ab7fSJens Wiklander get_mpi(&mpi_op, op); 898062e3d01SJens Wiklander 899*32b31808SJens Wiklander rc = mbedtls_mpi_is_prime_ext(&mpi_op, MAX(confidenceLevel, 80U), 900*32b31808SJens Wiklander rng_read, NULL); 901062e3d01SJens Wiklander 9027696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op); 903062e3d01SJens Wiklander 904062e3d01SJens Wiklander if (rc) 905062e3d01SJens Wiklander return 0; 906062e3d01SJens Wiklander 907062e3d01SJens Wiklander return 1; 908062e3d01SJens Wiklander } 909062e3d01SJens Wiklander 910062e3d01SJens Wiklander /* 911062e3d01SJens Wiklander * Not so fast FMM implementation based on the normal big int functions. 912062e3d01SJens Wiklander * 913062e3d01SJens Wiklander * Note that these functions (along with all the other functions in this 914062e3d01SJens Wiklander * file) only are used directly by the TA doing bigint arithmetics on its 915062e3d01SJens Wiklander * own. Performance of RSA operations in TEE Internal API are not affected 916062e3d01SJens Wiklander * by this. 917062e3d01SJens Wiklander */ 918fe03ed8bSJens Wiklander void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len) 919062e3d01SJens Wiklander { 920062e3d01SJens Wiklander TEE_BigIntInit(bigIntFMM, len); 921062e3d01SJens Wiklander } 922062e3d01SJens Wiklander 923fe03ed8bSJens Wiklander void __GP11_TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len) 924fe03ed8bSJens Wiklander { 925fe03ed8bSJens Wiklander TEE_BigIntInitFMM(bigIntFMM, len); 926fe03ed8bSJens Wiklander } 927fe03ed8bSJens Wiklander 928062e3d01SJens Wiklander void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context __unused, 929fe03ed8bSJens Wiklander size_t len __unused, 930062e3d01SJens Wiklander const TEE_BigInt *modulus __unused) 931062e3d01SJens Wiklander { 932062e3d01SJens Wiklander } 933062e3d01SJens Wiklander 934fe03ed8bSJens Wiklander void __GP11_TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, 935fe03ed8bSJens Wiklander uint32_t len, const TEE_BigInt *modulus) 936fe03ed8bSJens Wiklander { 937fe03ed8bSJens Wiklander TEE_BigIntInitFMMContext(context, len, modulus); 938fe03ed8bSJens Wiklander } 939fe03ed8bSJens Wiklander 940fe03ed8bSJens Wiklander TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context __unused, 941fe03ed8bSJens Wiklander size_t len __unused, 942fe03ed8bSJens Wiklander const TEE_BigInt *modulus __unused) 943fe03ed8bSJens Wiklander { 944fe03ed8bSJens Wiklander return TEE_SUCCESS; 945fe03ed8bSJens Wiklander } 946fe03ed8bSJens Wiklander 947fe03ed8bSJens Wiklander size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits) 948062e3d01SJens Wiklander { 949062e3d01SJens Wiklander return TEE_BigIntSizeInU32(modulusSizeInBits); 950062e3d01SJens Wiklander } 951062e3d01SJens Wiklander 952fe03ed8bSJens Wiklander uint32_t __GP11_TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits) 953fe03ed8bSJens Wiklander { 954fe03ed8bSJens Wiklander return TEE_BigIntFMMSizeInU32(modulusSizeInBits); 955fe03ed8bSJens Wiklander } 956fe03ed8bSJens Wiklander 957fe03ed8bSJens Wiklander size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits __unused) 958062e3d01SJens Wiklander { 959062e3d01SJens Wiklander /* Return something larger than 0 to keep malloc() and friends happy */ 960062e3d01SJens Wiklander return 1; 961062e3d01SJens Wiklander } 962062e3d01SJens Wiklander 963fe03ed8bSJens Wiklander uint32_t __GP11_TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits) 964fe03ed8bSJens Wiklander { 965fe03ed8bSJens Wiklander return TEE_BigIntFMMContextSizeInU32(modulusSizeInBits); 966fe03ed8bSJens Wiklander } 967fe03ed8bSJens Wiklander 968062e3d01SJens Wiklander void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, 969062e3d01SJens Wiklander const TEE_BigInt *n, 970062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused) 971062e3d01SJens Wiklander { 972062e3d01SJens Wiklander TEE_BigIntMod(dest, src, n); 973062e3d01SJens Wiklander } 974062e3d01SJens Wiklander 975062e3d01SJens Wiklander void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, 976062e3d01SJens Wiklander const TEE_BigInt *n __unused, 977062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused) 978062e3d01SJens Wiklander { 979062e3d01SJens Wiklander mbedtls_mpi mpi_dst; 980062e3d01SJens Wiklander mbedtls_mpi mpi_src; 981062e3d01SJens Wiklander 982062e3d01SJens Wiklander get_mpi(&mpi_dst, dest); 9837696ab7fSJens Wiklander get_mpi(&mpi_src, src); 984062e3d01SJens Wiklander 985062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_copy(&mpi_dst, &mpi_src)); 986062e3d01SJens Wiklander 9877696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest)); 9887696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dst); 9897696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_src); 990062e3d01SJens Wiklander } 991062e3d01SJens Wiklander 992062e3d01SJens Wiklander void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, 993062e3d01SJens Wiklander const TEE_BigIntFMM *op2, const TEE_BigInt *n, 994062e3d01SJens Wiklander const TEE_BigIntFMMContext *context __unused) 995062e3d01SJens Wiklander { 996062e3d01SJens Wiklander mbedtls_mpi mpi_dst; 997062e3d01SJens Wiklander mbedtls_mpi mpi_op1; 998062e3d01SJens Wiklander mbedtls_mpi mpi_op2; 999062e3d01SJens Wiklander mbedtls_mpi mpi_n; 1000062e3d01SJens Wiklander mbedtls_mpi mpi_t; 1001062e3d01SJens Wiklander 1002062e3d01SJens Wiklander get_mpi(&mpi_dst, dest); 10037696ab7fSJens Wiklander get_mpi(&mpi_op1, op1); 10047696ab7fSJens Wiklander get_mpi(&mpi_op2, op2); 10057696ab7fSJens Wiklander get_mpi(&mpi_n, n); 1006062e3d01SJens Wiklander get_mpi(&mpi_t, NULL); 1007062e3d01SJens Wiklander 1008062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mul_mpi(&mpi_t, &mpi_op1, &mpi_op2)); 1009062e3d01SJens Wiklander MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dst, &mpi_t, &mpi_n)); 1010062e3d01SJens Wiklander 10117696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_t); 10127696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_n); 10137696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op2); 10147696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_op1); 10157696ab7fSJens Wiklander MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest)); 10167696ab7fSJens Wiklander mbedtls_mpi_free(&mpi_dst); 1017062e3d01SJens Wiklander } 1018