diff --git a/library/rsa.c b/library/rsa.c index 79726c1b5..2cc1de189 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -24,6 +24,11 @@ * * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * */ #if !defined(POLARSSL_CONFIG_FILE) @@ -350,6 +355,27 @@ cleanup: return( ret ); } +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + /* * Do an RSA private key operation */ @@ -362,11 +388,23 @@ int rsa_private( rsa_context *ctx, int ret; size_t olen; mpi T, T1, T2; +#if defined(POLARSSL_RSA_NO_CRT) + mpi P1, Q1; + mpi D_blind, R; + mpi *D = &ctx->D; +#endif mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); + mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); +#if defined(POLARSSL_RSA_NO_CRT) + mpi_init( &P1 ); mpi_init( &Q1 ); + mpi_init( &R ); mpi_init( &D_blind ); +#endif + + #if defined(POLARSSL_THREADING_C) - if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + if( ( ret = mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif @@ -386,13 +424,32 @@ int rsa_private( rsa_context *ctx, 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 ) ); + +#if defined(POLARSSL_RSA_NO_CRT) + /* + * Exponent blinding + */ + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MPI_CHK( mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MPI_CHK( mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MPI_CHK( mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MPI_CHK( mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#endif /* POLARSSL_RSA_NO_CRT */ } #if defined(POLARSSL_RSA_NO_CRT) - MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); + MPI_CHK( mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); #else /* - * faster decryption using the CRT + * Faster decryption using the CRT * * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q @@ -434,6 +491,10 @@ cleanup: #endif mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); +#if defined(POLARSSL_RSA_NO_CRT) + mpi_free( &P1 ); mpi_free( &Q1 ); + mpi_free( &R ); mpi_free( &D_blind ); +#endif if( ret != 0 ) return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );