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); }
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; }
/* * Compute and write signature */ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; mbedtls_mpi r, s; mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) (void) f_rng; (void) p_rng; MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, hash, hlen, md_alg ) ); #else (void) md_alg; MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng ) ); #endif MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); }
/* 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; }
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); }
/* * Free the components of a sign restart sub-context */ static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) { if( ctx == NULL ) return; mbedtls_mpi_free( &ctx->k ); mbedtls_mpi_free( &ctx->r ); }
/* * Free the components of a DHM key */ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) { mbedtls_mpi_free( &ctx->pX); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P ); mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); }
/* * Restartable read and check signature */ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen, mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if( p + len != end ) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; goto cleanup; } if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } #if defined(MBEDTLS_ECDSA_VERIFY_ALT) if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; #else if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) goto cleanup; #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ /* At this point we know that the buffer starts with a valid signature. * Return 0 if the buffer just contains the signature, and a specific * error code if the valid signature is followed by more data. */ if( p != end ) ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); }
/* * Free the components of a verify restart sub-context */ static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) { if( ctx == NULL ) return; mbedtls_mpi_free( &ctx->u1 ); mbedtls_mpi_free( &ctx->u2 ); ecdsa_restart_ver_init( ctx ); }
bool ECDSA_Verify(COSE * pSigner, int index, const cn_cbor * pKey, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr) { mbedtls_ecp_keypair keypair; mbedtls_mpi r; mbedtls_mpi s; mbedtls_md_type_t mdType; const mbedtls_md_info_t *pmdInfo; byte rgbDigest[MBEDTLS_MD_MAX_SIZE]; cn_cbor * pSig; bool result = false; mbedtls_ecp_keypair_init(&keypair); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if(!ECKey_From(pKey, &keypair, perr)) goto errorReturn; switch(cbitDigest) { case 256: mdType = MBEDTLS_MD_SHA256; break; case 384: mdType = MBEDTLS_MD_SHA384; break; case 512: mdType = MBEDTLS_MD_SHA512; break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); } pmdInfo = mbedtls_md_info_from_type(mdType); CHECK_CONDITION(pmdInfo != NULL, COSE_ERR_INVALID_PARAMETER); CHECK_CONDITION(mbedtls_md(pmdInfo, rgbToSign, cbToSign, rgbDigest) == 0, COSE_ERR_INVALID_PARAMETER); pSig = _COSE_arrayget_int(pSigner, index); CHECK_CONDITION((pSig != NULL) && (pSig->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER); CHECK_CONDITION(mbedtls_mpi_read_binary( &r, pSig->v.bytes, pSig->length / 2 ) == 0, COSE_ERR_OUT_OF_MEMORY); CHECK_CONDITION(mbedtls_mpi_read_binary( &s, pSig->v.bytes + pSig->length / 2, pSig->length / 2 ) == 0, COSE_ERR_OUT_OF_MEMORY); CHECK_CONDITION(mbedtls_ecdsa_verify(&keypair.grp, rgbDigest, mbedtls_md_get_size(pmdInfo), &keypair.Q, &r, &s) == 0, COSE_ERR_CRYPTO_FAIL); result = true; errorReturn: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecp_keypair_free(&keypair); return result; }
/* * Free context */ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) { if( ctx == NULL ) return; mbedtls_ecp_group_free( &ctx->grp ); mbedtls_ecp_point_free( &ctx->Q ); mbedtls_ecp_point_free( &ctx->Qp ); mbedtls_ecp_point_free( &ctx->Vi ); mbedtls_ecp_point_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->d ); mbedtls_mpi_free( &ctx->z ); mbedtls_mpi_free( &ctx->_d ); }
/* * Deterministic signature wrapper */ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg ) { int ret; mbedtls_hmac_drbg_context rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = ( grp->nbits + 7 ) / 8; const mbedtls_md_info_t *md_info; mbedtls_mpi h; if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); mbedtls_mpi_init( &h ); mbedtls_hmac_drbg_init( &rng_ctx ); /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, &rng_ctx ); cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_mpi_free( &h ); return( ret ); }
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; }
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; }
result_t X509Cert::get_serial(exlib::string &retVal) { mbedtls_x509_crt *crt = get_crt(); if (!crt) return CHECK_ERROR(CALL_E_INVALID_CALL); int32_t ret; mbedtls_mpi serial; mbedtls_mpi_init(&serial); ret = mbedtls_mpi_read_binary(&serial, crt->serial.p, crt->serial.len); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); retVal.resize(8192); size_t sz = retVal.length(); ret = mbedtls_mpi_write_string(&serial, 10, &retVal[0], sz, &sz); mbedtls_mpi_free(&serial); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); retVal.resize(sz - 1); return 0; }
/* Z = (X * Y) mod M Not an mbedTLS function */ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M) { int ret; size_t num_words = hardware_words_needed(M); mbedtls_mpi Rinv; mbedtls_mpi_uint Mprime; /* Calculate and load the first stage montgomery multiplication */ mbedtls_mpi_init(&Rinv); MBEDTLS_MPI_CHK(calculate_rinv(&Rinv, M, num_words)); Mprime = modular_inverse(M); esp_mpi_acquire_hardware(); /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */ mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words); mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, num_words); REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime); /* "mode" register loaded with number of 512-bit blocks, minus 1 */ REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1); /* Execute first stage montgomery multiplication */ execute_op(RSA_MULT_START_REG); /* execute second stage */ MBEDTLS_MPI_CHK( modular_multiply_finish(Z, X, Y, num_words) ); esp_mpi_release_hardware(); cleanup: mbedtls_mpi_free(&Rinv); return ret; }
/* * Read and check signature */ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ) { int ret; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if( p + len != end ) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; goto cleanup; } if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; if( p != end ) ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); }
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 mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) { mbedtls_mpi_free( &ctx->serial ); mbedtls_asn1_free_named_data_list( &ctx->subject ); mbedtls_asn1_free_named_data_list( &ctx->issuer ); mbedtls_asn1_free_named_data_list( &ctx->extensions ); mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) ); }
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); }
/* * Uninitialize a MPI. * * If the MPI is linked to a bigint the final changes (size and sign) will * be copied back. * * If the MPI isn't linked to bigint it's only freed. */ static void put_mpi(mbedtls_mpi *mpi) { if (mpi->alloc_type == MBEDTLS_MPI_ALLOC_TYPE_STATIC) { struct bigint_hdr *hdr = ((struct bigint_hdr *)mpi->p) - 1; hdr->sign = mpi->s; hdr->nblimbs = mpi->n; } else { mbedtls_mpi_free(mpi); } }
/* * Verify sanity of parameter with regards to P * * Parameter should be: 2 <= public_param <= P - 2 * * For more information on the attack, see: * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 */ static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) { mbedtls_mpi L, U; int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); if( mbedtls_mpi_cmp_mpi( param, &L ) >= 0 && mbedtls_mpi_cmp_mpi( param, &U ) <= 0 ) { ret = 0; } cleanup: mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); return( ret ); }
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; }
/* Calculate Rinv = RR^2 mod M, where: * * R = b^n where b = 2^32, n=num_words, * R = 2^N (where N=num_bits) * RR = R^2 = 2^(2*N) (where N=num_bits=num_words*32) * * This calculation is computationally expensive (mbedtls_mpi_mod_mpi) * so caller should cache the result where possible. * * DO NOT call this function while holding esp_mpi_acquire_hardware(). * */ static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words) { int ret; size_t num_bits = num_words * 32; mbedtls_mpi RR; mbedtls_mpi_init(&RR); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&RR, num_bits * 2, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(Rinv, &RR, M)); cleanup: mbedtls_mpi_free(&RR); return ret; }
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; }