mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-01-23 05:01:12 +00:00
Verify the result of RSA private key operations
If RSA-CRT is used for signing, and if an attacker can cause a glitch in one of the two computations modulo P or Q, the difference between the faulty and the correct signature (which is not secret) will be divisible by P or Q, but not by both, allowing to recover the private key by taking the GCD with the public RSA modulus N. This is known as the Bellcore Glitch Attack. Verifying the RSA signature before handing it out is a countermeasure against it.
This commit is contained in:
parent
f936cb1c1b
commit
a5fa07958e
124
library/rsa.c
124
library/rsa.c
|
@ -773,16 +773,38 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
size_t olen;
|
size_t olen;
|
||||||
mbedtls_mpi T, T1, T2;
|
|
||||||
|
/* Temporary holding the result */
|
||||||
|
mbedtls_mpi T;
|
||||||
|
|
||||||
|
/* Temporaries holding P-1, Q-1 and the
|
||||||
|
* exponent blinding factor, respectively. */
|
||||||
mbedtls_mpi P1, Q1, R;
|
mbedtls_mpi P1, Q1, R;
|
||||||
#if defined(MBEDTLS_RSA_NO_CRT)
|
|
||||||
mbedtls_mpi D_blind;
|
#if !defined(MBEDTLS_RSA_NO_CRT)
|
||||||
mbedtls_mpi *D = &ctx->D;
|
/* Temporaries holding the results mod p resp. mod q. */
|
||||||
#else
|
mbedtls_mpi TP, TQ;
|
||||||
|
|
||||||
|
/* Temporaries holding the blinded exponents for
|
||||||
|
* the mod p resp. mod q computation (if used). */
|
||||||
mbedtls_mpi DP_blind, DQ_blind;
|
mbedtls_mpi DP_blind, DQ_blind;
|
||||||
|
|
||||||
|
/* Pointers to actual exponents to be used - either the unblinded
|
||||||
|
* or the blinded ones, depending on the presence of a PRNG. */
|
||||||
mbedtls_mpi *DP = &ctx->DP;
|
mbedtls_mpi *DP = &ctx->DP;
|
||||||
mbedtls_mpi *DQ = &ctx->DQ;
|
mbedtls_mpi *DQ = &ctx->DQ;
|
||||||
#endif
|
#else
|
||||||
|
/* Temporary holding the blinded exponent (if used). */
|
||||||
|
mbedtls_mpi D_blind;
|
||||||
|
|
||||||
|
/* Pointer to actual exponent to be used - either the unblinded
|
||||||
|
* or the blinded one, depending on the presence of a PRNG. */
|
||||||
|
mbedtls_mpi *D = &ctx->D;
|
||||||
|
#endif /* MBEDTLS_RSA_NO_CRT */
|
||||||
|
|
||||||
|
/* Temporaries holding the initial input and the double
|
||||||
|
* checked result; should be the same in the end. */
|
||||||
|
mbedtls_mpi I, C;
|
||||||
|
|
||||||
if( rsa_check_context( ctx, 1 /* private key checks */,
|
if( rsa_check_context( ctx, 1 /* private key checks */,
|
||||||
f_rng != NULL /* blinding y/n */ ) != 0 )
|
f_rng != NULL /* blinding y/n */ ) != 0 )
|
||||||
|
@ -790,8 +812,17 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
|
||||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R );
|
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
|
||||||
|
return( ret );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MPI Initialization */
|
||||||
|
mbedtls_mpi_init( &T );
|
||||||
|
|
||||||
|
mbedtls_mpi_init( &P1 );
|
||||||
|
mbedtls_mpi_init( &Q1 );
|
||||||
|
mbedtls_mpi_init( &R );
|
||||||
|
|
||||||
if( f_rng != NULL )
|
if( f_rng != NULL )
|
||||||
{
|
{
|
||||||
|
@ -803,12 +834,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(MBEDTLS_RSA_NO_CRT)
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ );
|
||||||
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
|
|
||||||
return( ret );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
mbedtls_mpi_init( &I );
|
||||||
|
mbedtls_mpi_init( &C );
|
||||||
|
|
||||||
|
/* End of MPI initialization */
|
||||||
|
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
|
||||||
if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
|
if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
|
||||||
{
|
{
|
||||||
|
@ -816,6 +850,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) );
|
||||||
|
|
||||||
if( f_rng != NULL )
|
if( f_rng != NULL )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -874,24 +910,25 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
|
||||||
/*
|
/*
|
||||||
* Faster decryption using the CRT
|
* Faster decryption using the CRT
|
||||||
*
|
*
|
||||||
* T1 = input ^ dP mod P
|
* TP = input ^ dP mod P
|
||||||
* T2 = input ^ dQ mod Q
|
* TQ = input ^ dQ mod Q
|
||||||
*/
|
*/
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, DP, &ctx->P, &ctx->RP ) );
|
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, DQ, &ctx->Q, &ctx->RQ ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) );
|
||||||
|
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* T = (T1 - T2) * (Q^-1 mod P) mod P
|
* T = (TP - TQ) * (Q^-1 mod P) mod P
|
||||||
*/
|
*/
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) );
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) );
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* T = T2 + T * Q
|
* T = TQ + T * Q
|
||||||
*/
|
*/
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) );
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) );
|
||||||
#endif /* MBEDTLS_RSA_NO_CRT */
|
#endif /* MBEDTLS_RSA_NO_CRT */
|
||||||
|
|
||||||
if( f_rng != NULL )
|
if( f_rng != NULL )
|
||||||
|
@ -904,6 +941,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify the result to prevent glitching attacks. */
|
||||||
|
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E,
|
||||||
|
&ctx->N, &ctx->RN ) );
|
||||||
|
if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 )
|
||||||
|
{
|
||||||
|
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
olen = ctx->len;
|
olen = ctx->len;
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
|
||||||
|
|
||||||
|
@ -913,8 +959,9 @@ cleanup:
|
||||||
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
|
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
|
mbedtls_mpi_free( &P1 );
|
||||||
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &R );
|
mbedtls_mpi_free( &Q1 );
|
||||||
|
mbedtls_mpi_free( &R );
|
||||||
|
|
||||||
if( f_rng != NULL )
|
if( f_rng != NULL )
|
||||||
{
|
{
|
||||||
|
@ -926,6 +973,15 @@ cleanup:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mbedtls_mpi_free( &T );
|
||||||
|
|
||||||
|
#if !defined(MBEDTLS_RSA_NO_CRT)
|
||||||
|
mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mbedtls_mpi_free( &C );
|
||||||
|
mbedtls_mpi_free( &I );
|
||||||
|
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
|
return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
|
||||||
|
|
||||||
|
@ -2222,7 +2278,8 @@ int mbedtls_rsa_self_test( int verbose )
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
mbedtls_printf( "failed\n" );
|
mbedtls_printf( "failed\n" );
|
||||||
|
|
||||||
return( 1 );
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
|
@ -2237,7 +2294,8 @@ int mbedtls_rsa_self_test( int verbose )
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
mbedtls_printf( "failed\n" );
|
mbedtls_printf( "failed\n" );
|
||||||
|
|
||||||
return( 1 );
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
|
@ -2250,7 +2308,8 @@ int mbedtls_rsa_self_test( int verbose )
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
mbedtls_printf( "failed\n" );
|
mbedtls_printf( "failed\n" );
|
||||||
|
|
||||||
return( 1 );
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
|
if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
|
||||||
|
@ -2258,7 +2317,8 @@ int mbedtls_rsa_self_test( int verbose )
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
mbedtls_printf( "failed\n" );
|
mbedtls_printf( "failed\n" );
|
||||||
|
|
||||||
return( 1 );
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
|
@ -2283,7 +2343,8 @@ int mbedtls_rsa_self_test( int verbose )
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
mbedtls_printf( "failed\n" );
|
mbedtls_printf( "failed\n" );
|
||||||
|
|
||||||
return( 1 );
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
|
@ -2296,7 +2357,8 @@ int mbedtls_rsa_self_test( int verbose )
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
mbedtls_printf( "failed\n" );
|
mbedtls_printf( "failed\n" );
|
||||||
|
|
||||||
return( 1 );
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( verbose != 0 )
|
if( verbose != 0 )
|
||||||
|
|
Loading…
Reference in a new issue