/* * 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 ); }
/* * 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 ); }
int main( void ) { int ret; mbedtls_mpi E, P, Q, N, H, D, X, Y, Z; mbedtls_mpi_init( &E ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &D ); mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P, 10, "2789" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Q, 10, "3203" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 10, "257" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &N, &P, &Q ) ); mbedtls_printf( "\n Public key:\n\n" ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " N = ", &N, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " E = ", &E, 10, NULL ) ); mbedtls_printf( "\n Private key:\n\n" ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " P = ", &P, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Q = ", &Q, 10, NULL ) ); #if defined(MBEDTLS_GENPRIME) MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P, &P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q, &Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P, &Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &D, &E, &H ) ); mbedtls_mpi_write_file( " D = E^-1 mod (P-1)*(Q-1) = ", &D, 10, NULL ); #else mbedtls_printf("\nTest skipped (MBEDTLS_GENPRIME not defined).\n\n"); #endif MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &X, 10, "55555" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &Y, &X, &E, &N, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &Z, &Y, &D, &N, NULL ) ); mbedtls_printf( "\n RSA operation:\n\n" ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " X (plaintext) = ", &X, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Y (ciphertext) = X^E mod N = ", &Y, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Z (decrypted) = Y^D mod N = ", &Z, 10, NULL ) ); mbedtls_printf( "\n" ); cleanup: mbedtls_mpi_free( &E ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &D ); mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); if( ret != 0 ) { mbedtls_printf( "\nAn error occurred.\n" ); ret = 1; } #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char **argv ) { int ret = 1; mbedtls_mpi G, P, Q; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "dh_genprime"; FILE *fout; int nbits = DFL_BITS; int i; char *p, *q; mbedtls_mpi_init( &G ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_entropy_init( &entropy ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); return( 1 ); } for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "bits" ) == 0 ) { nbits = atoi( q ); if( nbits < 0 || nbits > MBEDTLS_MPI_MAX_BITS ) goto usage; } else goto usage; } if( ( ret = mbedtls_mpi_read_string( &G, 10, GENERATOR ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_string returned %d\n", ret ); goto exit; } mbedtls_printf( " ! Generating large primes may take minutes!\n" ); mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n . Generating the modulus, please wait..." ); fflush( stdout ); /* * This can take a long time... */ if( ( ret = mbedtls_mpi_gen_prime( &P, nbits, 1, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_gen_prime returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n . Verifying that Q = (P-1)/2 is prime..." ); fflush( stdout ); if( ( ret = mbedtls_mpi_sub_int( &Q, &P, 1 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_sub_int returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_mpi_div_int( &Q, NULL, &Q, 2 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_div_int returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_mpi_is_prime( &Q, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_is_prime returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n . Exporting the value in dh_prime.txt..." ); fflush( stdout ); if( ( fout = fopen( "dh_prime.txt", "wb+" ) ) == NULL ) { ret = 1; mbedtls_printf( " failed\n ! Could not create dh_prime.txt\n\n" ); goto exit; } if( ( ret = mbedtls_mpi_write_file( "P = ", &P, 16, fout ) != 0 ) || ( ret = mbedtls_mpi_write_file( "G = ", &G, 16, fout ) != 0 ) ) { mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n\n" ); fclose( fout ); exit: mbedtls_mpi_free( &G ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * 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 ); }