Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport 2.7: Parse RSA parameters DP, DQ and QP from PKCS1 private keys #3017

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ mbed TLS ChangeLog (Sorted per branch, date)

= mbed TLS 2.7.X branch released XXXX-XX-XX

Security
* To avoid a side channel vulnerability when parsing an RSA private key,
read all the CRT parameters from the DER structure rather than
reconstructing them. Found by Alejandro Cabrera Aldaya and Billy Bob
Brumley. Reported and fix contributed by Jack Lloyd.
ARMmbed/mbed-crypto#352

Bugfix
* Allow loading symlinked certificates. Fixes #3005. Reported and fixed
by Jonathan Bennett <JBennett@incomsystems.biz> via #3008.
Expand Down
34 changes: 30 additions & 4 deletions library/pkparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -754,14 +754,40 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
goto cleanup;
p += len;

/* Complete the RSA private key */
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
goto cleanup;
#if !defined(MBEDTLS_RSA_NO_CRT)
/*
* The RSA CRT parameters DP, DQ and QP are nominally redundant, in
* that they can be easily recomputed from D, P and Q. However by
* parsing them from the PKCS1 structure it is possible to avoid
* recalculating them which both reduces the overhead of loading
* RSA private keys into memory and also avoids side channels which
* can arise when computing those values, since all of D, P, and Q
* are secret. See https://eprint.iacr.org/2020/055 for a
* description of one such attack.
*/

/* Import DP */
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0)
goto cleanup;

/* Import DQ */
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0)
goto cleanup;

/* Import QP */
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0)
goto cleanup;

/* Check optional parameters */
#else
/* Verify existance of the CRT params */
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
goto cleanup;
#endif

/* Complete the RSA private key */
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
goto cleanup;

if( p != end )
Expand Down
8 changes: 7 additions & 1 deletion library/rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );

#if !defined(MBEDTLS_RSA_NO_CRT)
const int have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 );
const int have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 );
const int have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 );
#endif

/*
* Check whether provided parameters are enough
* to deduce all others. The following incomplete
Expand Down Expand Up @@ -316,7 +322,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
*/

#if !defined(MBEDTLS_RSA_NO_CRT)
if( is_priv )
if( is_priv && ! ( have_DP && have_DQ && have_QP ) )
{
ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP );
Expand Down