/* * Check a private RSA key */ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) { int ret; mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) return( ret ); if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); /* * Check for a valid PKCS1v2 private key */ if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || mbedtls_mpi_cmp_int( &I, 1 ) != 0 || mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } cleanup: mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP ); if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) return( ret ); if( ret != 0 ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); return( 0 ); }
/* * Generate or update blinding values, see section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer * Berlin Heidelberg, 1996. p. 104-113. */ static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, count = 0; if( ctx->Vf.p != NULL ) { /* We already have blinding values, just update them by squaring */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); goto cleanup; } /* Unblinding value: Vf = random number, invertible mod N */ do { if( count++ > 10 ) return( MBEDTLS_ERR_RSA_RNG_FAILED ); MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); /* Blinding value: Vi = Vf^(-e) mod N */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); cleanup: return( ret ); }
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; }
/* gcd */ static int gcd(void *a, void *b, void *c) { if (mbedtls_mpi_gcd(c, a, b)) return CRYPT_MEM; return CRYPT_OK; }
/* 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; }
/* * Generate an RSA keypair */ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent ) { int ret; mbedtls_mpi P1, Q1, H, G; if( f_rng == NULL || nbits < 128 || exponent < 3 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); do { MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mbedtls_mpi_swap( &ctx->P, &ctx->Q ); if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) continue; MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) continue; MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); } while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); /* * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; cleanup: mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); if( ret != 0 ) { mbedtls_rsa_free( ctx ); return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); } return( 0 ); }