Skip to content

Commit 3827fb0

Browse files
bors[bot]jack-fortanixJethro Beekman
authored
Merge #90 #91 #94
90: Fix ECDSA side channel r=jethrogb a=jack-fortanix Backport of ARMmbed/mbed-crypto@247c4d3 which addresses the attack described in https://eprint.iacr.org/2020/055.pdf 91: Parse RSA CRT parameters from PKCS1 private keys r=jethrogb a=jack-fortanix Currently they are ignored in the serialized key and then regenerated from P/Q/D. But that exposes key loading to a side channel attack on the modular inversion and GCD bignum functions when QP is computed. [And probably similar issues for DP/DQ during the division step but no attack there has been published yet.] Also this reduces computational overhead of loading RSA private keys from memory which will be nice for us in roche. Backport of ARMmbed/mbed-crypto#352 94: Fix docs on macro invocations r=jethrogb a=jethrogb Co-authored-by: Jack Lloyd <[email protected]> Co-authored-by: Jethro Beekman <[email protected]>
4 parents 2087951 + 13b4326 + a2caae2 + 1bf3312 commit 3827fb0

File tree

6 files changed

+62
-16
lines changed

6 files changed

+62
-16
lines changed

mbedtls-sys/vendor/library/ecdsa.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
358358
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
359359
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
360360
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
361+
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) ); // CVE-2019-18222
361362
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
362363
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
363364
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );

mbedtls-sys/vendor/library/pkparse.c

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

771-
/* Complete the RSA private key */
772-
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
773-
goto cleanup;
771+
#if !defined(MBEDTLS_RSA_NO_CRT)
772+
/*
773+
* The RSA CRT parameters DP, DQ and QP are nominally redundant, in
774+
* that they can be easily recomputed from D, P and Q. However by
775+
* parsing them from the PKCS1 structure it is possible to avoid
776+
* recalculating them which both reduces the overhead of loading
777+
* RSA private keys into memory and also avoids side channels which
778+
* can arise when computing those values, since all of D, P, and Q
779+
* are secret. See https://eprint.iacr.org/2020/055 for a
780+
* description of one such attack.
781+
*/
782+
783+
/* Import DP */
784+
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0)
785+
goto cleanup;
786+
787+
/* Import DQ */
788+
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0)
789+
goto cleanup;
790+
791+
/* Import QP */
792+
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0)
793+
goto cleanup;
774794

775-
/* Check optional parameters */
795+
#else
796+
/* Verify existance of the CRT params */
776797
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
777798
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
778799
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
800+
goto cleanup;
801+
#endif
802+
803+
/* Complete the RSA private key */
804+
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
779805
goto cleanup;
780806

781807
if( p != end )

mbedtls-sys/vendor/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 );

mbedtls/src/pk/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,10 @@ impl Pk {
315315
.is_ok()
316316
}
317317

318-
/// Key length in bits
319-
getter!(len() -> usize = fn pk_get_bitlen);
318+
getter!(
319+
/// Key length in bits
320+
len() -> usize = fn pk_get_bitlen
321+
);
320322
getter!(pk_type() -> Type = fn pk_get_type);
321323

322324
pub fn curve(&self) -> Result<EcGroupId> {

mbedtls/src/ssl/config.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,15 @@ impl<'c> Config<'c> {
214214
};
215215
}
216216

217-
/// Client only: whether to remember and use session tickets
218-
setter!(set_session_tickets(u: UseSessionTickets) = ssl_conf_session_tickets);
219-
220-
/// Client only: minimal FFDH group size
221-
setter!(set_ffdh_min_bitlen(bitlen: c_uint) = ssl_conf_dhm_min_bitlen);
217+
setter!(
218+
/// Client only: whether to remember and use session tickets
219+
set_session_tickets(u: UseSessionTickets) = ssl_conf_session_tickets
220+
);
221+
222+
setter!(
223+
/// Client only: minimal FFDH group size
224+
set_ffdh_min_bitlen(bitlen: c_uint) = ssl_conf_dhm_min_bitlen
225+
);
222226

223227
// TODO: The lifetime restrictions on HandshakeContext here are too strict.
224228
// Once we need something else, we might fix it.

mbedtls/src/wrapper_macros.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ macro_rules! define_struct {
227227
}
228228

229229
macro_rules! setter {
230-
{ $rfn:ident($n:ident : $rty:ty) = $cfn:ident } => {
230+
{ $(#[$m:meta])* $rfn:ident($n:ident : $rty:ty) = $cfn:ident } => {
231+
$(#[$m])*
231232
pub fn $rfn(&mut self, $n: $rty) {
232233
unsafe{::mbedtls_sys::$cfn(&mut self.inner,$n.into())}
233234
}
@@ -236,9 +237,10 @@ macro_rules! setter {
236237

237238
// can't make this work without as as_XXX! macro, and there is no as_method!...
238239
macro_rules! setter_callback {
239-
{ $s:ident<$l:tt>::$rfn:ident($n:ident : $($rty:tt)+) = $cfn:ident } => {
240+
{ $(#[$m:meta])* $s:ident<$l:tt>::$rfn:ident($n:ident : $($rty:tt)+) = $cfn:ident } => {
240241
as_item!(
241242
impl<$l> $s<$l> {
243+
$(#[$m])*
242244
pub fn $rfn<F: $($rty)+>(&mut self, $n: Option<&$l mut F>) {
243245
unsafe{::mbedtls_sys::$cfn(
244246
&mut self.inner,
@@ -252,12 +254,14 @@ macro_rules! setter_callback {
252254
}
253255

254256
macro_rules! getter {
255-
{ $rfn:ident() -> $rty:ty = .$cfield:ident } => {
257+
{ $(#[$m:meta])* $rfn:ident() -> $rty:ty = .$cfield:ident } => {
258+
$(#[$m])*
256259
pub fn $rfn(&self) -> $rty {
257260
self.inner.$cfield.into()
258261
}
259262
};
260-
{ $rfn:ident() -> $rty:ty = fn $cfn:ident } => {
263+
{ $(#[$m:meta])* $rfn:ident() -> $rty:ty = fn $cfn:ident } => {
264+
$(#[$m])*
261265
pub fn $rfn(&self) -> $rty {
262266
unsafe{::mbedtls_sys::$cfn(&self.inner).into()}
263267
}

0 commit comments

Comments
 (0)