Skip to content

Commit 32b6e69

Browse files
jack-fortanixsimonbutcher
authored andcommitted
Parse RSA parameters DP, DQ and QP from PKCS1 private keys
Otherwise these values are recomputed in mbedtls_rsa_deduce_crt, which currently suffers from side channel issues in the computation of QP (see https://eprint.iacr.org/2020/055). By loading the pre-computed values not only is the side channel avoided, but runtime overhead of loading RSA keys is reduced. Discussion in ARMmbed/mbed-crypto#347 Backport of ARMmbed/mbed-crypto#352
1 parent 9a5c8d4 commit 32b6e69

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

library/pkparse.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -843,14 +843,40 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
843843
goto cleanup;
844844
p += len;
845845

846-
/* Complete the RSA private key */
847-
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
848-
goto cleanup;
846+
#if !defined(MBEDTLS_RSA_NO_CRT)
847+
/*
848+
* The RSA CRT parameters DP, DQ and QP are nominally redundant, in
849+
* that they can be easily recomputed from D, P and Q. However by
850+
* parsing them from the PKCS1 structure it is possible to avoid
851+
* recalculating them which both reduces the overhead of loading
852+
* RSA private keys into memory and also avoids side channels which
853+
* can arise when computing those values, since all of D, P, and Q
854+
* are secret. See https://eprint.iacr.org/2020/055 for a
855+
* description of one such attack.
856+
*/
857+
858+
/* Import DP */
859+
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0)
860+
goto cleanup;
861+
862+
/* Import DQ */
863+
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0)
864+
goto cleanup;
865+
866+
/* Import QP */
867+
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0)
868+
goto cleanup;
849869

850-
/* Check optional parameters */
870+
#else
871+
/* Verify existance of the CRT params */
851872
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
852873
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
853874
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
875+
goto cleanup;
876+
#endif
877+
878+
/* Complete the RSA private key */
879+
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
854880
goto cleanup;
855881

856882
if( p != end )

library/rsa.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
249249
{
250250
int ret = 0;
251251
int have_N, have_P, have_Q, have_D, have_E;
252+
#if !defined(MBEDTLS_RSA_NO_CRT)
253+
int have_DP, have_DQ, have_QP;
254+
#endif
252255
int n_missing, pq_missing, d_missing, is_pub, is_priv;
253256

254257
RSA_VALIDATE_RET( ctx != NULL );
@@ -259,6 +262,12 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
259262
have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
260263
have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
261264

265+
#if !defined(MBEDTLS_RSA_NO_CRT)
266+
have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 );
267+
have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 );
268+
have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 );
269+
#endif
270+
262271
/*
263272
* Check whether provided parameters are enough
264273
* to deduce all others. The following incomplete
@@ -324,7 +333,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
324333
*/
325334

326335
#if !defined(MBEDTLS_RSA_NO_CRT)
327-
if( is_priv )
336+
if( is_priv && ! ( have_DP && have_DQ && have_QP ) )
328337
{
329338
ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
330339
&ctx->DP, &ctx->DQ, &ctx->QP );

0 commit comments

Comments
 (0)