diff options
author | Werner Koch <[email protected]> | 2013-11-27 13:22:10 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2013-12-03 08:26:04 +0000 |
commit | d0d72d98f34579213230b3febfebd2fd8dff272b (patch) | |
tree | 37f17efd808a5e1eccd2c5da760926e79003e4ba | |
parent | Use blinding for the RSA secret operation. (diff) | |
download | gnupg-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.c | 6 | ||||
-rw-r--r-- | cipher/elgamal.c | 3 | ||||
-rw-r--r-- | cipher/rsa.c | 22 |
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; } |