diff --git a/library/rsa.c b/library/rsa.c index 40ef2a948..e29979bad 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -29,6 +29,11 @@ * [2] Handbook of Applied Cryptography - 1997, Chapter 8 * Menezes, van Oorschot and Vanstone * + * [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(MBEDTLS_CONFIG_FILE) @@ -356,6 +361,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 */ @@ -368,12 +394,22 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, int ret; size_t olen; mbedtls_mpi T, T1, T2; +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi P1, Q1; + mbedtls_mpi D_blind, R; + mbedtls_mpi *D = &ctx->D; +#endif /* Make sure we have private key info, prevent possible misuse */ if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); mbedtls_mpi_init( &D_blind ); +#endif + #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) @@ -396,13 +432,32 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ } #if defined(MBEDTLS_RSA_NO_CRT) - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_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 @@ -444,6 +499,10 @@ cleanup: #endif mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); mbedtls_mpi_free( &D_blind ); +#endif if( ret != 0 ) return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );