int asn1_write_shmpi( unsigned char **p, unsigned char *start, shmpi *X ) { int ret; size_t len = 0; // Write the MPI // len = shmpi_size( X ); if( *p - start < (int) len ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); (*p) -= len; MPI_CHK( shmpi_write_binary( X, *p, len ) ); // DER format assumes 2s complement for numbers, so the leftmost bit // should be 0 for positive numbers and 1 for negative numbers. // if( X->s ==1 && **p & 0x80 ) { if( *p - start < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); *--(*p) = 0x00; len += 1; } ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); ret = (int) len; cleanup: return( ret ); }
/* * Do an RSA public key operation */ int shrsa_public( shrsa_context *ctx, const unsigned char *input, unsigned char *output ) { int ret; size_t olen; shmpi T; shmpi_init( &T ); MPI_CHK( shmpi_read_binary( &T, input, ctx->len ) ); if( shmpi_cmp_shmpi( &T, &ctx->N ) >= 0 ) { shmpi_free( &T ); return( RSA_ERR_RSA_BAD_INPUT_DATA ); } #if defined(RSA_THREADING_C) polarssl_mutex_lock( &ctx->mutex ); #endif olen = ctx->len; MPI_CHK( shmpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); MPI_CHK( shmpi_write_binary( &T, output, olen ) ); cleanup: #if defined(RSA_THREADING_C) polarssl_mutex_unlock( &ctx->mutex ); #endif shmpi_free( &T ); if( ret != 0 ) return( RSA_ERR_RSA_PUBLIC_FAILED + ret ); return( 0 ); }
/* * Do an RSA private key operation */ int shrsa_private( shrsa_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; shmpi T, T1, T2; shmpi *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(RSA_THREADING_C) shmpi Vi_copy, Vf_copy; shmpi_init( &Vi_copy ); shmpi_init( &Vf_copy ); Vi = &Vi_copy; Vf = &Vf_copy; #else Vi = &ctx->Vi; Vf = &ctx->Vf; #endif shmpi_init( &T ); shmpi_init( &T1 ); shmpi_init( &T2 ); MPI_CHK( shmpi_read_binary( &T, input, ctx->len ) ); if( shmpi_cmp_shmpi( &T, &ctx->N ) >= 0 ) { shmpi_free( &T ); return( RSA_ERR_RSA_BAD_INPUT_DATA ); } if( f_rng != NULL ) { /* * Blinding * T = T * Vi mod N */ MPI_CHK( shrsa_prepare_blinding( ctx, Vi, Vf, f_rng, p_rng ) ); MPI_CHK( shmpi_mul_shmpi( &T, &T, Vi ) ); MPI_CHK( shmpi_mod_shmpi( &T, &T, &ctx->N ) ); } #if defined(RSA_THREADING_C) polarssl_mutex_lock( &ctx->mutex ); #endif #if defined(RSA_RSA_NO_CRT) MPI_CHK( shmpi_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( shmpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); MPI_CHK( shmpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P */ MPI_CHK( shmpi_sub_shmpi( &T, &T1, &T2 ) ); MPI_CHK( shmpi_mul_shmpi( &T1, &T, &ctx->QP ) ); MPI_CHK( shmpi_mod_shmpi( &T, &T1, &ctx->P ) ); /* * T = T2 + T * Q */ MPI_CHK( shmpi_mul_shmpi( &T1, &T, &ctx->Q ) ); MPI_CHK( shmpi_add_shmpi( &T, &T2, &T1 ) ); #endif /* RSA_RSA_NO_CRT */ if( f_rng != NULL ) { /* * Unblind * T = T * Vf mod N */ MPI_CHK( shmpi_mul_shmpi( &T, &T, Vf ) ); MPI_CHK( shmpi_mod_shmpi( &T, &T, &ctx->N ) ); } olen = ctx->len; MPI_CHK( shmpi_write_binary( &T, output, olen ) ); cleanup: #if defined(RSA_THREADING_C) polarssl_mutex_unlock( &ctx->mutex ); shmpi_free( &Vi_copy ); shmpi_free( &Vf_copy ); #endif shmpi_free( &T ); shmpi_free( &T1 ); shmpi_free( &T2 ); if( ret != 0 ) return( RSA_ERR_RSA_PRIVATE_FAILED + ret ); return( 0 ); }