Merge remote-tracking branch 'upstream-restricted/pr/360' into mbedtls-2.1-restricted-proposed
Conflicts:
* scripts/config.pl: reconciled parallel edits in a comment.
diff --git a/ChangeLog b/ChangeLog
index 0eb0702..b8ac52b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -17,6 +17,8 @@
implementation allowed an offline 2^80 brute force attack on the
HMAC key of a single, uninterrupted connection (with no
resumption of the session).
+ * Verify results of RSA private key operations to defend
+ against Bellcore glitch attack.
Features
* Extend PKCS#8 interface by introducing support for the entire SHA
@@ -51,6 +53,7 @@
structure. Do not assume that zeroizing a context is a correct way to
reset it. Found independently by ccli8 on Github.
* In mbedtls_entropy_free(), properly free the message digest context.
+ * Fix memory leak in RSA self test.
Changes
* Clarified the documentation of mbedtls_ssl_setup.
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 6b2e54b..8e34e62 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -220,7 +220,7 @@
* \brief Do an RSA private key operation
*
* \param ctx RSA context
- * \param f_rng RNG function (Needed for blinding)
+ * \param f_rng RNG function (used for blinding)
* \param p_rng RNG parameter
* \param input input buffer
* \param output output buffer
@@ -229,6 +229,18 @@
*
* \note The input and output buffers must be large
* enough (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note Blinding is used if and only if a PRNG is provided.
+ *
+ * \note If blinding is used, both the base of exponentation
+ * and the exponent are blinded, providing protection
+ * against some side-channel attacks.
+ *
+ * \warning It is deprecated and a security risk to not provide
+ * a PRNG here and thereby prevent the use of blinding.
+ * Future versions of the library may enforce the presence
+ * of a PRNG.
+ *
*/
int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
diff --git a/library/bignum.c b/library/bignum.c
index 25fe8be..165cf87 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1613,7 +1613,7 @@
mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
int neg;
- if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+ if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
diff --git a/library/rsa.c b/library/rsa.c
index d2bddf6..13beba4 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -403,9 +403,41 @@
mbedtls_mpi *DQ = &ctx->DQ;
#endif
+ /* Temporaries holding the initial input and the double
+ * checked result; should be the same in the end. */
+ mbedtls_mpi I, C;
+
/* Make sure we have private key info, prevent possible misuse */
- if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL )
+#if defined(MBEDTLS_RSA_NO_CRT)
+ if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->D, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->E, 0 ) == 0 ||
+ ( f_rng != NULL && mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) ||
+ ( f_rng != NULL && mbedtls_mpi_cmp_int( &ctx->Q, 0 ) == 0 ) )
+ {
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+ }
+#else /* ! MBEDTLS_RSA_NO_CRT */
+ if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->E, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->Q, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->DP, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) == 0 ||
+ mbedtls_mpi_cmp_int( &ctx->QP, 0 ) == 0 )
+ {
+ return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+ }
+#endif /* ! MBEDTLS_RSA_NO_CRT */
+
+
+#if defined(MBEDTLS_THREADING_C)
+ if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ mbedtls_mpi_init( &I );
+ mbedtls_mpi_init( &C );
mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R );
@@ -421,12 +453,6 @@
#endif
}
-
-#if defined(MBEDTLS_THREADING_C)
- if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
- return( ret );
-#endif
-
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{
@@ -434,6 +460,8 @@
goto cleanup;
}
+ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) );
+
if( f_rng != NULL )
{
/*
@@ -522,6 +550,15 @@
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
}
+ /* Verify the result to prevent glitching attacks. */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E,
+ &ctx->N, &ctx->RN ) );
+ if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 )
+ {
+ ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
+ goto cleanup;
+ }
+
olen = ctx->len;
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
@@ -544,6 +581,9 @@
#endif
}
+ mbedtls_mpi_free( &C );
+ mbedtls_mpi_free( &I );
+
if( ret != 0 )
return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
@@ -705,7 +745,7 @@
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
-
+
// first comparison checks for overflow
if( ilen + 11 < ilen || olen < ilen + 11 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1167,11 +1207,6 @@
size_t nb_pad, olen, oid_size = 0;
unsigned char *p = sig;
const char *oid = NULL;
- unsigned char *sig_try = NULL, *verif = NULL;
- size_t i;
- unsigned char diff;
- volatile unsigned char diff_no_optimize;
- int ret;
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1237,42 +1272,7 @@
if( mode == MBEDTLS_RSA_PUBLIC )
return( mbedtls_rsa_public( ctx, sig, sig ) );
- /*
- * In order to prevent Lenstra's attack, make the signature in a
- * temporary buffer and check it before returning it.
- */
- sig_try = mbedtls_calloc( 1, ctx->len );
- if( sig_try == NULL )
- return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-
- verif = mbedtls_calloc( 1, ctx->len );
- if( verif == NULL )
- {
- mbedtls_free( sig_try );
- return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
- }
-
- MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
- MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) );
-
- /* Compare in constant time just in case */
- for( diff = 0, i = 0; i < ctx->len; i++ )
- diff |= verif[i] ^ sig[i];
- diff_no_optimize = diff;
-
- if( diff_no_optimize != 0 )
- {
- ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
- goto cleanup;
- }
-
- memcpy( sig, sig_try, ctx->len );
-
-cleanup:
- mbedtls_free( sig_try );
- mbedtls_free( verif );
-
- return( ret );
+ return( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
}
#endif /* MBEDTLS_PKCS1_V15 */
@@ -1792,7 +1792,8 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( 1 );
+ ret = 1;
+ goto cleanup;
}
if( verbose != 0 )
@@ -1806,7 +1807,8 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( 1 );
+ ret = 1;
+ goto cleanup;
}
if( verbose != 0 )
@@ -1819,7 +1821,8 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( 1 );
+ ret = 1;
+ goto cleanup;
}
if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
@@ -1827,7 +1830,8 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( 1 );
+ ret = 1;
+ goto cleanup;
}
if( verbose != 0 )
@@ -1845,7 +1849,8 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( 1 );
+ ret = 1;
+ goto cleanup;
}
if( verbose != 0 )
@@ -1857,7 +1862,8 @@
if( verbose != 0 )
mbedtls_printf( "failed\n" );
- return( 1 );
+ ret = 1;
+ goto cleanup;
}
if( verbose != 0 )
diff --git a/scripts/config.pl b/scripts/config.pl
index 1464813..dcf0281 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -76,6 +76,11 @@
EOU
+# The following options are disabled instead of enabled with "full".
+# Notes:
+# - MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 and
+# MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION could be enabled if the
+# respective tests were adapted
my @excluded = qw(
MBEDTLS_DEPRECATED_REMOVED
MBEDTLS_HAVE_SSE2
@@ -87,6 +92,7 @@
MBEDTLS_NO_PLATFORM_ENTROPY
MBEDTLS_REMOVE_ARC4_CIPHERSUITES
MBEDTLS_SSL_HW_RECORD_ACCEL
+MBEDTLS_RSA_NO_CRT
MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
MBEDTLS_ZLIB_SUPPORT
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 9728bd5..f6b59db 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -478,6 +478,23 @@
msg "test: !MBEDTLS_SSL_RENEGOTIATION - ssl-opt.sh (ASan build)" # ~ 6 min
if_build_succeeded tests/ssl-opt.sh
+msg "build: Default + RSA_NO_CRT (ASan build)" # ~ 6 min
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl set MBEDTLS_RSA_NO_CRT
+CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+make
+
+msg "test: RSA_NO_CRT - main suites (inc. selftests) (ASan build)" # ~ 50s
+make test
+
+msg "test: RSA_NO_CRT - RSA-related part of ssl-opt.sh (ASan build)" # ~ 5s
+tests/ssl-opt.sh -f RSA
+
+msg "test: RSA_NO_CRT - RSA-related part of compat.sh (ASan build)" # ~ 3 min
+tests/compat.sh -t RSA
+
+
msg "build: cmake, full config, clang" # ~ 50s
cleanup
cp "$CONFIG_H" "$CONFIG_BAK"
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index f291c2a..f76cdce 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -43,16 +43,19 @@
const unsigned char *input, unsigned char *output,
size_t output_max_len )
{
- return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, NULL, NULL, mode, olen,
- input, output, output_max_len ) );
+ return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx,
+ rnd_std_rand, NULL, mode, olen,
+ input, output, output_max_len ) );
}
int mbedtls_rsa_sign_func( void *ctx,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
int mode, mbedtls_md_type_t md_alg, unsigned int hashlen,
const unsigned char *hash, unsigned char *sig )
{
- return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, mode,
- md_alg, hashlen, hash, sig ) );
+ ((void) f_rng);
+ ((void) p_rng);
+ return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, rnd_std_rand, NULL, mode,
+ md_alg, hashlen, hash, sig ) );
}
size_t mbedtls_rsa_key_len_func( void *ctx )
{