From: Daiki Ueno <du...@redhat.com>

This adds the dsa_sign_deterministic function that calculates
signature without requiring entropy source.  Instead, it uses the
deterministic construction described in RFC 6979, through
_dsa_compute_k.

Signed-off-by: Daiki Ueno <du...@redhat.com>
---
 Makefile.in              |   3 +-
 dsa-sign-deterministic.c | 107 ++++++++++++++++++++++++++++
 dsa.h                    |  12 ++++
 testsuite/dsa-test.c     | 148 ++++++++++++++++++++++++++++++++++++++-
 4 files changed, 268 insertions(+), 2 deletions(-)
 create mode 100644 dsa-sign-deterministic.c

diff --git a/Makefile.in b/Makefile.in
index 27cbf93f..38b2a9a6 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -188,7 +188,8 @@ hogweed_SOURCES = sexp.c sexp-format.c \
                  eddsa-hash.c eddsa-pubkey.c eddsa-sign.c eddsa-verify.c \
                  ed25519-sha512-pubkey.c \
                  ed25519-sha512-sign.c ed25519-sha512-verify.c \
-                 dsa-compute-k.c ecdsa-sign-deterministic.c
+                 dsa-compute-k.c ecdsa-sign-deterministic.c \
+                 dsa-sign-deterministic.c
 
 OPT_SOURCES = fat-x86_64.c fat-arm.c mini-gmp.c
 
diff --git a/dsa-sign-deterministic.c b/dsa-sign-deterministic.c
new file mode 100644
index 00000000..8c75b80f
--- /dev/null
+++ b/dsa-sign-deterministic.c
@@ -0,0 +1,107 @@
+/* dsa-sign-deterministic.c
+
+   Copyright (C) 2002, 2010 Niels Möller
+   Copyright (C) 2019 Red Hat, Inc.
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "dsa.h"
+#include "dsa-internal.h"
+#include "dsa-compute-k.h"
+
+#include "bignum.h"
+
+
+int
+dsa_sign_deterministic (const struct dsa_params *params,
+                       const mpz_t x,
+                       void *mac_ctx,
+                       nettle_hash_update_func *set_key,
+                       nettle_hash_update_func *update,
+                       nettle_hash_digest_func *digest,
+                       size_t digest_length,
+                       const uint8_t *digest_message,
+                       struct dsa_signature *signature)
+{
+  mpz_t k;
+  mpz_t h;
+  mpz_t tmp;
+  int res;
+
+  /* Check that p is odd, so that invalid keys don't result in a crash
+     inside mpz_powm_sec. */
+  if (mpz_even_p (params->p))
+    return 0;
+
+  /* Select k, 0<k<q, deterministically */
+  mpz_init(k);
+  _dsa_compute_k (mpz_limbs_write (k, mpz_size (params->q)),
+                 mpz_size (params->q),
+                 mpz_limbs_read (params->q),
+                 mpz_limbs_read (x),
+                 mac_ctx, set_key, update, digest,
+                 digest_length, digest_message);
+  mpz_limbs_finish (k, mpz_size (params->q));
+
+  /* Compute r = (g^k (mod p)) (mod q) */
+  mpz_init (tmp);
+  mpz_powm_sec(tmp, params->g, k, params->p);
+  mpz_fdiv_r(signature->r, tmp, params->q);
+
+  /* Compute hash */
+  mpz_init(h);
+  _dsa_hash (h, mpz_sizeinbase(params->q, 2), digest_length, digest_message);
+
+  /* Compute k^-1 (mod q) */
+  if (mpz_invert(k, k, params->q))
+    {
+      /* Compute signature s = k^-1 (h + xr) (mod q) */
+      mpz_mul(tmp, signature->r, x);
+      mpz_fdiv_r(tmp, tmp, params->q);
+      mpz_add(tmp, tmp, h);
+      mpz_mul(tmp, tmp, k);
+      mpz_fdiv_r(signature->s, tmp, params->q);
+      res = 1;
+    }
+  else
+    /* What do we do now? The key is invalid. */
+    res = 0;
+
+  mpz_clear(k);
+  mpz_clear(h);
+  mpz_clear(tmp);
+
+  return res;
+}
diff --git a/dsa.h b/dsa.h
index 553ef327..fddaea9d 100644
--- a/dsa.h
+++ b/dsa.h
@@ -47,6 +47,7 @@ extern "C" {
 #define dsa_signature_init nettle_dsa_signature_init
 #define dsa_signature_clear nettle_dsa_signature_clear
 #define dsa_sign nettle_dsa_sign
+#define dsa_sign_deterministic nettle_dsa_sign_deterministic
 #define dsa_verify nettle_dsa_verify
 #define dsa_generate_params nettle_dsa_generate_params
 #define dsa_generate_keypair nettle_dsa_generate_keypair
@@ -109,6 +110,17 @@ dsa_sign(const struct dsa_params *params,
         const uint8_t *digest,
         struct dsa_signature *signature);
 
+int
+dsa_sign_deterministic (const struct dsa_params *params,
+                       const mpz_t x,
+                       void *mac_ctx,
+                       nettle_hash_update_func *set_key,
+                       nettle_hash_update_func *update,
+                       nettle_hash_digest_func *digest,
+                       size_t digest_length,
+                       const uint8_t *digest_message,
+                       struct dsa_signature *signature);
+
 int
 dsa_verify(const struct dsa_params *params,
           const mpz_t y,
diff --git a/testsuite/dsa-test.c b/testsuite/dsa-test.c
index 9a80c967..dbc8d063 100644
--- a/testsuite/dsa-test.c
+++ b/testsuite/dsa-test.c
@@ -1,4 +1,57 @@
 #include "testutils.h"
+#include "hmac.h"
+#include "nettle-internal.h"
+
+static void
+test_dsa_sign_deterministic(const struct dsa_params *params,
+                           /* Private key */
+                           const char *sz,
+                           /* HMAC */
+                           void *mac_ctx,
+                           nettle_hash_update_func *set_key,
+                           nettle_hash_update_func *update,
+                           nettle_hash_digest_func *digest,
+                           /* Hash */
+                           const struct tstring *h,
+                           /* Expected signature */
+                           const char *r, const char *s)
+{
+  struct dsa_signature ref;
+  struct dsa_signature signature;
+  mpz_t z;
+
+  dsa_signature_init (&ref);
+  dsa_signature_init(&signature);
+
+  mpz_init_set_str (z, sz, 16);
+
+  ASSERT (dsa_sign_deterministic (params, z,
+                                 mac_ctx, set_key, update, digest,
+                                 h->length, h->data, &signature));
+
+  mpz_set_str (ref.r, r, 16);
+  mpz_set_str (ref.s, s, 16);
+
+  if (mpz_cmp (signature.r, ref.r) != 0
+      || mpz_cmp (signature.s, ref.s) != 0)
+    {
+      fprintf (stderr, "_dsa_sign failed\n");
+      fprintf (stderr, "r     = ");
+      mpz_out_str (stderr, 16, signature.r);
+      fprintf (stderr, "\ns     = ");
+      mpz_out_str (stderr, 16, signature.s);
+      fprintf (stderr, "\nref.r = ");
+      mpz_out_str (stderr, 16, ref.r);
+      fprintf (stderr, "\nref.s = ");
+      mpz_out_str (stderr, 16, ref.s);
+      fprintf (stderr, "\n");
+      abort();
+    }
+
+  dsa_signature_clear (&ref);
+  dsa_signature_clear (&signature);
+  mpz_clear (z);
+}
 
 void
 test_main(void)
@@ -7,6 +60,13 @@ test_main(void)
   struct dsa_private_key key;
   struct dsa_signature signature;
   struct dsa_params *params = (struct dsa_params *) &pub;
+  struct hmac_sha256_ctx hmac_sha256;
+  struct sha256_ctx hash_sha256;
+  uint8_t digest[NETTLE_MAX_HASH_DIGEST_SIZE];
+
+  sha256_init (&hash_sha256);
+  sha256_update (&hash_sha256, 6, (const uint8_t *)"sample");
+  sha256_digest (&hash_sha256, SHA256_DIGEST_SIZE, digest);
 
   dsa_public_key_init(&pub);
   dsa_private_key_init(&key);
@@ -877,7 +937,93 @@ test_main(void)
                       "bb7441c122f1dc2f9d0b0bc07f26ba29a35cdf0da846a9d8"
                       "eab405cbf8c8e77f"),
                  &signature);
