Add counter-measure against RSA-CRT attack

https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/

backport of a1cdcd2
This commit is contained in:
Manuel Pégourié-Gonnard 2015-09-03 20:03:15 +02:00
parent fa566e3545
commit 2bc4505f5d
2 changed files with 41 additions and 3 deletions

View file

@ -6,6 +6,9 @@ Security
* Fix possible client-side NULL pointer dereference (read) when the client * Fix possible client-side NULL pointer dereference (read) when the client
tries to continue the handshake after it failed (a misuse of the API). tries to continue the handshake after it failed (a misuse of the API).
(Found by GDS Labs using afl-fuzz.) (Found by GDS Labs using afl-fuzz.)
* Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5
signatures. (Found by Florian Weimer, Red Hat.)
https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/
Bugfix Bugfix
* Fix unused function warning when using MBEDTLS_MDx_ALT or * Fix unused function warning when using MBEDTLS_MDx_ALT or

View file

@ -919,6 +919,11 @@ int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
{ {
size_t nb_pad, olen; size_t nb_pad, olen;
unsigned char *p = sig; unsigned char *p = sig;
unsigned char *sig_try = NULL, *verif = NULL;
size_t i;
unsigned char diff;
volatile unsigned char diff_no_optimize;
int ret;
if( ctx->padding != RSA_PKCS_V15 ) if( ctx->padding != RSA_PKCS_V15 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
@ -1021,9 +1026,39 @@ int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
} }
return( ( mode == RSA_PUBLIC ) if( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, sig ) return( rsa_public( ctx, sig, sig ) );
: rsa_private( ctx, f_rng, p_rng, sig, sig ) );
/*
* In order to prevent Lenstra's attack, make the signature in a
* temporary buffer and check it before returning it.
*/
sig_try = malloc( ctx->len );
verif = malloc( ctx->len );
if( sig_try == NULL || verif == NULL )
return( POLARSSL_ERR_MPI_MALLOC_FAILED );
MPI_CHK( rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
MPI_CHK( 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 = POLARSSL_ERR_RSA_PRIVATE_FAILED;
goto cleanup;
}
memcpy( sig, sig_try, ctx->len );
cleanup:
free( sig_try );
free( verif );
return( ret );
} }
/* /*