From aab30c130c7d2dcf8c0096d35fcdad87f59ea1ca Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Fri, 30 Aug 2013 11:00:25 +0200
Subject: [PATCH] RSA blinding added for CRT operations
---
ChangeLog | 4 ++++
library/rsa.c | 33 +++++++++++++++++++++++++++------
2 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index ba4010211..9f24244dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -46,6 +46,10 @@ Bugfix
* zlib compression/decompression skipped on empty blocks
* Support for AIX header locations in net.c module
+Security
+ * RSA blinding on CRT operations to counter timing attacks
+ (found by Cyril Arnaud and Pierre-Alain Fouque)
+
= Version 1.2.8 released 2013-06-19
Features
* Parsing of PKCS#8 encrypted private key files
diff --git a/library/rsa.c b/library/rsa.c
index 2cb37423c..47884f96f 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -265,13 +265,15 @@ int rsa_private( rsa_context *ctx,
int ret;
size_t olen;
mpi T, T1, T2;
- ((void) f_rng);
- ((void) p_rng);
+ mpi A, X;
+
+ if( f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
+ mpi_init( &A ); mpi_init( &X );
MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
-
if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{
mpi_free( &T );
@@ -281,6 +283,16 @@ int rsa_private( rsa_context *ctx,
#if defined(POLARSSL_RSA_NO_CRT)
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
#else
+ /*
+ * RSA Blinding
+ * A = rnd MPI
+ * T = A^E * T mod N
+ */
+ MPI_CHK( mpi_fill_random( &A, ctx->len - 1, f_rng, p_rng ) );
+ MPI_CHK( mpi_exp_mod( &X, &A, &ctx->E, &ctx->N, NULL ) );
+ MPI_CHK( mpi_mul_mpi( &X, &X, &T ) );
+ MPI_CHK( mpi_mod_mpi( &T, &X, &ctx->N ) );
+
/*
* faster decryption using the CRT
*
@@ -298,10 +310,18 @@ int rsa_private( rsa_context *ctx,
MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
/*
- * output = T2 + T * Q
+ * X = T2 + T * Q
*/
MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
- MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
+ MPI_CHK( mpi_add_mpi( &X, &T2, &T1 ) );
+
+ /*
+ * Unblind
+ * T = X / A mod N
+ */
+ MPI_CHK( mpi_inv_mod( &A, &A, &ctx->N ) );
+ MPI_CHK( mpi_mul_mpi( &T, &X, &A ) );
+ MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
#endif
olen = ctx->len;
@@ -310,6 +330,7 @@ int rsa_private( rsa_context *ctx,
cleanup:
mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
+ mpi_free( &A ); mpi_free( &X );
if( ret != 0 )
return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
@@ -1410,7 +1431,7 @@ int rsa_self_test( int verbose )
sha1( rsa_plaintext, PT_LEN, sha1sum );
- if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, POLARSSL_MD_SHA1, 0,
+ if( rsa_pkcs1_sign( &rsa, myrand, NULL, RSA_PRIVATE, POLARSSL_MD_SHA1, 0,
sha1sum, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )