aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2013-11-27 13:22:10 +0000
committerWerner Koch <[email protected]>2013-12-03 08:26:04 +0000
commitd0d72d98f34579213230b3febfebd2fd8dff272b (patch)
tree37f17efd808a5e1eccd2c5da760926e79003e4ba
parentUse blinding for the RSA secret operation. (diff)
downloadgnupg-d0d72d98f34579213230b3febfebd2fd8dff272b.tar.gz
gnupg-d0d72d98f34579213230b3febfebd2fd8dff272b.zip
Normalize the MPIs used as input to secret key functions.
* cipher/rsa.c (secret): Normalize the INPUT. (rsa_decrypt): Pass reduced data to secret. * cipher/elgamal.c (decrypt): Normalize A and B. * cipher/dsa.c (sign): Normalize HASH. -- mpi_normalize is in general not required because extra leading zeroes do not harm the computation. However, adding extra all zero limbs or padding with multiples of N may be useful in side-channel attacks. In particular they are used by the acoustic crypt-analysis. This is an extra pre-caution which alone would not be sufficient to mitigate the described attack. CVE-id: CVE-2013-4576 Signed-off-by: Werner Koch <[email protected]>
-rw-r--r--cipher/dsa.c6
-rw-r--r--cipher/elgamal.c3
-rw-r--r--cipher/rsa.c22
3 files changed, 25 insertions, 6 deletions
diff --git a/cipher/dsa.c b/cipher/dsa.c
index 69b7d1bff..e23f05cab 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -274,7 +274,7 @@ check_secret_key( DSA_secret_key *sk )
/****************
* Make a DSA signature from HASH and put it into r and s.
*
- * Without generating the k this function runs in
+ * Without generating the k this function runs in
* about 26ms on a 300 Mhz Mobile Pentium
*/
@@ -285,6 +285,8 @@ sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
MPI kinv;
MPI tmp;
+ mpi_normalize (hash);
+
/* select a random k with 0 < k < q */
k = gen_k( skey->q );
@@ -311,7 +313,7 @@ sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
/****************
* Returns true if the signature composed from R and S is valid.
*
- * Without the checks this function runs in
+ * Without the checks this function runs in
* about 31ms on a 300 Mhz Mobile Pentium
*/
static int
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index c3f086238..5143ecc8c 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -374,6 +374,9 @@ decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey )
{
MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
+ mpi_normalize (a);
+ mpi_normalize (b);
+
/* output = b/(a^x) mod p */
mpi_powm( t1, a, skey->x, skey->p );
mpi_invm( t1, t1, skey->p );
diff --git a/cipher/rsa.c b/cipher/rsa.c
index c52704c72..c4d5161cf 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -308,9 +308,14 @@ secret(MPI output, MPI input, RSA_secret_key *skey )
MPI m2 = mpi_alloc_secure (nlimbs);
MPI h = mpi_alloc_secure (nlimbs);
# ifdef USE_BLINDING
- MPI r = mpi_alloc_secure (nlimbs);
MPI bdata= mpi_alloc_secure (nlimbs);
+ MPI r = mpi_alloc_secure (nlimbs);
+# endif /* USE_BLINDING */
+
+ /* Remove superfluous leading zeroes from INPUT. */
+ mpi_normalize (input);
+# ifdef USE_BLINDING
/* Blind: bdata = (data * r^e) mod n */
randomize_mpi (r, mpi_get_nbits (skey->n), 0);
mpi_fdiv_r (r, r, skey->n);
@@ -338,8 +343,8 @@ secret(MPI output, MPI input, RSA_secret_key *skey )
mpi_add ( output, m1, h );
# ifdef USE_BLINDING
- /* Unblind: output = (output * r^(-1)) mod n */
mpi_free (bdata);
+ /* Unblind: output = (output * r^(-1)) mod n */
mpi_invm (r, r, skey->n);
mpi_mulm (output, output, r, skey->n);
mpi_free (r);
@@ -419,6 +424,7 @@ int
rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
{
RSA_secret_key sk;
+ MPI input;
if( algo != 1 && algo != 2 )
return G10ERR_PUBKEY_ALGO;
@@ -429,8 +435,16 @@ rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
sk.p = skey[3];
sk.q = skey[4];
sk.u = skey[5];
- *result = mpi_alloc_secure( mpi_get_nlimbs( sk.n ) );
- secret( *result, data[0], &sk );
+
+ /* Better make sure that there are no superfluous leading zeroes
+ in the input and it has not been padded using multiples of N.
+ This mitigates side-channel attacks (CVE-2013-4576). */
+ input = mpi_alloc (0);
+ mpi_normalize (data[0]);
+ mpi_fdiv_r (input, data[0], sk.n);
+ *result = mpi_alloc_secure (mpi_get_nlimbs (sk.n));
+ secret (*result, input, &sk);
+ mpi_free (input);
return 0;
}