diff --git a/ChangeLog b/ChangeLog index 50f910c13771236458fa56ddcdfb7a1e780ceb6e..f7e6eb226545c67b268785eaf439d1a188b38957 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2013-11-24 Niels Möller <nisse@lysator.liu.se> + + * testsuite/dsa-keygen-test.c (test_main): Test generating a + key with 224-bit q. + + * dsa-verify.c (_dsa_verify): Use _dsa_hash. + + * dsa-sign.c (_dsa_sign): Use _dsa_hash. Fix memory leak in + error case, spotted by Nikos. + + * dsa-keygen.c (dsa_generate_keypair): Allow q_bits == 224. + + * dsa-hash.c (_dsa_hash): New file and function. Allows digest + sizes not matching the bitsize of q. + * dsa.h (_dsa_hash): Declare it. + * Makefile.in (hogweed_SOURCES): Added dsa-hash.c. + 2013-11-23 Niels Möller <nisse@lysator.liu.se> * configure.ac: Check also for openssl/ecdsa.h. diff --git a/Makefile.in b/Makefile.in index 13acde64625cff7d88675c7f009d7137431d1694..05e6adeb7287ab7f388320c6baaaf374ff3d5fa7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -129,7 +129,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \ rsa-encrypt.c rsa-decrypt.c rsa-decrypt-tr.c \ rsa-keygen.c rsa-compat.c rsa-blind.c \ rsa2sexp.c sexp2rsa.c \ - dsa.c dsa-sign.c dsa-verify.c dsa-keygen.c \ + dsa.c dsa-sign.c dsa-verify.c dsa-keygen.c dsa-hash.c \ dsa-sha1-sign.c dsa-sha1-verify.c \ dsa-sha256-sign.c dsa-sha256-verify.c \ dsa2sexp.c sexp2dsa.c \ diff --git a/dsa-hash.c b/dsa-hash.c new file mode 100644 index 0000000000000000000000000000000000000000..f61cfd825ec9102abdf38bf18ea6961a4f67bac9 --- /dev/null +++ b/dsa-hash.c @@ -0,0 +1,47 @@ +/* dsa-hash.c */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Niels Möller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The nettle library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the nettle library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02111-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "dsa.h" + +#include "bignum.h" + +/* Convert hash value to an integer. The general description of DSA in + FIPS186-3 allows both larger and smaller q; in the the latter case, + the hash must be truncated to the right number of bits. */ +void +_dsa_hash (mpz_t h, unsigned bit_size, + size_t length, const uint8_t *digest) +{ + + if (length > (bit_size + 7) / 8) + length = (bit_size + 7) / 8; + + nettle_mpz_set_str_256_u(h, length, digest); + + if (8 * length > bit_size) + /* We got a few extra bits, at the low end. Discard them. */ + mpz_tdiv_q_2exp (h, h, 8*length - bit_size); +} diff --git a/dsa-keygen.c b/dsa-keygen.c index 1b84e4977b0a1239fee36e6ac4f8dfc57f82b4f4..0a9cf406d87774ce255b8e0f54db323a66b64dd3 100644 --- a/dsa-keygen.c +++ b/dsa-keygen.c @@ -36,7 +36,7 @@ #include "nettle-internal.h" -/* Valid sizes, according to FIPS 186-3 are (1024, 160), (2048. 224), +/* Valid sizes, according to FIPS 186-3 are (1024, 160), (2048, 224), (2048, 256), (3072, 256). Currenty, we use only q_bits of 160 or 256. */ int @@ -56,6 +56,7 @@ dsa_generate_keypair(struct dsa_public_key *pub, if (p_bits < DSA_SHA1_MIN_P_BITS) return 0; break; + case 224: case 256: if (p_bits < DSA_SHA256_MIN_P_BITS) return 0; diff --git a/dsa-sign.c b/dsa-sign.c index 93b3653046d818f45abc87185e1556fc44fb55af..2165ace7e163c4517a77c3853e9487215eba7864 100644 --- a/dsa-sign.c +++ b/dsa-sign.c @@ -46,14 +46,8 @@ _dsa_sign(const struct dsa_public_key *pub, mpz_t k; mpz_t h; mpz_t tmp; - - /* Require precise match of bitsize of q and hash size. The general - description of DSA in FIPS186-3 allows both larger and smaller q; - in the the latter case, the hash must be truncated to the right - number of bits. */ - if (mpz_sizeinbase(pub->q, 2) != 8 * digest_size) - return 0; - + int res; + /* Select k, 0<k<q, randomly */ mpz_init_set(tmp, pub->q); mpz_sub_ui(tmp, tmp, 1); @@ -68,23 +62,26 @@ _dsa_sign(const struct dsa_public_key *pub, /* Compute hash */ mpz_init(h); - nettle_mpz_set_str_256_u(h, digest_size, digest); + _dsa_hash (h, mpz_sizeinbase(pub->q, 2), digest_size, digest); /* Compute k^-1 (mod q) */ - if (!mpz_invert(k, k, pub->q)) + if (mpz_invert(k, k, pub->q)) + { + /* Compute signature s = k^-1 (h + xr) (mod q) */ + mpz_mul(tmp, signature->r, key->x); + mpz_fdiv_r(tmp, tmp, pub->q); + mpz_add(tmp, tmp, h); + mpz_mul(tmp, tmp, k); + mpz_fdiv_r(signature->s, tmp, pub->q); + res = 1; + } + else /* What do we do now? The key is invalid. */ - return 0; - - /* Compute signature s = k^-1 (h + xr) (mod q) */ - mpz_mul(tmp, signature->r, key->x); - mpz_fdiv_r(tmp, tmp, pub->q); - mpz_add(tmp, tmp, h); - mpz_mul(tmp, tmp, k); - mpz_fdiv_r(signature->s, tmp, pub->q); + res = 0; mpz_clear(k); mpz_clear(h); mpz_clear(tmp); - return 1; + return res; } diff --git a/dsa-verify.c b/dsa-verify.c index 8dac16d8ae75a912388a58f2bfd1b292c1cf90ee..89232e8feb66381a46bda41f64108301f8527008 100644 --- a/dsa-verify.c +++ b/dsa-verify.c @@ -45,9 +45,6 @@ _dsa_verify(const struct dsa_public_key *key, int res; - if (mpz_sizeinbase(key->q, 2) != 8 * digest_size) - return 0; - /* Check that r and s are in the proper range */ if (mpz_sgn(signature->r) <= 0 || mpz_cmp(signature->r, key->q) >= 0) return 0; @@ -71,7 +68,7 @@ _dsa_verify(const struct dsa_public_key *key, mpz_init(v); /* The message digest */ - nettle_mpz_set_str_256_u(tmp, digest_size, digest); + _dsa_hash (tmp, mpz_sizeinbase (key->q, 2), digest_size, digest); /* v = g^{w * h (mod q)} (mod p) */ mpz_mul(tmp, tmp, w); diff --git a/dsa.h b/dsa.h index b30f941d0c0d0f0e3e6f58d280e5302189835482..59ddbec24b70aaba168d94d4d7da5ba09a834641 100644 --- a/dsa.h +++ b/dsa.h @@ -62,6 +62,7 @@ extern "C" { #define dsa_public_key_from_der_iterator nettle_dsa_public_key_from_der_iterator #define dsa_openssl_private_key_from_der_iterator nettle_dsa_openssl_private_key_from_der_iterator #define dsa_openssl_private_key_from_der nettle_openssl_provate_key_from_der +#define _dsa_hash _nettle_dsa_hash #define _dsa_sign _nettle_dsa_sign #define _dsa_verify _nettle_dsa_verify @@ -272,6 +273,10 @@ dsa_openssl_private_key_from_der(struct dsa_public_key *pub, /* Internal functions. */ +void +_dsa_hash (mpz_t h, unsigned bit_size, + size_t length, const uint8_t *digest); + int _dsa_sign(const struct dsa_public_key *pub, const struct dsa_private_key *key, diff --git a/testsuite/dsa-keygen-test.c b/testsuite/dsa-keygen-test.c index a4db5994dd29c28ab6de8bdaf60d61697347a02a..d57c1107d71ffef227e61e5fce91f7577637c411 100644 --- a/testsuite/dsa-keygen-test.c +++ b/testsuite/dsa-keygen-test.c @@ -39,6 +39,15 @@ test_main(void) test_dsa_key(&pub, &key, 256); test_dsa256(&pub, &key, NULL); + ASSERT (dsa_generate_keypair(&pub, &key, + &lfib, + (nettle_random_func *) knuth_lfib_random, + NULL, verbose ? progress : NULL, + 2048, 224)); + + test_dsa_key(&pub, &key, 224); + test_dsa256(&pub, &key, NULL); + dsa_public_key_clear(&pub); dsa_private_key_clear(&key); }