summaryrefslogtreecommitdiff
path: root/cipher/elgamal.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2015-02-23 11:39:58 +0100
committerWerner Koch <wk@gnupg.org>2015-02-23 11:39:58 +0100
commit410d70bad9a650e3837055e36f157894ae49a57d (patch)
treee638c75e8241d52010eebbf41354eb00c884ad6c /cipher/elgamal.c
parent653a9fa1a3a4c35a4dc1841cb57d7e2a318f3288 (diff)
downloadlibgcrypt-410d70bad9a650e3837055e36f157894ae49a57d.tar.gz
cipher: 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. This patch is a backport of the GnuPG 1.4 commit ff53cf06e966dce0daba5f2c84e03ab9db2c3c8b. Unfortunately, the performance impact of Elgamal blinding is quite noticeable (i5-2410M CPU @ 2.30GHz TP 220): Algorithm generate 100*priv 100*public ------------------------------------------------ ELG 1024 bit - 100ms 90ms ELG 2048 bit - 330ms 350ms ELG 3072 bit - 660ms 790ms Algorithm generate 100*priv 100*public ------------------------------------------------ ELG 1024 bit - 150ms 90ms ELG 2048 bit - 520ms 360ms ELG 3072 bit - 1100ms 800ms Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'cipher/elgamal.c')
-rw-r--r--cipher/elgamal.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index cb3ca43a..4eb52d62 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -33,6 +33,12 @@
#include "pubkey-internal.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
{
gcry_mpi_t p; /* prime */
@@ -516,15 +522,45 @@ do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
static void
decrypt (gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey )
{
- gcry_mpi_t t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
+ gcry_mpi_t t1, t2, r;
+ unsigned int nbits = mpi_get_nbits (skey->p);
mpi_normalize (a);
mpi_normalize (b);
+ t1 = mpi_snew (nbits);
+
+#ifdef USE_BLINDING
+
+ t2 = mpi_snew (nbits);
+ r = mpi_new (nbits);
+
+ /* We need a random number of about the prime size. The random
+ number merely needs to be unpredictable; thus we use level 0. */
+ _gcry_mpi_randomize (r, nbits, GCRY_WEAK_RANDOM);
+
+ /* 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_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 );
- mpi_mulm( output, b, t1, skey->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);
+
#if 0
if( DBG_CIPHER )
{
@@ -535,7 +571,7 @@ decrypt (gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey )
log_mpidump ("elg decrypted M", output);
}
#endif
- mpi_free(t1);
+ mpi_free (t1);
}