summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2013-02-20 11:27:24 +0100
committerNiels Möller <nisse@lysator.liu.se>2013-02-20 11:27:24 +0100
commitbf913c733da8b5e5d9f9e4cca5ed81b92237774d (patch)
treec24a14d4a0996b207d8f388ba18d5199a7308e6a
parentaaf431459847561bc8df7e31bfb62fe95cfc3382 (diff)
downloadnettle-bf913c733da8b5e5d9f9e4cca5ed81b92237774d.tar.gz
Implemented ECDSA key generation.
-rw-r--r--ChangeLog6
-rw-r--r--Makefile.in2
-rw-r--r--ecdsa-keygen.c51
-rw-r--r--testsuite/.gitignore1
-rw-r--r--testsuite/.test-rules.make3
-rw-r--r--testsuite/Makefile.in2
-rw-r--r--testsuite/ecdsa-keygen-test.c113
7 files changed, 176 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index fa11ddc4..fb9932a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2013-02-20 Niels Möller <nisse@lysator.liu.se>
+ * ecdsa-keygen.c (ecdsa_generate_keypair): New file and function.
+ * Makefile.in (hogweed_SOURCES): Added ecdsa-keygen.c.
+ * testsuite/ecdsa-keygen-test.c: New testcase.
+ * testsuite/Makefile.in (TS_HOGWEED_SOURCES): Added
+ ecdsa-keygen-test.c.
+
* nettle-internal.h (TMP_ALLOC): Added missing parentheses.
2013-02-18 Niels Möller <nisse@lysator.liu.se>
diff --git a/Makefile.in b/Makefile.in
index 958278df..a327b0bf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -133,7 +133,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
ecc-mul-g.c ecc-mul-a.c ecc-hash.c ecc-random.c \
ecc-point.c ecc-scalar.c \
ecc-ecdsa-sign.c ecdsa-sign.c \
- ecc-ecdsa-verify.c ecdsa-verify.c
+ ecc-ecdsa-verify.c ecdsa-verify.c ecdsa-keygen.c
HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
base16.h base64.h buffer.h camellia.h cast128.h \
diff --git a/ecdsa-keygen.c b/ecdsa-keygen.c
new file mode 100644
index 00000000..7f8a37f1
--- /dev/null
+++ b/ecdsa-keygen.c
@@ -0,0 +1,51 @@
+/* ecdsa-keygen.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.
+ */
+
+/* Development of Nettle's ECC support was funded by Internetfonden. */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "ecdsa.h"
+#include "ecc-internal.h"
+#include "nettle-internal.h"
+
+void
+ecdsa_generate_keypair (struct ecc_point *pub,
+ struct ecc_scalar *key,
+ void *random_ctx, nettle_random_func *random)
+{
+ TMP_DECL(p, mp_limb_t, 3*ECC_MAX_SIZE + ECC_MUL_G_ITCH (ECC_MAX_SIZE));
+ mp_size_t itch = 3*pub->ecc->size + ECC_MUL_G_ITCH (pub->ecc->size);
+
+ assert (key->ecc == pub->ecc);
+
+ TMP_ALLOC (p, itch);
+
+ ecc_modq_random (key->ecc, key->p, random_ctx, random, p);
+ ecc_mul_g (pub->ecc, p, key->p, p + 3*pub->ecc->size);
+ ecc_j_to_a (pub->ecc, 1, pub->p, p, p + 3*pub->ecc->size);
+}
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index a5b83b51..642d8c42 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -23,6 +23,7 @@
/ecc-mul-a-test
/ecc-mul-g-test
/ecc-redc-test
+/ecdsa-keygen-test
/ecdsa-sign-test
/ecdsa-verify-test
/gcm-test
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index f23f2515..a935171d 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -181,6 +181,9 @@ ecdsa-sign-test$(EXEEXT): ecdsa-sign-test.$(OBJEXT)
ecdsa-verify-test$(EXEEXT): ecdsa-verify-test.$(OBJEXT)
$(LINK) ecdsa-verify-test.$(OBJEXT) $(TEST_OBJS) -o ecdsa-verify-test$(EXEEXT)
+ecdsa-keygen-test$(EXEEXT): ecdsa-keygen-test.$(OBJEXT)
+ $(LINK) ecdsa-keygen-test.$(OBJEXT) $(TEST_OBJS) -o ecdsa-keygen-test$(EXEEXT)
+
sha1-huge-test$(EXEEXT): sha1-huge-test.$(OBJEXT)
$(LINK) sha1-huge-test.$(OBJEXT) $(TEST_OBJS) -o sha1-huge-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 847c01d7..a155b447 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -37,7 +37,7 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
dsa-test.c dsa-keygen-test.c \
ecc-mod-test.c ecc-modinv-test.c ecc-redc-test.c \
ecc-mul-g-test.c ecc-mul-a-test.c \
- ecdsa-sign-test.c ecdsa-verify-test.c
+ ecdsa-sign-test.c ecdsa-verify-test.c ecdsa-keygen-test.c
TS_SOURCES = $(TS_NETTLE_SOURCES) $(TS_HOGWEED_SOURCES)
CXX_SOURCES = cxx-test.cxx
diff --git a/testsuite/ecdsa-keygen-test.c b/testsuite/ecdsa-keygen-test.c
new file mode 100644
index 00000000..375820c7
--- /dev/null
+++ b/testsuite/ecdsa-keygen-test.c
@@ -0,0 +1,113 @@
+#include "testutils.h"
+#include <nettle/knuth-lfib.h>
+
+/* Check if y^2 = x^3 - 3x + b */
+static int
+ecc_valid_p (struct ecc_point *pub)
+{
+ mpz_t t, x, y;
+ mpz_t lhs, rhs;
+ int res;
+ mp_size_t size;
+
+ size = pub->ecc->size;
+
+ /* First check range */
+ if (mpn_cmp (pub->p, pub->ecc->p, size) >= 0
+ || mpn_cmp (pub->p + size, pub->ecc->p, size) >= 0)
+ return 0;
+
+ mpz_init (lhs);
+ mpz_init (rhs);
+
+ _mpz_init_mpn (x, pub->p, size);
+ _mpz_init_mpn (y, pub->p + size, size);
+
+ mpz_mul (lhs, y, y);
+ mpz_mul (rhs, x, x);
+ mpz_sub_ui (rhs, rhs, 3);
+ mpz_mul (rhs, rhs, x);
+ mpz_add (rhs, rhs, _mpz_init_mpn (t, pub->ecc->b, size));
+
+ res = mpz_congruent_p (lhs, rhs, _mpz_init_mpn (t, pub->ecc->p, size));
+
+ mpz_clear (lhs);
+ mpz_clear (rhs);
+
+ return res;
+}
+
+void
+test_main (void)
+{
+ unsigned i;
+ struct knuth_lfib_ctx rctx;
+ struct dsa_signature signature;
+
+ struct tstring *digest;
+
+ knuth_lfib_init (&rctx, 4711);
+ dsa_signature_init (&signature);
+
+ digest = SHEX (/* sha256("abc") */
+ "BA7816BF 8F01CFEA 414140DE 5DAE2223"
+ "B00361A3 96177A9C B410FF61 F20015AD");
+
+ for (i = 0; ecc_curves[i]; i++)
+ {
+ const struct ecc_curve *ecc = ecc_curves[i];
+ struct ecc_point pub;
+ struct ecc_scalar key;
+
+ if (verbose)
+ fprintf (stderr, "Curve %d\n", ecc->bit_size);
+
+ ecc_point_init (&pub, ecc);
+ ecc_scalar_init (&key, ecc);
+
+ ecdsa_generate_keypair (&pub, &key,
+ &rctx,
+ (nettle_random_func *) knuth_lfib_random);
+
+ if (verbose)
+ {
+ gmp_fprintf (stderr,
+ "Public key:\nx = %Nx\ny = %Nx\n",
+ pub.p, ecc->size, pub.p + ecc->size, ecc->size);
+ gmp_fprintf (stderr,
+ "Private key: %Nx\n", key.p, ecc->size);
+ }
+ if (!ecc_valid_p (&pub))
+ die ("ecdsa_generate_keypair produced an invalid point.\n");
+
+ ecdsa_sign (&key,
+ &rctx, (nettle_random_func *) knuth_lfib_random,
+ digest->length, digest->data,
+ &signature);
+
+ if (!ecdsa_verify (&pub, digest->length, digest->data,
+ &signature))
+ die ("ecdsa_verify failed.\n");
+
+ digest->data[3] ^= 17;
+ if (ecdsa_verify (&pub, digest->length, digest->data,
+ &signature))
+ die ("ecdsa_verify returned success with invalid digest.\n");
+ digest->data[3] ^= 17;
+
+ mpz_combit (signature.r, 117);
+ if (ecdsa_verify (&pub, digest->length, digest->data,
+ &signature))
+ die ("ecdsa_verify returned success with invalid signature.r.\n");
+
+ mpz_combit (signature.r, 117);
+ mpz_combit (signature.s, 93);
+ if (ecdsa_verify (&pub, digest->length, digest->data,
+ &signature))
+ die ("ecdsa_verify returned success with invalid signature.s.\n");
+
+ ecc_point_clear (&pub);
+ ecc_scalar_clear (&key);
+ }
+ dsa_signature_clear (&signature);
+}