-  
+
+  /* Test vectors from RFC 6979 */
+  mpz_set_str(pub.p,
+             "86f5ca03dcfeb225063ff830a0c769b9dd9d6153ad91d7ce"
+             "27f787c43278b447e6533b86b18bed6e8a48b784a14c252c"
+             "5be0dbf60b86d6385bd2f12fb763ed8873abfd3f5ba2e0a8"
+             "c0a59082eac056935e529daf7c610467899c77adedfc846c"
+             "881870b7b19b2b58f9be0521a17002e3bdd6b86685ee90b3"
+             "d9a1b02b782b1779", 16);
+  mpz_set_str(pub.q,
+             "996f967f6c8e388d9e28d01e205fba957a5698b1", 16);
+  mpz_set_str(pub.g,
+             "07b0f92546150b62514bb771e2a0c0ce387f03bda6c56b50"
+             "5209ff25fd3c133d89bbcd97e904e09114d9a7defdeadfc9"
+             "078ea544d2e401aeecc40bb9fbbf78fd87995a10a1c27cb7"
+             "789b594ba7efb5c4326a9fe59a070e136db77175464adca4"
+             "17be5dce2f40d10a46a3a3943f26ab7fd9c0398ff8c76ee0"
+             "a56826a8a88f1dbd", 16);
+  mpz_set_str(pub.y,
+             "5df5e01ded31d0297e274e1691c192fe5868fef9e19a8477"
+             "6454b100cf16f65392195a38b90523e2542ee61871c0440c"
+             "b87c322fc4b4d2ec5e1e7ec766e1be8d4ce935437dc11c3c"
+             "8fd426338933ebfe739cb3465f4d3668c5e473508253b1e6"
+             "82f65cbdc4fae93c2ea212390e54905a86e2223170b44eaa"
+             "7da5dd9ffcfb7f3b", 16);
+  test_dsa_sign_deterministic (params,
+                              "411602cb19a6ccc34494d79d98ef1e7ed5af25f7",
+                              &hmac_sha256,
+                              (nettle_hash_update_func *)hmac_sha256_set_key,
+                              (nettle_hash_update_func *)hmac_sha256_update,
+                              (nettle_hash_digest_func *)hmac_sha256_digest,
+                              tstring_data (SHA256_DIGEST_SIZE, digest), /* h 
*/
+                              "81f2f5850be5bc123c43f71a3033e9384611c545",
+                              "4cdd914b65eb6c66a8aaad27299bee6b035f5e89");
+
+  mpz_set_str(pub.p,
+             "9db6fb5951b66bb6fe1e140f1d2ce5502374161fd6538df1"
+             "648218642f0b5c48c8f7a41aadfa187324b87674fa1822b0"
+             "0f1ecf8136943d7c55757264e5a1a44ffe012e9936e00c1d"
+             "3e9310b01c7d179805d3058b2a9f4bb6f9716bfe6117c6b5"
+             "b3cc4d9be341104ad4a80ad6c94e005f4b993e14f091eb51"
+             "743bf33050c38de235567e1b34c3d6a5c0ceaa1a0f368213"
+             "c3d19843d0b4b09dcb9fc72d39c8de41f1bf14d4bb4563ca"
+             "28371621cad3324b6a2d392145bebfac748805236f5ca2fe"
+             "92b871cd8f9c36d3292b5509ca8caa77a2adfc7bfd77dda6"
+             "f71125a7456fea153e433256a2261c6a06ed3693797e7995"
+             "fad5aabbcfbe3eda2741e375404ae25b", 16);
+  mpz_set_str(pub.q,
+             "f2c3119374ce76c9356990b465374a17f23f9ed35089bd96"
+             "9f61c6dde9998c1f", 16);
+  mpz_set_str(pub.g,
+             "5c7ff6b06f8f143fe8288433493e4769c4d988ace5be25a0"
+             "e24809670716c613d7b0cee6932f8faa7c44d2cb24523da5"
+             "3fbe4f6ec3595892d1aa58c4328a06c46a15662e7eaa703a"
+             "1decf8bbb2d05dbe2eb956c142a338661d10461c0d135472"
+             "085057f3494309ffa73c611f78b32adbb5740c361c9f35be"
+             "90997db2014e2ef5aa61782f52abeb8bd6432c4dd097bc54"
+             "23b285dafb60dc364e8161f4a2a35aca3a10b1c4d203cc76"
+             "a470a33afdcbdd92959859abd8b56e1725252d78eac66e71"
+             "ba9ae3f1dd2487199874393cd4d832186800654760e1e34c"
+             "09e4d155179f9ec0dc4473f996bdce6eed1cabed8b6f116f"
+             "7ad9cf505df0f998e34ab27514b0ffe7", 16);
+  mpz_set_str(pub.y,
+             "667098c654426c78d7f8201eac6c203ef030d43605032c2f"
+             "1fa937e5237dbd949f34a0a2564fe126dc8b715c5141802c"
+             "e0979c8246463c40e6b6bdaa2513fa611728716c2e4fd53b"
+             "c95b89e69949d96512e873b9c8f8dfd499cc312882561ade"
+             "cb31f658e934c0c197f2c4d96b05cbad67381e7b768891e4"
+             "da3843d24d94cdfb5126e9b8bf21e8358ee0e0a30ef13fd6"
+             "a664c0dce3731f7fb49a4845a4fd8254687972a2d382599c"
+             "9bac4e0ed7998193078913032558134976410b89d2c171d1"
+             "23ac35fd977219597aa7d15c1a9a428e59194f75c721ebcb"
+             "cfae44696a499afa74e04299f132026601638cb87ab79190"
+             "d4a0986315da8eec6561c938996beadf", 16);
+  test_dsa_sign_deterministic (params,
+                              "69c7548c21d0dfea6b9a51c9ead4e27c33d3b3f1"
+                              "80316e5bcab92c933f0e4dbc",
+                              &hmac_sha256,
+                              (nettle_hash_update_func *)hmac_sha256_set_key,
+                              (nettle_hash_update_func *)hmac_sha256_update,
+                              (nettle_hash_digest_func *)hmac_sha256_digest,
+                              tstring_data (SHA256_DIGEST_SIZE, digest), /* h 
*/
+                              "eace8bdbbe353c432a795d9ec556c6d021f7a03f"
+                              "42c36e9bc87e4ac7932cc809",
+                              "7081e175455f9247b812b74583e9e94f9ea79bd6"
+                              "40dc962533b0680793a38d53");
+
   dsa_public_key_clear(&pub);
   dsa_private_key_clear(&key);
   dsa_signature_clear(&signature);
-- 
2.21.0

_______________________________________________
nettle-bugs mailing list
nettle-bugs@lists.lysator.liu.se
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to