/* modi */ static int modi(void *a, unsigned long b, unsigned long *c) { mbedtls_mpi bn_b; mbedtls_mpi bn_c; int res = 0; mbedtls_mpi_init_mempool(&bn_b); mbedtls_mpi_init_mempool(&bn_c); res = set_int(&bn_b, b); if (res) return res; res = mbedtls_mpi_mod_mpi(&bn_c, &bn_b, a); if (!res) *c = get_int(&bn_c); mbedtls_mpi_free(&bn_b); mbedtls_mpi_free(&bn_c); if (res) return CRYPT_MEM; return CRYPT_OK; }
/* * Initializes a MPI. * * A temporary MPI is allocated and if a bigInt is supplied the MPI is * initialized with the value of the bigInt. */ static void get_mpi(mbedtls_mpi *mpi, const TEE_BigInt *bigInt) { /* * The way the GP spec is defining the bignums it's * difficult/tricky to do it using 64-bit arithmetics given that * we'd need 64-bit alignment of the data as well. */ COMPILE_TIME_ASSERT(sizeof(mbedtls_mpi_uint) == sizeof(uint32_t)); /* * The struct bigint_hdr is the overhead added to the bigint and * is required to take exactly 2 uint32_t. */ COMPILE_TIME_ASSERT(sizeof(struct bigint_hdr) == sizeof(uint32_t) * BIGINT_HDR_SIZE_IN_U32); mbedtls_mpi_init_mempool(mpi); if (bigInt) { const struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; const mbedtls_mpi_uint *p = (const mbedtls_mpi_uint *)(hdr + 1); size_t n = hdr->nblimbs; /* Trim of eventual insignificant zeroes */ while (n && !p[n - 1]) n--; MPI_CHECK(mbedtls_mpi_grow(mpi, n)); mpi->s = hdr->sign; memcpy(mpi->p, p, n * sizeof(mbedtls_mpi_uint)); } }
static int init(void **a) { mbedtls_mpi *bn = mempool_alloc(mbedtls_mpi_mempool, sizeof(*bn)); if (!bn) return CRYPT_MEM; mbedtls_mpi_init_mempool(bn); *a = bn; return CRYPT_OK; }
/* reduce */ static int montgomery_reduce(void *a, void *b, void *c) { mbedtls_mpi A; mbedtls_mpi *N = b; mbedtls_mpi_uint *mm = c; mbedtls_mpi T; int ret = CRYPT_MEM; mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A); if (mbedtls_mpi_grow(&T, (N->n + 1) * 2)) goto out; if (mbedtls_mpi_cmp_mpi(a, N) > 0) { if (mbedtls_mpi_mod_mpi(&A, a, N)) goto out; } else { if (mbedtls_mpi_copy(&A, a)) goto out; } if (mbedtls_mpi_grow(&A, N->n + 1)) goto out; if (mbedtls_mpi_montred(&A, N, *mm, &T)) goto out; if (mbedtls_mpi_copy(a, &A)) goto out; ret = CRYPT_OK; out: mbedtls_mpi_free(&A); mbedtls_mpi_free(&T); return ret; }
static int mulmod(void *a, void *b, void *c, void *d) { int res; mbedtls_mpi ta; mbedtls_mpi tb; mbedtls_mpi_init_mempool(&ta); mbedtls_mpi_init_mempool(&tb); res = mod(a, c, &ta); if (res) goto out; res = mod(b, c, &tb); if (res) goto out; res = mul(&ta, &tb, d); if (res) goto out; res = mod(d, c, d); out: mbedtls_mpi_free(&ta); mbedtls_mpi_free(&tb); return res; }
/* lcm */ static int lcm(void *a, void *b, void *c) { int res = CRYPT_MEM; mbedtls_mpi tmp; mbedtls_mpi_init_mempool(&tmp); if (mbedtls_mpi_mul_mpi(&tmp, a, b)) goto out; if (mbedtls_mpi_gcd(c, a, b)) goto out; /* We use the following equality: gcd(a, b) * lcm(a, b) = a * b */ res = divide(&tmp, c, c, NULL); out: mbedtls_mpi_free(&tmp); return res; }
/* * This function calculates: * d = a^b mod c * * @a: base * @b: exponent * @c: modulus * @d: destination */ static int exptmod(void *a, void *b, void *c, void *d) { int res; if (d == a || d == b || d == c) { mbedtls_mpi dest; mbedtls_mpi_init_mempool(&dest); res = mbedtls_mpi_exp_mod(&dest, a, b, c, NULL); if (!res) res = mbedtls_mpi_copy(d, &dest); mbedtls_mpi_free(&dest); } else { res = mbedtls_mpi_exp_mod(d, a, b, c, NULL); } if (res) return CRYPT_MEM; else return CRYPT_OK; }
/* * Initializes a MPI. * * If a bigint is supplied it's initialized with the value of the bigint * and changes will be written back completely with a call to put_mpi(). * The bigint dictates the size of the MPI which will be fixed to this * size. * * If no bigint is supplied a temporary MPI is allocated instead which will * be freed by put_mpi(). */ static void get_mpi(mbedtls_mpi *mpi, TEE_BigInt *bigInt) { /* * The way the GP spec is defining the bignums it's * difficult/tricky to do it using 64-bit arithmetics given that * we'd need 64-bit alignment of the data as well. */ COMPILE_TIME_ASSERT(sizeof(mbedtls_mpi_uint) == sizeof(uint32_t)); /* * The struct bigint_hdr is the overhead added to the bigint and * is required to take exactly 2 uint32_t. */ COMPILE_TIME_ASSERT(sizeof(struct bigint_hdr) == sizeof(uint32_t) * BIGINT_HDR_SIZE_IN_U32); if (bigInt) init_static_mpi(mpi, bigInt); else mbedtls_mpi_init_mempool(mpi); }
static int compare_d(void *a, unsigned long b) { unsigned long v = b; unsigned int shift = 31; uint32_t mask = BIT(shift) - 1; mbedtls_mpi bn; mbedtls_mpi_init_mempool(&bn); while (true) { mbedtls_mpi_add_int(&bn, &bn, v & mask); v >>= shift; if (!v) break; mbedtls_mpi_shift_l(&bn, shift); } int ret = compare(a, &bn); mbedtls_mpi_free(&bn); return ret; }