/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent ) { int ret; mpi P1, Q1, H, G; if( f_rng == NULL || nbits < 128 || exponent < 3 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ MPI_CHK( mpi_lset( &ctx->E, exponent ) ); do { MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mpi_swap( &ctx->P, &ctx->Q ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) continue; MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); if( mpi_msb( &ctx->N ) != nbits ) continue; MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); } while( 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 */ MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; cleanup: mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G ); if( ret != 0 ) { rsa_free( ctx ); return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret ); } return( 0 ); }
/* * Do an RSA private key operation */ int rsa_private( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output ) { int ret; size_t olen; mpi T, T1, T2; mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { mpi_free( &T ); return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } #if defined(POLARSSL_RSA_NO_CRT) ((void) f_rng); ((void) p_rng); MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); #else if( f_rng != NULL ) { /* * Blinding * T = T * Vi mod N */ MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); MPI_CHK( mpi_mul_mpi( &T, &T, &ctx->Vi ) ); MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); } /* * faster decryption using the CRT * * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q */ MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P */ MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); /* * output = T2 + T * Q */ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); if( f_rng != NULL ) { /* * Unblind * T = T * Vf mod N */ MPI_CHK( mpi_mul_mpi( &T, &T, &ctx->Vf ) ); MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); } #endif olen = ctx->len; MPI_CHK( mpi_write_binary( &T, output, olen ) ); cleanup: mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); if( ret != 0 ) return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret ); return( 0 ); }
/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int nbits, int exponent, int (*rng_f)(void *), void *rng_d ) { int ret; mpi P1, Q1, H, G; if( nbits < 128 || exponent < 3 || rng_f == NULL ) return( ERR_RSA_BAD_INPUT_DATA ); mpi_init( &P1, &Q1, &H, &G, NULL ); memset( ctx, 0, sizeof( rsa_context ) ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ CHK( mpi_lset( &ctx->E, exponent ) ); nbits >>= 1; do { CHK( mpi_gen_prime( &ctx->P, nbits, 0, rng_f, rng_d ) ); CHK( mpi_gen_prime( &ctx->Q, nbits, 0, rng_f, rng_d ) ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mpi_swap( &ctx->P, &ctx->Q ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) continue; CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); CHK( mpi_gcd( &G, &ctx->E, &H ) ); } while( 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 */ CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mpi_size( &ctx->N ) + 7 ) >> 3; cleanup: mpi_free( &P1, &Q1, &H, &G, NULL ); if( ret != 0 ) { rsa_free( ctx ); return( ERR_RSA_KEY_GEN_FAILED | ret ); } return( 0 ); }
/* * Do an RSA private key operation */ int rsa_private( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output ) { int ret; size_t olen; mpi T, T1, T2; #if !defined(POLARSSL_RSA_NO_CRT) mpi *Vi, *Vf; /* * When using the Chinese Remainder Theorem, we use blinding values. * Without threading, we just read them directly from the context, * otherwise we make a local copy in order to reduce locking contention. */ #if defined(POLARSSL_THREADING_C) mpi Vi_copy, Vf_copy; mpi_init( &Vi_copy ); mpi_init( &Vf_copy ); Vi = &Vi_copy; Vf = &Vf_copy; #else Vi = &ctx->Vi; Vf = &ctx->Vf; #endif #endif /* !POLARSSL_RSA_NO_CRT */ mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { mpi_free( &T ); return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } #if defined(POLARSSL_RSA_NO_CRT) ((void) f_rng); ((void) p_rng); MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); #else if( f_rng != NULL ) { /* * Blinding * T = T * Vi mod N */ MPI_CHK( rsa_prepare_blinding( ctx, Vi, Vf, f_rng, p_rng ) ); MPI_CHK( mpi_mul_mpi( &T, &T, Vi ) ); MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); } /* * faster decryption using the CRT * * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q */ MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P */ MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); /* * T = T2 + T * Q */ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); if( f_rng != NULL ) { /* * Unblind * T = T * Vf mod N */ MPI_CHK( mpi_mul_mpi( &T, &T, Vf ) ); MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); } #endif /* POLARSSL_RSA_NO_CRT */ olen = ctx->len; MPI_CHK( mpi_write_binary( &T, output, olen ) ); cleanup: mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); #if !defined(POLARSSL_RSA_NO_CRT) && defined(POLARSSL_THREADING_C) mpi_free( &Vi_copy ); mpi_free( &Vf_copy ); #endif if( ret != 0 ) return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret ); return( 0 ); }
int main( void ) { int ret; mpi E, P, Q, N, H, D, X, Y, Z; mpi_init( &E ); mpi_init( &P ); mpi_init( &Q ); mpi_init( &N ); mpi_init( &H ); mpi_init( &D ); mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); MPI_CHK( mpi_read_string( &P, 10, "2789" ) ); MPI_CHK( mpi_read_string( &Q, 10, "3203" ) ); MPI_CHK( mpi_read_string( &E, 10, "257" ) ); MPI_CHK( mpi_mul_mpi( &N, &P, &Q ) ); polarssl_printf( "\n Public key:\n\n" ); MPI_CHK( mpi_write_file( " N = ", &N, 10, NULL ) ); MPI_CHK( mpi_write_file( " E = ", &E, 10, NULL ) ); polarssl_printf( "\n Private key:\n\n" ); MPI_CHK( mpi_write_file( " P = ", &P, 10, NULL ) ); MPI_CHK( mpi_write_file( " Q = ", &Q, 10, NULL ) ); #if defined(POLARSSL_GENPRIME) MPI_CHK( mpi_sub_int( &P, &P, 1 ) ); MPI_CHK( mpi_sub_int( &Q, &Q, 1 ) ); MPI_CHK( mpi_mul_mpi( &H, &P, &Q ) ); MPI_CHK( mpi_inv_mod( &D, &E, &H ) ); mpi_write_file( " D = E^-1 mod (P-1)*(Q-1) = ", &D, 10, NULL ); #else polarssl_printf("\nTest skipped (POLARSSL_GENPRIME not defined).\n\n"); #endif MPI_CHK( mpi_read_string( &X, 10, "55555" ) ); MPI_CHK( mpi_exp_mod( &Y, &X, &E, &N, NULL ) ); MPI_CHK( mpi_exp_mod( &Z, &Y, &D, &N, NULL ) ); polarssl_printf( "\n RSA operation:\n\n" ); MPI_CHK( mpi_write_file( " X (plaintext) = ", &X, 10, NULL ) ); MPI_CHK( mpi_write_file( " Y (ciphertext) = X^E mod N = ", &Y, 10, NULL ) ); MPI_CHK( mpi_write_file( " Z (decrypted) = Y^D mod N = ", &Z, 10, NULL ) ); polarssl_printf( "\n" ); cleanup: mpi_free( &E ); mpi_free( &P ); mpi_free( &Q ); mpi_free( &N ); mpi_free( &H ); mpi_free( &D ); mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); if( ret != 0 ) { polarssl_printf( "\nAn error occurred.\n" ); ret = 1; } #if defined(_WIN32) polarssl_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
void cmd_sign(char *conf, char *key) { rsa_sig_t sign; rsa_key_t pubkey; rsa_key_t seckey; rsa_context *ctx; sigstruct_t *sigstruct; // Load sigstruct from file sigstruct = load_sigstruct(conf); // Ignore fields don't need to sign memset(sigstruct->modulus, 0, 384); sigstruct->exponent = 0; memset(sigstruct->signature, 0, 384); memset(sigstruct->q1, 0, 384); memset(sigstruct->q2, 0, 384); // Load rsa keys from file ctx = load_rsa_keys(key, pubkey, seckey, KEY_LENGTH_BITS); #if 0 { char *pubkey_str = fmt_bytes(pubkey, KEY_LENGTH); char *seckey_str = fmt_bytes(seckey, KEY_LENGTH); printf("PUBKEY: %.40s..\n", pubkey_str); printf("SECKEY: %.40s..\n", seckey_str); free(pubkey_str); free(seckey_str); } #endif // Generate rsa sign on sigstruct with private key rsa_sign(ctx, sign, (unsigned char *)sigstruct, sizeof(sigstruct_t)); // Compute q1, q2 unsigned char *q1, *q2; q1 = malloc(384); q2 = malloc(384); memset(q1, 0, 384); memset(q2, 0, 384); mpi Q1, Q2, S, M, T1, T2, R; mpi_init(&Q1); mpi_init(&Q2); mpi_init(&S); mpi_init(&M); mpi_init(&T1); mpi_init(&T2); mpi_init(&R); // q1 = signature ^ 2 / modulus mpi_read_binary(&S, sign, 384); mpi_read_binary(&M, pubkey, 384); mpi_mul_mpi(&T1, &S, &S); mpi_div_mpi(&Q1, &R, &T1, &M); // q2 = (signature ^ 3 - q1 * signature * modulus) / modulus mpi_init(&R); mpi_mul_mpi(&T1, &T1, &S); mpi_mul_mpi(&T2, &Q1, &S); mpi_mul_mpi(&T2, &T2, &M); mpi_sub_mpi(&Q2, &T1, &T2); mpi_div_mpi(&Q2, &R, &Q2, &M); mpi_write_binary(&Q1, q1, 384); mpi_write_binary(&Q2, q2, 384); mpi_free(&Q1); mpi_free(&Q2); mpi_free(&S); mpi_free(&M); mpi_free(&T1); mpi_free(&T2); mpi_free(&R); sigstruct = load_sigstruct(conf); sigstruct->exponent = 3; memcpy(sigstruct->modulus, pubkey, 384); memcpy(sigstruct->signature, sign, 384); memcpy(sigstruct->q1, q1, 384); memcpy(sigstruct->q2, q2, 384); char *msg = dump_sigstruct(sigstruct); printf("# SIGSTRUCT START\n"); printf("%s\n", msg); printf("# SIGSTRUCT END\n"); /*unsigned char exp[4] = { 0x00, 0x00, 0x00, 0x03 }; char *mod_str = fmt_bytes(pubkey, 384); char *exp_str = fmt_bytes(exp, 4); char *sign_str = fmt_bytes(sign, 384); char *q1_str = fmt_bytes(q1, 384); char *q2_str = fmt_bytes(q2, 384); printf("# sign information\n"); printf("MODULUS : %s\n", mod_str); printf("EXPONENT : %s\n", exp_str); printf("SIGNATURE : %s\n", sign_str); printf("Q1 : %s\n", q1_str); printf("Q2 : %s\n", q2_str); free(mod_str); free(exp_str); free(sign_str); unsigned char signer[32]; sha256(pubkey, KEY_LENGTH, signer, 0); char *signer_str = fmt_bytes(pubkey, 32); printf("# hash of public key\n"); printf("MRSIGNER : %s\n", signer_str);*/ }