Normalize the MPIs used as input to secret key functions.
authorWerner Koch <wk@gnupg.org>
Wed, 27 Nov 2013 13:22:10 +0000 (14:22 +0100)
committerWerner Koch <wk@gnupg.org>
Tue, 3 Dec 2013 08:26:04 +0000 (09:26 +0100)
* 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 <wk@gnupg.org>
cipher/dsa.c
cipher/elgamal.c
cipher/rsa.c

index 69b7d1b..e23f05c 100644 (file)
@@ -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
index c3f0862..5143ecc 100644 (file)
@@ -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 );
index c52704c..c4d5161 100644 (file)
@@ -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;
 }