bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2) { bool rc; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop2 = &mpi_op2; mbedtls_mpi gcd; get_mpi(&mpi_op1, op1); if (op2 == op1) pop2 = &mpi_op1; else get_mpi(&mpi_op2, op2); get_mpi(&gcd, NULL); MPI_CHECK(mbedtls_mpi_gcd(&gcd, &mpi_op1, &mpi_op2)); rc = !mbedtls_mpi_cmp_int(&gcd, 1); mbedtls_mpi_free(&gcd); mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); return rc; }
static void bigint_binary(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)) { mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop1 = &mpi_op1; mbedtls_mpi *pop2 = &mpi_op2; get_mpi(&mpi_dest, dest); if (op1 == dest) pop1 = &mpi_dest; else get_mpi(&mpi_op1, op1); if (op2 == dest) pop2 = &mpi_dest; else if (op2 == op1) pop2 = pop1; else get_mpi(&mpi_op2, op2); MPI_CHECK(func(&mpi_dest, pop1, pop2)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); if (pop1 == &mpi_op1) mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); }
void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n) { if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0) API_PANIC("too small modulus or trying to invert zero"); mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op; mbedtls_mpi mpi_n; mbedtls_mpi *pop = &mpi_op; get_mpi(&mpi_dest, dest); get_mpi(&mpi_n, n); if (op == dest) pop = &mpi_dest; else get_mpi(&mpi_op, op); MPI_CHECK(mbedtls_mpi_inv_mod(&mpi_dest, pop, &mpi_n)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); mbedtls_mpi_free(&mpi_n); if (pop == &mpi_op) mbedtls_mpi_free(&mpi_op); }
void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, TEE_BigInt *v, const TEE_BigInt *op1, const TEE_BigInt *op2) { mbedtls_mpi mpi_gcd_res; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop2 = &mpi_op2; get_mpi(&mpi_gcd_res, gcd); get_mpi(&mpi_op1, op1); if (op2 == op1) pop2 = &mpi_op1; else get_mpi(&mpi_op2, op2); if (!u && !v) { if (gcd) MPI_CHECK(mbedtls_mpi_gcd(&mpi_gcd_res, &mpi_op1, pop2)); } else { mbedtls_mpi mpi_u; mbedtls_mpi mpi_v; int8_t s1 = mpi_op1.s; int8_t s2 = pop2->s; int cmp; mpi_op1.s = 1; pop2->s = 1; get_mpi(&mpi_u, u); get_mpi(&mpi_v, v); cmp = mbedtls_mpi_cmp_abs(&mpi_op1, pop2); if (cmp == 0) { MPI_CHECK(mbedtls_mpi_copy(&mpi_gcd_res, &mpi_op1)); MPI_CHECK(mbedtls_mpi_lset(&mpi_u, 1)); MPI_CHECK(mbedtls_mpi_lset(&mpi_v, 0)); } else if (cmp > 0) { mpi_egcd(&mpi_gcd_res, &mpi_u, &mpi_v, &mpi_op1, pop2); } else { mpi_egcd(&mpi_gcd_res, &mpi_v, &mpi_u, pop2, &mpi_op1); } mpi_u.s *= s1; mpi_v.s *= s2; MPI_CHECK(copy_mpi_to_bigint(&mpi_u, u)); MPI_CHECK(copy_mpi_to_bigint(&mpi_v, v)); mbedtls_mpi_free(&mpi_u); mbedtls_mpi_free(&mpi_v); } MPI_CHECK(copy_mpi_to_bigint(&mpi_gcd_res, gcd)); mbedtls_mpi_free(&mpi_gcd_res); mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); }
int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2) { mbedtls_mpi mpi1; mbedtls_mpi mpi2; int32_t rc; get_mpi(&mpi1, op1); get_mpi(&mpi2, op2); rc = mbedtls_mpi_cmp_mpi(&mpi1, &mpi2); mbedtls_mpi_free(&mpi1); mbedtls_mpi_free(&mpi2); return rc; }
TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src) { TEE_Result res = TEE_SUCCESS; mbedtls_mpi mpi; uint32_t v; get_mpi(&mpi, src); if (mbedtls_mpi_write_binary(&mpi, (void *)&v, sizeof(v))) { res = TEE_ERROR_OVERFLOW; goto out; } if (mpi.s > 0) { if (ADD_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) res = TEE_ERROR_OVERFLOW; } else { if (SUB_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) res = TEE_ERROR_OVERFLOW; } out: mbedtls_mpi_free(&mpi); return res; }
/* * Initializes a MPI from a constant bigint. * * A MPI is allocated and given an initial value based on the supplied * bigint. When the MPI is freed with put_mpi() no changes are propagated * back. */ static void get_const_mpi(mbedtls_mpi *mpi, const TEE_BigInt *bigInt) { mbedtls_mpi mpi_const; init_static_mpi(&mpi_const, (TEE_BigInt *)bigInt); get_mpi(mpi, NULL); MPI_CHECK(mbedtls_mpi_copy(mpi, &mpi_const)); }
static void bigint_binary_mod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n, int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)) { if (TEE_BigIntCmpS32(n, 2) < 0) API_PANIC("Modulus is too short"); mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi mpi_n; mbedtls_mpi *pop1 = &mpi_op1; mbedtls_mpi *pop2 = &mpi_op2; mbedtls_mpi mpi_t; get_mpi(&mpi_dest, dest); get_mpi(&mpi_n, n); if (op1 == dest) pop1 = &mpi_dest; else get_mpi(&mpi_op1, op1); if (op2 == dest) pop2 = &mpi_dest; else if (op2 == op1) pop2 = pop1; else get_mpi(&mpi_op2, op2); get_mpi(&mpi_t, NULL); MPI_CHECK(func(&mpi_t, pop1, pop2)); MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dest, &mpi_t, &mpi_n)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); if (pop1 == &mpi_op1) mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); mbedtls_mpi_free(&mpi_t); }
void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal) { mbedtls_mpi mpi; get_mpi(&mpi, dest); MPI_CHECK(mbedtls_mpi_lset(&mpi, shortVal)); put_mpi(&mpi); }
void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal) { mbedtls_mpi mpi; get_mpi(&mpi, dest); MPI_CHECK(mbedtls_mpi_lset(&mpi, shortVal)); MPI_CHECK(copy_mpi_to_bigint(&mpi, dest)); mbedtls_mpi_free(&mpi); }
void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src) { mbedtls_mpi mpi_dest; get_mpi(&mpi_dest, dest); if (dest != src) { mbedtls_mpi mpi_src; get_mpi(&mpi_src, src); MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_src)); mbedtls_mpi_free(&mpi_src); } mpi_dest.s *= -1; MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); }
void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits) { mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op; get_mpi(&mpi_dest, dest); if (dest == op) { MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); goto out; } get_mpi(&mpi_op, op); if (mbedtls_mpi_size(&mpi_dest) >= mbedtls_mpi_size(&mpi_op)) { MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_op)); MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); } else { mbedtls_mpi mpi_t; get_mpi(&mpi_t, NULL); /* * We're using a temporary buffer to avoid the corner case * where destination is unexpectedly overflowed by up to * @bits number of bits. */ MPI_CHECK(mbedtls_mpi_copy(&mpi_t, &mpi_op)); MPI_CHECK(mbedtls_mpi_shift_r(&mpi_t, bits)); MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_t)); mbedtls_mpi_free(&mpi_t); } mbedtls_mpi_free(&mpi_op); out: MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); }
void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, const TEE_BigInt *op1, const TEE_BigInt *op2) { mbedtls_mpi mpi_dest_q; mbedtls_mpi mpi_dest_r; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop1 = &mpi_op1; mbedtls_mpi *pop2 = &mpi_op2; get_mpi(&mpi_dest_q, dest_q); get_mpi(&mpi_dest_r, dest_r); if (op1 == dest_q) pop1 = &mpi_dest_q; else if (op1 == dest_r) pop1 = &mpi_dest_r; else get_mpi(&mpi_op1, op1); if (op2 == dest_q) pop2 = &mpi_dest_q; else if (op2 == dest_r) pop2 = &mpi_dest_r; else if (op2 == op1) pop2 = pop1; else get_mpi(&mpi_op2, op2); MPI_CHECK(mbedtls_mpi_div_mpi(&mpi_dest_q, &mpi_dest_r, pop1, pop2)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_q, dest_q)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_r, dest_r)); mbedtls_mpi_free(&mpi_dest_q); mbedtls_mpi_free(&mpi_dest_r); if (pop1 == &mpi_op1) mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); }
uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src) { uint32_t rc; mbedtls_mpi mpi; get_mpi(&mpi, src); rc = mbedtls_mpi_bitlen(&mpi); mbedtls_mpi_free(&mpi); return rc; }
int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal) { mbedtls_mpi mpi; int32_t rc; get_mpi(&mpi, op); rc = mbedtls_mpi_cmp_int(&mpi, shortVal); mbedtls_mpi_free(&mpi); return rc; }
bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex) { bool rc; mbedtls_mpi mpi; get_mpi(&mpi, src); rc = mbedtls_mpi_get_bit(&mpi, bitIndex); mbedtls_mpi_free(&mpi); return rc; }
static libspectrum_error get_signature( gcry_mpi_t *r, gcry_mpi_t *s, libspectrum_byte *data, size_t data_length, libspectrum_rzx_dsa_key *key ) { libspectrum_error error; gcry_error_t gcrypt_error; gcry_sexp_t hash, s_key, s_signature; error = get_hash( &hash, data, data_length ); if( error ) return error; error = create_key( &s_key, key, 1 ); if( error ) { gcry_sexp_release( hash ); return error; } gcrypt_error = gcry_pk_sign( &s_signature, hash, s_key ); if( gcrypt_error ) { libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC, "get_signature: error signing data: %s", gcry_strerror( gcrypt_error ) ); gcry_sexp_release( s_key ); gcry_sexp_release( hash ); return LIBSPECTRUM_ERROR_LOGIC; } gcry_sexp_release( s_key ); gcry_sexp_release( hash ); error = get_mpi( r, s_signature, "r" ); if( error ) { gcry_sexp_release( s_signature ); return error; } error = get_mpi( s, s_signature, "s" ); if( error ) { gcry_sexp_release( s_signature ); gcry_mpi_release( *r ); return error; } gcry_sexp_release( s_signature ); return LIBSPECTRUM_ERROR_NONE; }
void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src) { mbedtls_mpi mpi_dest; get_mpi(&mpi_dest, dest); if (dest != src) { mbedtls_mpi mpi_src; get_const_mpi(&mpi_src, src); MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_src)); put_mpi(&mpi_src); } mpi_dest.s *= -1; put_mpi(&mpi_dest); }
TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, uint32_t *bufferLen, const TEE_BigInt *bigInt) { TEE_Result res = TEE_SUCCESS; mbedtls_mpi mpi; size_t sz; get_mpi(&mpi, bigInt); sz = mbedtls_mpi_size(&mpi); if (sz <= *bufferLen) MPI_CHECK(mbedtls_mpi_write_binary(&mpi, buffer, sz)); else res = TEE_ERROR_SHORT_BUFFER; *bufferLen = sz; mbedtls_mpi_free(&mpi); return res; }
TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, const uint8_t *buffer, uint32_t bufferLen, int32_t sign) { TEE_Result res; mbedtls_mpi mpi_dest; get_mpi(&mpi_dest, dest); if (mbedtls_mpi_read_binary(&mpi_dest, buffer, bufferLen)) res = TEE_ERROR_OVERFLOW; else res = TEE_SUCCESS; if (sign < 0) mpi_dest.s = -1; put_mpi(&mpi_dest); return res; }
/* * Based on libmpa implementation __mpa_egcd(), modified to work with MPI * instead. */ static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b, mbedtls_mpi *x_in, mbedtls_mpi *y_in) { mbedtls_mpi_uint k; mbedtls_mpi A; mbedtls_mpi B; mbedtls_mpi C; mbedtls_mpi D; mbedtls_mpi x; mbedtls_mpi y; mbedtls_mpi u; get_mpi(&A, NULL); get_mpi(&B, NULL); get_mpi(&C, NULL); get_mpi(&D, NULL); get_mpi(&x, NULL); get_mpi(&y, NULL); get_mpi(&u, NULL); /* have y < x from assumption */ if (!mbedtls_mpi_cmp_int(y_in, 0)) { MPI_CHECK(mbedtls_mpi_lset(a, 1)); MPI_CHECK(mbedtls_mpi_lset(b, 0)); MPI_CHECK(mbedtls_mpi_copy(gcd, x_in)); goto out; } MPI_CHECK(mbedtls_mpi_copy(&x, x_in)); MPI_CHECK(mbedtls_mpi_copy(&y, y_in)); k = 0; while (mpi_is_even(&x) && mpi_is_even(&y)) { k++; MPI_CHECK(mbedtls_mpi_shift_r(&x, 1)); MPI_CHECK(mbedtls_mpi_shift_r(&y, 1)); } MPI_CHECK(mbedtls_mpi_copy(&u, &x)); MPI_CHECK(mbedtls_mpi_copy(gcd, &y)); MPI_CHECK(mbedtls_mpi_lset(&A, 1)); MPI_CHECK(mbedtls_mpi_lset(&B, 0)); MPI_CHECK(mbedtls_mpi_lset(&C, 0)); MPI_CHECK(mbedtls_mpi_lset(&D, 1)); while (mbedtls_mpi_cmp_int(&u, 0)) { while (mpi_is_even(&u)) { MPI_CHECK(mbedtls_mpi_shift_r(&u, 1)); if (mpi_is_odd(&A) || mpi_is_odd(&B)) { MPI_CHECK(mbedtls_mpi_add_mpi(&A, &A, &y)); MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &x)); } MPI_CHECK(mbedtls_mpi_shift_r(&A, 1)); MPI_CHECK(mbedtls_mpi_shift_r(&B, 1)); } while (mpi_is_even(gcd)) { MPI_CHECK(mbedtls_mpi_shift_r(gcd, 1)); if (mpi_is_odd(&C) || mpi_is_odd(&D)) { MPI_CHECK(mbedtls_mpi_add_mpi(&C, &C, &y)); MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &x)); } MPI_CHECK(mbedtls_mpi_shift_r(&C, 1)); MPI_CHECK(mbedtls_mpi_shift_r(&D, 1)); } if (mbedtls_mpi_cmp_mpi(&u, gcd) >= 0) { MPI_CHECK(mbedtls_mpi_sub_mpi(&u, &u, gcd)); MPI_CHECK(mbedtls_mpi_sub_mpi(&A, &A, &C)); MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &D)); } else { MPI_CHECK(mbedtls_mpi_sub_mpi(gcd, gcd, &u)); MPI_CHECK(mbedtls_mpi_sub_mpi(&C, &C, &A)); MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &B)); } } MPI_CHECK(mbedtls_mpi_copy(a, &C)); MPI_CHECK(mbedtls_mpi_copy(b, &D)); MPI_CHECK(mbedtls_mpi_shift_l(gcd, k)); out: mbedtls_mpi_free(&A); mbedtls_mpi_free(&B); mbedtls_mpi_free(&C); mbedtls_mpi_free(&D); mbedtls_mpi_free(&x); mbedtls_mpi_free(&y); mbedtls_mpi_free(&u); }