From 578517d459ff6772465befec567f68cb7dbf2212 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 22 Mar 2017 13:38:28 +0000 Subject: [PATCH 1/3] Add exponent blinding to RSA without CRT The sliding window exponentiation algorithm is vulnerable to side-channel attacks. As a countermeasure we add exponent blinding in order to prevent combining the results of different measurements. This commits handles the case when the Chinese Remainder Theorem is NOT used to accelerate computations. --- library/rsa.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index e83187526..3dc6055b7 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -23,6 +23,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(MBEDTLS_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,12 +388,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 ) @@ -390,13 +426,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 @@ -438,6 +493,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 ); From 9ef9f1099f44e1daa30985b074958bc297b237e2 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 22 Mar 2017 15:13:15 +0000 Subject: [PATCH 2/3] Add exponent blinding to RSA with CRT The sliding window exponentiation algorithm is vulnerable to side-channel attacks. As a countermeasure we add exponent blinding in order to prevent combining the results of different measurements. This commit handles the case when the Chinese Remainder Theorem is used to accelerate the computation. --- library/rsa.c | 59 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index 3dc6055b7..a4afb2a5d 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -388,10 +388,14 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, int ret; size_t olen; mbedtls_mpi T, T1, T2; + mbedtls_mpi P1, Q1, R; #if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi P1, Q1; - mbedtls_mpi D_blind, R; + mbedtls_mpi D_blind; mbedtls_mpi *D = &ctx->D; +#else + mbedtls_mpi DP_blind, DQ_blind; + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; #endif /* Make sure we have private key info, prevent possible misuse */ @@ -399,10 +403,18 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R ); + + + if( f_rng != NULL ) + { #if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); - mbedtls_mpi_init( &R ); mbedtls_mpi_init( &D_blind ); + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); #endif + } #if defined(MBEDTLS_THREADING_C) @@ -427,13 +439,13 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, 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 ) ); +#if defined(MBEDTLS_RSA_NO_CRT) /* * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D */ @@ -444,6 +456,28 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; #endif /* MBEDTLS_RSA_NO_CRT */ } @@ -456,8 +490,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P @@ -493,10 +527,17 @@ cleanup: #endif mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { #if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); - mbedtls_mpi_free( &R ); mbedtls_mpi_free( &D_blind ); + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); #endif + } if( ret != 0 ) return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); From 4477bcabc33593c4903aad44fa322cd6ff1b84e5 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 23 Mar 2017 10:41:56 +0000 Subject: [PATCH 3/3] Add Changelog entry for RSA exponent blinding --- ChangeLog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index fe5ce6535..15b555773 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ mbed TLS ChangeLog (Sorted per branch, date) += mbed TLS 2.1.x branch released xxxx-xx-xx + +Security + * Add exponent blinding to RSA private operations as a countermeasure + against side-channel attacks like the cache attack described in + https://arxiv.org/abs/1702.08719v2. + Found and fix proposed by Michael Schwarz, Samuel Weiser, Daniel Gruss, + Clémentine Maurice and Stefan Mangard. + = mbed TLS 2.1.7 branch released 2017-03-08 Security