Upstream-Status: Backport

Index: gnupg-1.4.7/cipher/dsa.c
===================================================================
--- gnupg-1.4.7.orig/cipher/dsa.c	2006-12-12 02:27:21.000000000 +0800
+++ gnupg-1.4.7/cipher/dsa.c	2014-01-23 11:30:17.300915919 +0800
@@ -287,6 +287,8 @@
     MPI kinv;
     MPI tmp;
 
+    mpi_normalize (hash);
+
     /* select a random k with 0 < k < q */
     k = gen_k( skey->q );
 
Index: gnupg-1.4.7/cipher/elgamal.c
===================================================================
--- gnupg-1.4.7.orig/cipher/elgamal.c	2006-12-12 03:08:05.000000000 +0800
+++ gnupg-1.4.7/cipher/elgamal.c	2014-01-23 11:30:17.300915919 +0800
@@ -376,6 +376,9 @@
 {
     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: gnupg-1.4.7/cipher/random.c
===================================================================
--- gnupg-1.4.7.orig/cipher/random.c	2006-11-03 18:09:39.000000000 +0800
+++ gnupg-1.4.7/cipher/random.c	2014-01-23 11:31:53.993495462 +0800
@@ -273,6 +273,18 @@
 }
 
 
+/* Randomize the MPI */ 
+void
+randomize_mpi (MPI mpi, size_t nbits, int level)
+{
+  unsigned char *buffer;
+
+  buffer = get_random_bits (nbits, level, mpi_is_secure (mpi));
+  mpi_set_buffer (mpi, buffer, (nbits+7)/8, 0);
+  xfree (buffer);
+}
+
+
 int
 random_is_faked()
 {
Index: gnupg-1.4.7/cipher/random.h
===================================================================
--- gnupg-1.4.7.orig/cipher/random.h	2006-02-09 19:29:29.000000000 +0800
+++ gnupg-1.4.7/cipher/random.h	2014-01-23 11:30:17.300915919 +0800
@@ -32,6 +32,7 @@
 int  random_is_faked(void);
 void random_disable_locking (void);
 void randomize_buffer( byte *buffer, size_t length, int level );
+void randomize_mpi (MPI mpi, size_t nbits, int level);
 byte *get_random_bits( size_t nbits, int level, int secure );
 void fast_random_poll( void );
 
Index: gnupg-1.4.7/cipher/rsa.c
===================================================================
--- gnupg-1.4.7.orig/cipher/rsa.c	2006-12-12 03:09:00.000000000 +0800
+++ gnupg-1.4.7/cipher/rsa.c	2014-01-23 11:35:04.330639125 +0800
@@ -301,9 +301,26 @@
 #if 0
     mpi_powm( output, input, skey->d, skey->n );
 #else
-    MPI m1   = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
-    MPI m2   = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
-    MPI h    = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
+    int nlimbs = mpi_get_nlimbs (skey->n)+1;
+    MPI m1   = mpi_alloc_secure (nlimbs);
+    MPI m2   = mpi_alloc_secure (nlimbs);
+    MPI h    = mpi_alloc_secure (nlimbs);
+# if 1
+    MPI bdata= mpi_alloc_secure (nlimbs);
+    MPI r    = mpi_alloc_secure (nlimbs);
+# endif
+
+    /* Remove superfluous leading zeroes from INPUT.  */
+    mpi_normalize (input);
+
+# if 1 
+    /* Blind:  bdata = (data * r^e) mod n   */
+    randomize_mpi (r, mpi_get_nbits (skey->n), 0);
+    mpi_fdiv_r (r, r, skey->n);
+    mpi_powm (bdata, r, skey->e, skey->n);
+    mpi_mulm (bdata, bdata, input, skey->n);
+    input = bdata;
+# endif
 
     /* m1 = c ^ (d mod (p-1)) mod p */
     mpi_sub_ui( h, skey->p, 1  );
@@ -321,8 +338,15 @@
     /* m = m2 + h * p */
     mpi_mul ( h, h, skey->p );
     mpi_add ( output, m1, h );
-    /* ready */
-    
+
+# if 1
+    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);
+# endif
+
     mpi_free ( h );
     mpi_free ( m1 );
     mpi_free ( m2 );
@@ -397,6 +421,7 @@
 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;
@@ -407,8 +432,14 @@
     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 );
+
+    /* 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;
 }
 
Index: gnupg-1.4.7/g10/gpgv.c
===================================================================
--- gnupg-1.4.7.orig/g10/gpgv.c	2006-12-13 19:25:04.000000000 +0800
+++ gnupg-1.4.7/g10/gpgv.c	2014-01-23 11:30:17.300915919 +0800
@@ -390,6 +390,7 @@
 void random_dump_stats(void) {}
 int quick_random_gen( int onoff ) { return -1;}
 void randomize_buffer( byte *buffer, size_t length, int level ) {}
+void randomize_mpi (MPI mpi, size_t nbits, int level) {}
 int random_is_faked() { return -1;}
 byte *get_random_bits( size_t nbits, int level, int secure ) { return NULL;}
 void set_random_seed_file( const char *name ) {}
