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
tries to continue the handshake after it failed (a misuse of the API).
(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
* 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;
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 )
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( ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, sig )
: rsa_private( ctx, f_rng, p_rng, sig, sig ) );
if( mode == RSA_PUBLIC )
return( 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 = 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 );
}
/*