aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-08-11 14:15:40 +0000
committerWerner Koch <[email protected]>2015-02-11 19:04:58 +0000
commitff53cf06e966dce0daba5f2c84e03ab9db2c3c8b (patch)
tree366398a4810df35f9a5526638dc266f50b1c4e4e
parentUpdate automake helper files. (diff)
downloadgnupg-ff53cf06e966dce0daba5f2c84e03ab9db2c3c8b.tar.gz
gnupg-ff53cf06e966dce0daba5f2c84e03ab9db2c3c8b.zip
Use ciphertext blinding for Elgamal decryption.
* cipher/elgamal.c (USE_BLINDING): New. (decrypt): Rewrite to use ciphertext blinding. -- CVE-id: CVE-2014-3591 As a countermeasure to a new side-channel attacks on sliding windows exponentiation we blind the ciphertext for Elgamal decryption. This is similar to what we are doing with RSA. Unfortunately, the performance impact of Elgamal blinding is quite noticeable: For a 3072 bit Elgamal key the decryption used to take 13ms; with the blinding it takes 24ms. This has been measured using time(1), calling gpg with a 100 byte message, and having gpg modified to run the pubkey_decrypt function 100 times and finally scale the result (using an i5-2410M CPU @ 2.30GHz TP 220).
-rw-r--r--cipher/elgamal.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 5143ecc8c..2ec52179a 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -31,6 +31,11 @@
#include "cipher.h"
#include "elgamal.h"
+/* Blinding is used to mitigate side-channel attacks. You may undef
+ this to speed up the operation in case the system is secured
+ against physical and network mounted side-channel attacks. */
+#define USE_BLINDING 1
+
typedef struct {
MPI p; /* prime */
MPI g; /* group generator */
@@ -372,25 +377,55 @@ do_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey )
static void
decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey )
{
- MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
+ MPI t1, t2, r;
+ unsigned int nbits = mpi_get_nbits (skey->p);
+
+ mpi_normalize (a);
+ mpi_normalize (b);
+
+ t1 = mpi_alloc_secure (mpi_nlimb_hint_from_nbits (nbits));
+#ifdef USE_BLINDING
+
+ t2 = mpi_alloc_secure (mpi_nlimb_hint_from_nbits (nbits));
+ r = mpi_alloc (mpi_nlimb_hint_from_nbits (nbits));
+
+ /* We need a random number of about the prime size. The random
+ number merely needs to be unpredictable; thus we use level 0. */
+ randomize_mpi (r, nbits, 0);
+
+ /* t1 = r^x mod p */
+ mpi_powm (t1, r, skey->x, skey->p);
+ /* t2 = (a * r)^-x mod p */
+ mpi_mulm (t2, a, r, skey->p);
+ mpi_powm (t2, t2, skey->x, skey->p);
+ mpi_invm (t2, t2, skey->p);
+ /* t1 = (t1 * t2) mod p*/
+ mpi_mulm (t1, t1, t2, skey->p);
- mpi_normalize (a);
- mpi_normalize (b);
+ mpi_free (r);
+ mpi_free (t2);
+
+#else /*!USE_BLINDING*/
+
+ /* output = b/(a^x) mod p */
+ mpi_powm (t1, a, skey->x, skey->p);
+ mpi_invm (t1, t1, skey->p);
+
+#endif /*!USE_BLINDING*/
+
+ mpi_mulm (output, b, t1, skey->p);
- /* output = b/(a^x) mod p */
- mpi_powm( t1, a, skey->x, skey->p );
- mpi_invm( t1, t1, skey->p );
- mpi_mulm( output, b, t1, skey->p );
#if 0
- if( DBG_CIPHER ) {
- log_mpidump("elg decrypted x= ", skey->x);
- log_mpidump("elg decrypted p= ", skey->p);
- log_mpidump("elg decrypted a= ", a);
- log_mpidump("elg decrypted b= ", b);
- log_mpidump("elg decrypted M= ", output);
+ if (DBG_CIPHER)
+ {
+ log_mpidump("elg decrypted x= ", skey->x);
+ log_mpidump("elg decrypted p= ", skey->p);
+ log_mpidump("elg decrypted a= ", a);
+ log_mpidump("elg decrypted b= ", b);
+ log_mpidump("elg decrypted M= ", output);
}
#endif
- mpi_free(t1);
+ mpi_free (t1);
}