diff options
author | Werner Koch <wk@gnupg.org> | 2013-09-07 10:06:46 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-09-08 11:25:58 +0200 |
commit | 6466db10fb22a4f24df4edad9c5cb33ec67321bd (patch) | |
tree | cf8bbffc0a1b22ac170c18efcbbf8d4c7864443e /agent/pksign.c | |
parent | scd: Suppress gcc warning about possible uninitialized use. (diff) | |
download | gnupg2-6466db10fb22a4f24df4edad9c5cb33ec67321bd.tar.xz gnupg2-6466db10fb22a4f24df4edad9c5cb33ec67321bd.zip |
Switch to deterministic DSA.
* agent/pksign.c (rfc6979_hash_algo_string): New.
(do_encode_dsa) [Libgcrypt >= 1.6]: Make use of RFC-6979.
--
Now that we have a good (and not NSA/NIST demanded ;-) specification
on how to use DSA without a random nonce, we take advantage of it and
thus avoid pitfalls related to a misbehaving RNG during signature
creation.
Note that OpenPGP has the option of using a longer hash algorithm but
truncated to what is suitable for the used DSA key size. The hash
used as input to RFC-6979 will also be one with an appropriate digest
length but not a truncated one. This is allowed by RFC-6979.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'agent/pksign.c')
-rw-r--r-- | agent/pksign.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/agent/pksign.c b/agent/pksign.c index 85187305c..ad783ce1b 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -1,5 +1,6 @@ /* pksign.c - public key signing (well, actually using a secret key) * Copyright (C) 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc. + * Copyright (C) 2013 Werner Koch * * This file is part of GnuPG. * @@ -111,6 +112,25 @@ get_dsa_qbits (gcry_sexp_t key) } +/* Return an appropriate hash algorithm to be used with RFC-6979 for a + message digest of length MDLEN. Although a fallback of SHA-256 is + used the current implementation in Libgcrypt will reject a hash + algorithm which does not match the length of the message. */ +static const char * +rfc6979_hash_algo_string (size_t mdlen) +{ + switch (mdlen) + { + case 20: return "sha1"; + case 28: return "sha224"; + case 32: return "sha256"; + case 48: return "sha384"; + case 64: return "sha512"; + default: return "sha256"; + } +} + + /* Encode a message digest for use with an DSA algorithm. */ static gpg_error_t do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, @@ -177,11 +197,20 @@ do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, if (mdlen > qbits/8) mdlen = qbits/8; - /* Create the S-expression. We need to convert to an MPI first - because we want an unsigned integer. Using %b directly is not - possible because libgcrypt assumes an mpi and uses - GCRYMPI_FMT_STD for parsing and thus possible yielding a negative - value. */ + /* Create the S-expression. If we are using Libgcrypt 1.6 we make + use of Deterministic DSA. Libgcrypt < 1.6 does not implement + RFC-6979 and also requires us to convert to an MPI because it + expects an unsigned integer. Using %b directly is not possible + because Libgcrypt assumes an MPI and uses GCRYMPI_FMT_STD for + parsing and thus possible yielding a negative value. */ +#if GCRYPT_VERSION_NUMBER >= 0x010600 /* Libgcrypt >= 1.6 */ + { + err = gcry_sexp_build (&hash, NULL, + "(data (flags rfc6979) (hash %s %b))", + rfc6979_hash_algo_string (mdlen), + (int)mdlen, md); + } +#else /* Libgcrypt < 1.6 */ { gcry_mpi_t mpi; @@ -193,6 +222,7 @@ do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, gcry_mpi_release (mpi); } } +#endif /* Libgcrypt < 1.6 */ if (!err) *r_hash = hash; return err; |