static int ctr_rsa_key_init(ctr_rsa_context* ctx ) { int ret; mpi P1, Q1; mpi_init( &P1, &Q1, NULL ); MPI_CHK( mpi_sub_int( &P1, &ctx->rsa.P, 1 ) ); MPI_CHK( mpi_sub_int( &Q1, &ctx->rsa.Q, 1 ) ); /* * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MPI_CHK( mpi_mod_mpi( &ctx->rsa.DP, &ctx->rsa.D, &P1 ) ); MPI_CHK( mpi_mod_mpi( &ctx->rsa.DQ, &ctx->rsa.D, &Q1 ) ); MPI_CHK( mpi_inv_mod( &ctx->rsa.QP, &ctx->rsa.Q, &ctx->rsa.P ) ); cleanup: mpi_free(&Q1, &P1, NULL ); if( ret != 0 ) { rsa_free( &ctx->rsa ); return( POLARSSL_ERR_RSA_KEY_GEN_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( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; if( ctx->Vf.p != NULL ) { /* We already have blinding values, just update them by squaring */ MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); return( 0 ); } /* Unblinding value: Vf = random number */ MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); /* Mathematically speaking, the algorithm should check Vf * against 0, P and Q (Vf should be relatively prime to N, and 0 < Vf < N), * so that Vf^-1 exists. */ /* Blinding value: Vi = Vf^(-e) mod N */ MPI_CHK( mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); MPI_CHK( mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); cleanup: return( ret ); }
/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int nbits, int exponent, ulong (*rng_fn)(void *), void *rng_st ) { int ret; mpi P1, Q1, H, G; 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_fn, rng_st ) ); CHK( mpi_gen_prime( &ctx->Q, nbits, 0, rng_fn, rng_st ) ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mpi_swap( &ctx->P, &ctx->Q ); 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_KEYGEN_FAILED | ret ); } return( 0 ); }
/* * Check a private RSA key */ int rsa_check_privkey( const rsa_context *ctx ) { int ret; mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) return( ret ); if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 ); mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ ); mpi_init( &QP ); MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); 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 ) ); MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); /* * Check for a valid PKCS1v2 private key */ if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || mpi_cmp_int( &L2, 0 ) != 0 || mpi_cmp_int( &I, 1 ) != 0 || mpi_cmp_int( &G, 1 ) != 0 ) { ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED; } cleanup: mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 ); mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ ); mpi_free( &QP ); if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED ) return( ret ); if( ret != 0 ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret ); return( 0 ); }
/* Generate an RSA keypair */ int rsa_gen_key(rsa_context *ctx, int nbits, int exponent) { mpi P1, Q1, H, G; int ret; if (ctx->f_rng == NULL || nbits < 128 || exponent < 3) { return EST_ERR_RSA_BAD_INPUT_DATA; } mpi_init(&P1, &Q1, &H, &G, NULL); /* 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, ctx->f_rng, ctx->p_rng)); MPI_CHK(mpi_gen_prime(&ctx->Q, (nbits + 1) >> 1, 0, ctx->f_rng, ctx->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(&G, &H, &Q1, &P1, NULL); if (ret != 0) { rsa_free(ctx); return EST_ERR_RSA_KEY_GEN_FAILED | ret; } return 0; }
int rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, struct key_data *kd) { mpi P1, Q1, H; int r; int output_len; DEBUG_INFO ("RSA decrypt:"); DEBUG_WORD ((uint32_t)&output_len); mpi_init (&P1, &Q1, &H, NULL); rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_ctx.len = msg_len; DEBUG_WORD (msg_len); mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], KEY_CONTENT_LEN / 2); #if 0 /* Using CRT, we don't use N */ mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); #endif mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_mul_mpi (&H, &P1, &Q1); mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H); mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1); mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1); mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P); mpi_free (&P1, &Q1, &H, NULL); DEBUG_INFO ("RSA decrypt ..."); r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len, input, output, MAX_RES_APDU_DATA_SIZE); rsa_free (&rsa_ctx); if (r < 0) { DEBUG_INFO ("fail:"); DEBUG_SHORT (r); return r; } else { res_APDU_size = output_len; DEBUG_INFO ("done.\r\n"); GPG_SUCCESS (); return 0; } }
/* * Check a private RSA key */ int rsa_check_privkey( rsa_context *ctx ) { int ret; mpi PQ, DE, P1, Q1, H, I, G; if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) return( ret ); if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, NULL ); MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); 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_mod_mpi( &I, &DE, &H ) ); MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 && mpi_cmp_int( &I, 1 ) == 0 && mpi_cmp_int( &G, 1 ) == 0 ) { mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL ); return( 0 ); } cleanup: mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL ); return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret ); }
/* * 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( rsa_context *ctx, mpi *Vi, mpi *Vf, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, count = 0; #if defined(POLARSSL_THREADING_C) polarssl_mutex_lock( &ctx->mutex ); #endif if( ctx->Vf.p != NULL ) { /* We already have blinding values, just update them by squaring */ MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); goto done; } /* Unblinding value: Vf = random number, invertible mod N */ do { if( count++ > 10 ) return( POLARSSL_ERR_RSA_RNG_FAILED ); MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); MPI_CHK( mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); } while( mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); /* Blinding value: Vi = Vf^(-e) mod N */ MPI_CHK( mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); MPI_CHK( mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); done: if( Vi != &ctx->Vi ) { MPI_CHK( mpi_copy( Vi, &ctx->Vi ) ); MPI_CHK( mpi_copy( Vf, &ctx->Vf ) ); } cleanup: #if defined(POLARSSL_THREADING_C) polarssl_mutex_unlock( &ctx->mutex ); #endif return( ret ); }
int rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, struct key_data *kd) { mpi P1, Q1, H; int r; unsigned char temp[RSA_SIGNATURE_LENGTH]; mpi_init (&P1, &Q1, &H, NULL); rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_ctx.len = KEY_CONTENT_LEN; mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2); #if 0 /* Using CRT, we don't use N */ mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); #endif mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_mul_mpi (&H, &P1, &Q1); mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H); mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1); mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1); mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P); mpi_free (&P1, &Q1, &H, NULL); DEBUG_INFO ("RSA sign..."); r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW, msg_len, raw_message, temp); memcpy (output, temp, RSA_SIGNATURE_LENGTH); rsa_free (&rsa_ctx); if (r < 0) { DEBUG_INFO ("fail:"); DEBUG_SHORT (r); return r; } else { res_APDU_size = RSA_SIGNATURE_LENGTH; DEBUG_INFO ("done.\r\n"); GPG_SUCCESS (); return 0; } }
/* * Do an RSA private key operation */ int rsa_private( rsa_context *ctx, unsigned char *input, unsigned char *output ) { int ret, olen; mpi T, T1, T2; //printf("RSA private key operation start\n"); mpi_init( &T, &T1, &T2, NULL ); MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { mpi_free( &T, NULL ); return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } #if 0 MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); #else /* * 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 ) ); #endif olen = ctx->len; MPI_CHK( mpi_write_binary( &T, output, olen ) ); cleanup: mpi_free( &T, &T1, &T2, NULL ); //printf("RSA private key operation end\n"); if( ret != 0 ) return( POLARSSL_ERR_RSA_PRIVATE_FAILED | ret ); return( 0 ); }
/* * Perform an RSA private key operation */ int rsa_private( rsa_context *ctx, unsigned char *input, int ilen, unsigned char *output, int *olen ) { int ret; mpi T, T1, T2; //if( ilen != ctx->len || olen != ctx->len ) // return( ERR_RSA_BAD_INPUT_DATA ); mpi_init( &T, &T1, &T2, NULL ); CHK( mpi_import( &T, input, ilen ) ); if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { mpi_free( &T, NULL ); return( ERR_RSA_BAD_INPUT_DATA ); } #if 0 CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); #else /* * faster decryption using the CRT * * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q */ CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P */ CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); /* * output = T2 + T * Q */ CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); CHK( mpi_add_mpi( &T, &T2, &T1 ) ); #endif CHK( mpi_export( &T, output, olen ) ); cleanup: mpi_free( &T, &T1, &T2, NULL ); if( ret != 0 ) return( ERR_RSA_PRIVATE_FAILED | ret ); return( 0 ); }
/* Do an RSA private key operation */ int rsa_private(rsa_context *ctx, uchar *input, uchar *output) { int ret, olen; mpi T, T1, T2; mpi_init(&T, &T1, &T2, NULL); MPI_CHK(mpi_read_binary(&T, input, ctx->len)); if (mpi_cmp_mpi(&T, &ctx->N) >= 0) { mpi_free(&T, NULL); return EST_ERR_RSA_BAD_INPUT_DATA; } // MOB - why ? #if 0 MPI_CHK(mpi_exp_mod(&T, &T, &ctx->D, &ctx->N, &ctx->RN)); #else /* 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)); #endif olen = ctx->len; MPI_CHK(mpi_write_binary(&T, output, olen)); cleanup: mpi_free(&T, &T1, &T2, NULL); if (ret != 0) return EST_ERR_RSA_PRIVATE_FAILED | ret; return 0; }
/* * Check a private RSA key */ int rsa_check_privkey( const rsa_context *ctx ) { int ret; mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2; if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) return( ret ); if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, &G2, &L1, &L2, NULL ); MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); 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 ) ); MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); /* * Check for a valid PKCS1v2 private key */ if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 && mpi_cmp_int( &L2, 0 ) == 0 && mpi_cmp_int( &I, 1 ) == 0 && mpi_cmp_int( &G, 1 ) == 0 ) { mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL ); return( 0 ); } cleanup: mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL ); return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret ); }
/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int (*f_rng)(void *), void *p_rng, 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, &Q1, &H, &G, NULL ); /* * 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( &G, &H, &Q1, &P1, NULL ); 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 ); }
/* * 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 ); }