This is the set of patches to add secp256k1 support. They apply on top of curve448 patches, because they reuse ecc->dup field added in that patchset.
Dmitry Eremin-Solenikov (6): ecc: use dup fiels for all the curves eccdata: use 'a' coefficient eccdata: switch to using curve name instead of just bits ecc: include coefficient 'a' into the ecc_curve struct ecdsa-keygen-test: make use of ecc->a ecc: support secp256k1 curve
Makefile.in | 26 ++++++---- ecc-192.c | 1 + ecc-224.c | 1 + ecc-25519.c | 1 + ecc-256.c | 1 + ecc-384.c | 1 + ecc-521.c | 1 + ecc-curve.h | 1 + ecc-dup-jj-0.c | 108 ++++++++++++++++++++++++++++++++++++++++++ ecc-internal.h | 11 ++++- ecc-mul-a.c | 6 +-- ecc-mul-g.c | 2 +- eccdata.c | 103 +++++++++++++++++++++++++++++----------- testsuite/ecc-add-test.c | 2 +- testsuite/ecc-dup-test.c | 2 +- testsuite/ecdsa-keygen-test.c | 5 +- testsuite/testutils.c | 12 ++++- 17 files changed, 238 insertions(+), 46 deletions(-) create mode 100644 ecc-dup-jj-0.c
secp256k1 will use the same code, but slightly different dup function. Use indirection to make it possible to support secp256k1 curve.
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- ecc-mul-a.c | 6 +++--- ecc-mul-g.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/ecc-mul-a.c b/ecc-mul-a.c index cb9c7d418633..2ed9084cb829 100644 --- a/ecc-mul-a.c +++ b/ecc-mul-a.c @@ -76,7 +76,7 @@ ecc_mul_a (const struct ecc_curve *ecc, { int digit;
- ecc_dup_jj (ecc, r, r, scratch_out); + ecc->dup (ecc, r, r, scratch_out); ecc_add_jja (ecc, tp, r, pj, scratch_out);
digit = (w & bit) > 0; @@ -110,7 +110,7 @@ table_init (const struct ecc_curve *ecc,
for (j = 2; j < size; j += 2) { - ecc_dup_jj (ecc, TABLE(j), TABLE(j/2), scratch); + ecc->dup (ecc, TABLE(j), TABLE(j/2), scratch); ecc_add_jja (ecc, TABLE(j+1), TABLE(j), TABLE(1), scratch); } } @@ -168,7 +168,7 @@ ecc_mul_a (const struct ecc_curve *ecc, bits |= w >> shift; } for (j = 0; j < ECC_MUL_A_WBITS; j++) - ecc_dup_jj (ecc, r, r, scratch_out); + ecc->dup (ecc, r, r, scratch_out);
bits &= TABLE_MASK; sec_tabselect (tp, 3*ecc->p.size, table, TABLE_SIZE, bits); diff --git a/ecc-mul-g.c b/ecc-mul-g.c index c4a1b5bbab19..c588ca10ae29 100644 --- a/ecc-mul-g.c +++ b/ecc-mul-g.c @@ -64,7 +64,7 @@ ecc_mul_g (const struct ecc_curve *ecc, mp_limb_t *r,
for (i = k, is_zero = 1; i-- > 0; ) { - ecc_dup_jj (ecc, r, r, scratch); + ecc->dup (ecc, r, r, scratch); for (j = 0; j * c < bit_rows; j++) { unsigned bits;
In preparation of adding secp256k1, add proper support for an 'a' curve coefficient.
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- eccdata.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-)
diff --git a/eccdata.c b/eccdata.c index b13547419e3e..a1f5b1135ab2 100644 --- a/eccdata.c +++ b/eccdata.c @@ -53,13 +53,13 @@ struct ecc_point
enum ecc_type { - /* y^2 = x^3 - 3x + b (mod p) */ + /* y^2 = x^3 + a x + b (mod p) */ ECC_TYPE_WEIERSTRASS, #if 0 /* x^2 + y^2 = 1 - d x^2 y^2 */ ECC_TYPE_EDWARDS, #endif - /* -x^2 + y^2 = 1 - d x^2 y^2 */ + /* a x^2 + y^2 = 1 - d x^2 y^2 */ ECC_TYPE_TWISTED_EDWARDS, };
@@ -75,6 +75,8 @@ struct ecc_curve mpz_t p; mpz_t b;
+ int a; + /* Curve order */ mpz_t q; struct ecc_point g; @@ -168,11 +170,14 @@ ecc_dup (const struct ecc_curve *ecc, mpz_mul_ui (m, p->y, 2); mpz_invert (m, m, ecc->p);
- /* t = 3 (x^2 - 1) * m */ + /* t = (3 * x^2 + a) * m */ mpz_mul (t, p->x, p->x); mpz_mod (t, t, ecc->p); - mpz_sub_ui (t, t, 1); mpz_mul_ui (t, t, 3); + if (ecc->a > 0) + mpz_add_ui (t, t, ecc->a); + else + mpz_sub_ui (t, t, -ecc->a);
mpz_mul (t, t, m); mpz_mod (t, t, ecc->p); @@ -296,10 +301,14 @@ ecc_add (const struct ecc_curve *ecc, struct ecc_point *r, mpz_mul (x, x, s); mpz_mod (x, x, ecc->p);
- /* y' = (p_y q_y - p_x q_x) / (1 + t) */ + /* y' = (p_y q_y - a p_x q_x) / (1 + t) */ mpz_mul (y, p->y, q->y); mpz_mod (y, y, ecc->p); - mpz_addmul (y, p->x, q->x); + mpz_mul (s, p->x, q->x); + if (ecc->a > 0) + mpz_submul_ui (y, s, ecc->a); + else + mpz_addmul_ui (y, s, -ecc->a); mpz_mod (y, y, ecc->p); mpz_add_ui (s, t, 1); mpz_invert (s, s, ecc->p); @@ -367,7 +376,7 @@ ecc_set_str (struct ecc_point *p,
static void ecc_curve_init_str (struct ecc_curve *ecc, enum ecc_type type, - const char *p, const char *b, const char *q, + const char *p, int a, const char *b, const char *q, const char *gx, const char *gy, const char *d, const char *t) { @@ -376,6 +385,7 @@ ecc_curve_init_str (struct ecc_curve *ecc, enum ecc_type type, mpz_init_set_str (ecc->p, p, 16); mpz_init_set_str (ecc->b, b, 16); mpz_init_set_str (ecc->q, q, 16); + ecc->a = a; ecc_init (&ecc->g); ecc_set_str (&ecc->g, gx, gy);
@@ -397,6 +407,8 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" "FFFFFFFFFFFFFFFF",
+ -3, + "64210519e59c80e70fa7e9ab72243049" "feb8deecc146b9b1",
@@ -429,6 +441,8 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "ffffffffffffffffffffffffffffffff" "000000000000000000000001",
+ -3, + "b4050a850c04b3abf54132565044b0b7" "d7bfd8ba270b39432355ffb4",
@@ -462,6 +476,8 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "FFFFFFFF000000010000000000000000" "00000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ -3, + "5AC635D8AA3A93E7B3EBBD55769886BC" "651D06B0CC53B0F63BCE3C3E27D2604B",
@@ -496,6 +512,8 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "fffffffffffffffffffffffffffffffe" "ffffffff0000000000000000ffffffff", + -3, + "b3312fa7e23ee7e4988e056be3f82d19" "181d9c6efe8141120314088f5013875a" "c656398d8a2ed19d2a85c8edd3ec2aef", @@ -535,6 +553,8 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "ffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffff",
+ -3, + "051" "953eb9618e1c9a1f929a21a0b68540ee" "a2da725b99b315f3b8b489918ef109e1" @@ -590,6 +610,7 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) ecc_curve_init_str (ecc, ECC_TYPE_TWISTED_EDWARDS, "7fffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffed", + -1, /* (121665/121666) mod p, from PARI/GP c = Mod(121665, p); c / (c+1) */
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- Makefile.in | 12 ++++++------ eccdata.c | 34 +++++++++++++--------------------- 2 files changed, 19 insertions(+), 27 deletions(-)
diff --git a/Makefile.in b/Makefile.in index 1aa2b29db702..fc93a689053d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -326,7 +326,7 @@ des.$(OBJEXT): des.c des.h $(des_headers) # k = 7, c = 6, 320 entries, ~15 KB # k = 9, c = 7, 512 entries, ~24 KB ecc-192.h: eccdata.stamp - ./eccdata$(EXEEXT_FOR_BUILD) 192 7 6 $(NUMB_BITS) > $@T && mv $@T $@ + ./eccdata$(EXEEXT_FOR_BUILD) secp192r1 7 6 $(NUMB_BITS) > $@T && mv $@T $@ # Some possible choices for 224: # k = 18, c = 4, 64 entries, ~4 KB # k = 24, c = 6, 128 entries, ~8 KB @@ -334,7 +334,7 @@ ecc-192.h: eccdata.stamp # k = 8, c = 6, 320 entries, ~20 KB # k = 10, c = 7, 512 entries, ~32 KB ecc-224.h: eccdata.stamp - ./eccdata$(EXEEXT_FOR_BUILD) 224 12 6 $(NUMB_BITS) > $@T && mv $@T $@ + ./eccdata$(EXEEXT_FOR_BUILD) secp224r1 12 6 $(NUMB_BITS) > $@T && mv $@T $@ # Some possible choices for 256: # k = 20, c = 4, 64 entries, ~4 KB # k = 27, c = 6, 128 entries, ~8 KB @@ -342,7 +342,7 @@ ecc-224.h: eccdata.stamp # k = 9, c = 6, 320 entries, ~20 KB # k = 12, c = 7, 512 entries, ~32 KB ecc-256.h: eccdata.stamp - ./eccdata$(EXEEXT_FOR_BUILD) 256 14 6 $(NUMB_BITS) > $@T && mv $@T $@ + ./eccdata$(EXEEXT_FOR_BUILD) secp256r1 14 6 $(NUMB_BITS) > $@T && mv $@T $@ # Some possible choices for 384: # k = 31, c = 4, 64 entries, ~6 KB # k = 41, c = 6, 128 entries, ~12 KB @@ -350,7 +350,7 @@ ecc-256.h: eccdata.stamp # k = 14, c = 6, 320 entries, ~30 KB # k = 18, c = 7, 512 entries, ~48 KB ecc-384.h: eccdata.stamp - ./eccdata$(EXEEXT_FOR_BUILD) 384 41 6 $(NUMB_BITS) > $@T && mv $@T $@ + ./eccdata$(EXEEXT_FOR_BUILD) secp384r1 41 6 $(NUMB_BITS) > $@T && mv $@T $@ # Some possible choices for 521: # k = 42, c = 4, 64 entries, ~9 KB # k = 56, c = 6, 128 entries, ~18 KB @@ -358,10 +358,10 @@ ecc-384.h: eccdata.stamp # k = 19, c = 6, 320 entries, ~44 KB # k = 24, c = 7, 512 entries, ~70 KB ecc-521.h: eccdata.stamp - ./eccdata$(EXEEXT_FOR_BUILD) 521 56 6 $(NUMB_BITS) > $@T && mv $@T $@ + ./eccdata$(EXEEXT_FOR_BUILD) secp521r1 56 6 $(NUMB_BITS) > $@T && mv $@T $@
ecc-25519.h: eccdata.stamp - ./eccdata$(EXEEXT_FOR_BUILD) 255 14 6 $(NUMB_BITS) > $@T && mv $@T $@ + ./eccdata$(EXEEXT_FOR_BUILD) curve25519 14 6 $(NUMB_BITS) > $@T && mv $@T $@
eccdata.stamp: eccdata.c $(MAKE) eccdata$(EXEEXT_FOR_BUILD) diff --git a/eccdata.c b/eccdata.c index a1f5b1135ab2..271be31ee580 100644 --- a/eccdata.c +++ b/eccdata.c @@ -397,11 +397,9 @@ ecc_curve_init_str (struct ecc_curve *ecc, enum ecc_type type, }
static void -ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) +ecc_curve_init (struct ecc_curve *ecc, const char *curve) { - switch (bit_size) - { - case 192: + if (!strcmp(curve, "secp192r1")) { ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS, /* p = 2^{192} - 2^{64} - 1 */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" @@ -434,8 +432,7 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "35433907297cc378b0015703374729d7a4fe46647084e4ba", "a2649984f2135c301ea3acb0776cd4f125389b311db3be32");
- break; - case 224: + } else if (!strcmp(curve, "secp224r1")) { ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS, /* p = 2^{224} - 2^{96} + 1 */ "ffffffffffffffffffffffffffffffff" @@ -469,8 +466,7 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9");
- break; - case 256: + } else if (!strcmp(curve, "secp256r1")) { ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS, /* p = 2^{256} - 2^{224} + 2^{192} + 2^{96} - 1 */ "FFFFFFFF000000010000000000000000" @@ -504,8 +500,7 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852", "e0f1575a4c633cc719dfee5fda862d764efc96c3f30ee0055c42c23f184ed8c6");
- break; - case 384: + } else if (!strcmp(curve, "secp384r1")) { ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS, /* p = 2^{384} - 2^{128} - 2^{96} + 2^{32} - 1 */ "ffffffffffffffffffffffffffffffff" @@ -544,8 +539,7 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "138251cd52ac9298c1c8aad977321deb97e709bd0b4ca0aca55dc8ad51dcfc9d1589a1597e3a5120e1efd631c63e1835", "cacae29869a62e1631e8a28181ab56616dc45d918abc09f3ab0e63cf792aa4dced7387be37bba569549f1c02b270ed67");
- break; - case 521: + } else if (!strcmp (curve, "secp521r1")) { ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS, "1ff" /* p = 2^{521} - 1 */ "ffffffffffffffffffffffffffffffff" @@ -593,8 +587,7 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "35b5df64ae2ac204c354b483487c9070cdc61c891c5ff39afc06c5d55541d3ceac8659e24afe3d0750e8b88e9f078af066a1d5025b08e5a5e2fbc87412871902f3", "82096f84261279d2b673e0178eb0b4abb65521aef6e6e32e1b5ae63fe2f19907f279f283e54ba385405224f750a95b85eebb7faef04699d1d9e21f47fc346e4d0d");
- break; - case 255: + } else if (!strcmp(curve, "curve25519")) { /* Edwards curve used for eddsa25519 and curve25519,
-x^2 + y^2 = 1 - (121665/121666) x^2 y^2, with p = 2^{255} - 19. @@ -658,13 +651,12 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "1a739ec193ce1547493aa657c4c9f870", "47d0e827cb1595e1470eb88580d5716c" "4cf22832ea2f0ff0df38ab61ca32112f"); - break;
- default: - fprintf (stderr, "No known curve for size %d\n", bit_size); + } else { + fprintf (stderr, "No known curve for name %s\n", curve); exit(EXIT_FAILURE); - } - ecc->bit_size = bit_size; + } + ecc->bit_size = mpz_sizeinbase(ecc->p, 2); }
static void @@ -1174,11 +1166,11 @@ main (int argc, char **argv)
if (argc < 4) { - fprintf (stderr, "Usage: %s CURVE-BITS K C [BITS-PER-LIMB]\n", argv[0]); + fprintf (stderr, "Usage: %s CURVE K C [BITS-PER-LIMB]\n", argv[0]); return EXIT_FAILURE; }
- ecc_curve_init (&ecc, atoi(argv[1])); + ecc_curve_init (&ecc, argv[1]);
ecc_pippenger_precompute (&ecc, atoi(argv[2]), atoi(argv[3]));
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- ecc-192.c | 1 + ecc-224.c | 1 + ecc-25519.c | 1 + ecc-256.c | 1 + ecc-384.c | 1 + ecc-521.c | 1 + ecc-internal.h | 1 + eccdata.c | 1 + 8 files changed, 8 insertions(+)
diff --git a/ecc-192.c b/ecc-192.c index 0e79ba23ecd3..24b3b9d3bd69 100644 --- a/ecc-192.c +++ b/ecc-192.c @@ -169,6 +169,7 @@ const struct ecc_curve nettle_secp_192r1 = ecc_mul_g, ecc_j_to_a,
+ ecc_a, ecc_b, ecc_g, ecc_unit, diff --git a/ecc-224.c b/ecc-224.c index f81624837a05..49f5d9cb3aee 100644 --- a/ecc-224.c +++ b/ecc-224.c @@ -121,6 +121,7 @@ const struct ecc_curve nettle_secp_224r1 = ecc_mul_g, ecc_j_to_a,
+ ecc_a, ecc_b, ecc_g, ecc_unit, diff --git a/ecc-25519.c b/ecc-25519.c index c35178c13605..69f340891bc1 100644 --- a/ecc-25519.c +++ b/ecc-25519.c @@ -349,6 +349,7 @@ const struct ecc_curve _nettle_curve25519 = ecc_mul_g_eh, ecc_eh_to_a,
+ ecc_a, ecc_b, /* Edwards curve constant. */ ecc_g, ecc_unit, diff --git a/ecc-256.c b/ecc-256.c index 1406bad3fe30..4b33257f4294 100644 --- a/ecc-256.c +++ b/ecc-256.c @@ -298,6 +298,7 @@ const struct ecc_curve nettle_secp_256r1 = ecc_mul_g, ecc_j_to_a,
+ ecc_a, ecc_b, ecc_g, ecc_unit, diff --git a/ecc-384.c b/ecc-384.c index eb46cbffb410..8d6b8fd0f0ae 100644 --- a/ecc-384.c +++ b/ecc-384.c @@ -206,6 +206,7 @@ const struct ecc_curve nettle_secp_384r1 = ecc_mul_g, ecc_j_to_a,
+ ecc_a, ecc_b, ecc_g, ecc_unit, diff --git a/ecc-521.c b/ecc-521.c index 99c62fca68f8..7ab1f176391a 100644 --- a/ecc-521.c +++ b/ecc-521.c @@ -134,6 +134,7 @@ const struct ecc_curve nettle_secp_521r1 = ecc_mul_g, ecc_j_to_a,
+ ecc_a, ecc_b, ecc_g, ecc_unit, diff --git a/ecc-internal.h b/ecc-internal.h index 9c1ee93e266a..6475e4803aca 100644 --- a/ecc-internal.h +++ b/ecc-internal.h @@ -187,6 +187,7 @@ struct ecc_curve ecc_h_to_a_func *h_to_a;
/* Curve constant */ + int a; /* Used only for key verification */ const mp_limb_t *b; /* Generator, x coordinate followed by y (affine coordinates). Currently used only by the test suite. */ diff --git a/eccdata.c b/eccdata.c index 271be31ee580..56d779f8ca6e 100644 --- a/eccdata.c +++ b/eccdata.c @@ -963,6 +963,7 @@ output_curve (const struct ecc_curve *ecc, unsigned bits_per_limb) printf ("#define ECC_PIPPENGER_C %u\n", ecc->pippenger_c);
output_bignum ("ecc_p", ecc->p, limb_size, bits_per_limb); + printf ("#define ecc_a %d\n", ecc->a); output_bignum ("ecc_b", ecc->b, limb_size, bits_per_limb); output_bignum ("ecc_q", ecc->q, limb_size, bits_per_limb); output_point ("ecc_g", ecc, &ecc->g, 0, limb_size, bits_per_limb);
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- testsuite/ecdsa-keygen-test.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/testsuite/ecdsa-keygen-test.c b/testsuite/ecdsa-keygen-test.c index a96c09effeef..e728094c1ab4 100644 --- a/testsuite/ecdsa-keygen-test.c +++ b/testsuite/ecdsa-keygen-test.c @@ -44,7 +44,10 @@ ecc_valid_p (struct ecc_point *pub) { /* Check y^2 = x^3 - 3 x + b */ mpz_mul (rhs, x, x); - mpz_sub_ui (rhs, rhs, 3); + if (pub->ecc->a > 0) + mpz_add_ui (rhs, rhs, pub->ecc->a); + else + mpz_sub_ui (rhs, rhs, -pub->ecc->a); mpz_mul (rhs, rhs, x); mpz_add (rhs, rhs, mpz_roinit_n (t, pub->ecc->b, size)); }
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- Makefile.in | 14 +++++- ecc-curve.h | 1 + ecc-dup-jj-0.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++ ecc-internal.h | 10 ++++- eccdata.c | 33 ++++++++++++++ testsuite/ecc-add-test.c | 2 +- testsuite/ecc-dup-test.c | 2 +- testsuite/testutils.c | 12 +++++- 8 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 ecc-dup-jj-0.c
diff --git a/Makefile.in b/Makefile.in index fc93a689053d..3d054f113f87 100644 --- a/Makefile.in +++ b/Makefile.in @@ -168,9 +168,9 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ecc-mod.c ecc-mod-inv.c \ ecc-mod-arith.c ecc-pp1-redc.c ecc-pm1-redc.c \ ecc-192.c ecc-224.c ecc-256.c ecc-384.c ecc-521.c \ - ecc-25519.c \ + ecc-25519.c ecc-256k1.c \ ecc-size.c ecc-j-to-a.c ecc-a-to-j.c \ - ecc-dup-jj.c ecc-add-jja.c ecc-add-jjj.c \ + ecc-dup-jj.c ecc-dup-jj-0.c ecc-add-jja.c ecc-add-jjj.c \ ecc-eh-to-a.c \ ecc-dup-eh.c ecc-add-eh.c ecc-add-ehh.c \ ecc-mul-g-eh.c ecc-mul-a-eh.c \ @@ -343,6 +343,14 @@ ecc-224.h: eccdata.stamp # k = 12, c = 7, 512 entries, ~32 KB ecc-256.h: eccdata.stamp ./eccdata$(EXEEXT_FOR_BUILD) secp256r1 14 6 $(NUMB_BITS) > $@T && mv $@T $@ +# Some possible choices for 256: +# k = 20, c = 4, 64 entries, ~4 KB +# k = 27, c = 6, 128 entries, ~8 KB +# k = 14, c = 6, 256 entries, ~16 KB +# k = 9, c = 6, 320 entries, ~20 KB +# k = 12, c = 7, 512 entries, ~32 KB +ecc-256k1.h: eccdata.stamp + ./eccdata$(EXEEXT_FOR_BUILD) secp256k1 14 6 $(NUMB_BITS) > $@T && mv $@T $@ # Some possible choices for 384: # k = 31, c = 4, 64 entries, ~6 KB # k = 41, c = 6, 128 entries, ~12 KB @@ -370,6 +378,7 @@ eccdata.stamp: eccdata.c ecc-192.$(OBJEXT): ecc-192.h ecc-224.$(OBJEXT): ecc-224.h ecc-256.$(OBJEXT): ecc-256.h +ecc-256k1.$(OBJEXT): ecc-256k1.h ecc-384.$(OBJEXT): ecc-384.h ecc-521.$(OBJEXT): ecc-521.h ecc-25519.$(OBJEXT): ecc-25519.h @@ -626,6 +635,7 @@ distcheck: dist clean-here: -rm -f $(TARGETS) *.$(OBJEXT) *.s *.so *.dll *.a \ ecc-192.h ecc-224.h ecc-256.h ecc-384.h ecc-521.h ecc-25519.h \ + ecc-256k1.h \ eccdata$(EXEEXT_FOR_BUILD) eccdata.stamp -rm -rf .lib libnettle.stamp libhogweed.stamp
diff --git a/ecc-curve.h b/ecc-curve.h index 574c9f2e00e1..7bcfcd20f2da 100644 --- a/ecc-curve.h +++ b/ecc-curve.h @@ -44,6 +44,7 @@ struct ecc_curve; extern const struct ecc_curve nettle_secp_192r1; extern const struct ecc_curve nettle_secp_224r1; extern const struct ecc_curve nettle_secp_256r1; +extern const struct ecc_curve nettle_secp_256k1; extern const struct ecc_curve nettle_secp_384r1; extern const struct ecc_curve nettle_secp_521r1;
diff --git a/ecc-dup-jj-0.c b/ecc-dup-jj-0.c new file mode 100644 index 000000000000..b62bf008ed2a --- /dev/null +++ b/ecc-dup-jj-0.c @@ -0,0 +1,109 @@ +/* ecc-dup-jj-0.c + + Copyright (C) 2017 Dmitry Eremin-Solenikov + Copyright (C) 2013 Niels Möller + + 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/. +*/ + +/* Development of Nettle's ECC support was funded by the .SE Internet Fund. */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "ecc.h" +#include "ecc-internal.h" + +/* NOTE: Behaviour for corner cases: + + + p = 0 ==> r = 0, correct! +*/ +void +ecc_dup_jj_0 (const struct ecc_curve *ecc, + mp_limb_t *r, const mp_limb_t *p, + mp_limb_t *scratch) +{ + /* Formulas (from djb, + http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-db...): + + Computation Operation Live variables + delta = z^2 sqr delta + gamma = y^2 sqr delta, gamma + z' = (y+z)^2-gamma-delta sqr delta, gamma + alpha = 3*x^2 mul gamma, beta, alpha + beta = x*gamma mul gamma, beta, alpha + x' = alpha^2-8*beta sqr gamma, beta, alpha + y' = alpha*(4*beta-x')-8*gamma^2 mul, sqr + */ + +#define delta scratch +#define gamma (scratch + ecc->p.size) +#define beta (scratch + 2*ecc->p.size) +#define g2 (scratch + 3*ecc->p.size) +#define sum (scratch + 4*ecc->p.size) +#define alpha scratch /* Overlap delta */ + +#define xp p +#define yp (p + ecc->p.size) +#define zp (p + 2*ecc->p.size) + + /* delta */ + ecc_modp_sqr (ecc, delta, zp); + + /* gamma */ + ecc_modp_sqr (ecc, gamma, yp); + + /* z'. Can use beta area as scratch. */ + ecc_modp_add (ecc, r + 2*ecc->p.size, yp, zp); + ecc_modp_sqr (ecc, beta, r + 2*ecc->p.size); + ecc_modp_sub (ecc, beta, beta, gamma); + ecc_modp_sub (ecc, r + 2*ecc->p.size, beta, delta); + + /* alpha. Can use beta area as scratch, and overwrite delta. */ + ecc_modp_sqr (ecc, beta, xp); + ecc_modp_mul_1 (ecc, alpha, beta, 3); + + /* beta */ + ecc_modp_mul (ecc, beta, xp, gamma); + + /* Do gamma^2 and 4*beta early, to get them out of the way. We can + then use the old area at gamma as scratch. */ + ecc_modp_sqr (ecc, g2, gamma); + ecc_modp_mul_1 (ecc, sum, beta, 4); + + /* x' */ + ecc_modp_sqr (ecc, gamma, alpha); /* Overwrites gamma and beta */ + ecc_modp_submul_1 (ecc, gamma, sum, 2); + mpn_copyi (r, gamma, ecc->p.size); + + /* y' */ + ecc_modp_sub (ecc, sum, sum, r); + ecc_modp_mul (ecc, gamma, sum, alpha); + ecc_modp_submul_1 (ecc, gamma, g2, 8); + mpn_copyi (r + ecc->p.size, gamma, ecc->p.size); +} diff --git a/ecc-internal.h b/ecc-internal.h index 6475e4803aca..98e8515f3b82 100644 --- a/ecc-internal.h +++ b/ecc-internal.h @@ -57,6 +57,7 @@ #define ecc_j_to_a _nettle_ecc_j_to_a #define ecc_eh_to_a _nettle_ecc_eh_to_a #define ecc_dup_jj _nettle_ecc_dup_jj +#define ecc_dup_jj_0 _nettle_ecc_dup_jj_0 #define ecc_add_jja _nettle_ecc_add_jja #define ecc_add_jjj _nettle_ecc_add_jjj #define ecc_dup_eh _nettle_ecc_dup_eh @@ -299,13 +300,20 @@ ecc_eh_to_a (const struct ecc_curve *ecc,
/* Group operations */
-/* Point doubling, with jacobian input and output. Corner cases: +/* Point doubling, with jacobian input and output for a = -3. Corner cases: Correctly sets R = 0 (r_Z = 0) if p = 0 or 2p = 0. */ void ecc_dup_jj (const struct ecc_curve *ecc, mp_limb_t *r, const mp_limb_t *p, mp_limb_t *scratch);
+/* Point doubling, with jacobian input and output for a = 0. Corner cases: + Correctly sets R = 0 (r_Z = 0) if p = 0 or 2p = 0. */ +void +ecc_dup_jj_0 (const struct ecc_curve *ecc, + mp_limb_t *r, const mp_limb_t *p, + mp_limb_t *scratch); + /* Point addition, with jacobian output, one jacobian input and one affine input. Corner cases: Fails for the cases
diff --git a/eccdata.c b/eccdata.c index 56d779f8ca6e..ecd50723a4e7 100644 --- a/eccdata.c +++ b/eccdata.c @@ -500,6 +500,39 @@ ecc_curve_init (struct ecc_curve *ecc, const char *curve) "e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852", "e0f1575a4c633cc719dfee5fda862d764efc96c3f30ee0055c42c23f184ed8c6");
+ } else if (!strcmp(curve, "secp256k1")) { + ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS, + /* p = 2^{256} - 2^{32} - 2^{9} - 2^{8} - 2^{7} - 2^{6} - 2^{4} - 1 */ + "ffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffefffffc2f", + + 0, + + "7", + + "fffffffffffffffffffffffffffffffe" + "baaedce6af48a03bbfd25e8cd0364141", + + "79be667ef9dcbbac55a06295ce870b07" + "029bfcdb2dce28d959f2815b16f81798", + + "483ada7726a3c4655da4fbfc0e1108a8" + "fd17b448a68554199c47d08ffb10d4b8", + NULL, NULL); + + ecc->ref = ecc_alloc (3); + ecc_set_str (&ecc->ref[0], /* 2 g */ + "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a"); + + ecc_set_str (&ecc->ref[1], /* 3 g */ + "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"); + + ecc_set_str (&ecc->ref[2], /* 4 g */ + "e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13", + "51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922"); + } else if (!strcmp(curve, "secp384r1")) { ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS, /* p = 2^{384} - 2^{128} - 2^{96} + 2^{32} - 1 */ diff --git a/testsuite/ecc-add-test.c b/testsuite/ecc-add-test.c index ad2bd29230ee..d2df0c604ef3 100644 --- a/testsuite/ecc-add-test.c +++ b/testsuite/ecc-add-test.c @@ -54,7 +54,7 @@ test_main (void) else { ASSERT (ecc->add_hhh == ecc_add_jjj); - ASSERT (ecc->dup == ecc_dup_jj); + ASSERT (ecc->dup == ecc_dup_jj || ecc->dup == ecc_dup_jj_0); }
ecc->dup (ecc, g2, g, scratch); diff --git a/testsuite/ecc-dup-test.c b/testsuite/ecc-dup-test.c index 0ae4444a7cb0..7b280b1c0f65 100644 --- a/testsuite/ecc-dup-test.c +++ b/testsuite/ecc-dup-test.c @@ -30,7 +30,7 @@ test_main (void) free (z); } else - ASSERT (ecc->dup == ecc_dup_jj); + ASSERT (ecc->dup == ecc_dup_jj || ecc->dup == ecc_dup_jj_0);
ecc->dup (ecc, p, g, scratch); test_ecc_mul_h (i, 2, p); diff --git a/testsuite/testutils.c b/testsuite/testutils.c index 6f897617cadb..f2c884533131 100644 --- a/testsuite/testutils.c +++ b/testsuite/testutils.c @@ -1215,6 +1215,7 @@ const struct ecc_curve * const ecc_curves[] = { &nettle_secp_192r1, &nettle_secp_224r1, &nettle_secp_256r1, + &nettle_secp_256k1, &nettle_secp_384r1, &nettle_secp_521r1, &_nettle_curve25519, @@ -1269,7 +1270,7 @@ void test_ecc_mul_a (unsigned curve, unsigned n, const mp_limb_t *p) { /* For each curve, the points 2 g, 3 g and 4 g */ - static const struct ecc_ref_point ref[6][3] = { + static const struct ecc_ref_point ref[7][3] = { { { "dafebf5828783f2ad35534631588a3f629a70fb16982a888", "dd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" }, { "76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da", @@ -1291,6 +1292,13 @@ test_ecc_mul_a (unsigned curve, unsigned n, const mp_limb_t *p) { "e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852", "e0f1575a4c633cc719dfee5fda862d764efc96c3f30ee0055c42c23f184ed8c6" }, }, + { { "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a" }, + { "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672" }, + { "e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13", + "51ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922" }, + }, { { "8d999057ba3d2d969260045c55b97f089025959a6f434d651d207d19fb96e9e" "4fe0e86ebe0e64f85b96a9c75295df61", "8e80f1fa5b1b3cedb7bfe8dffd6dba74b275d875bc6cc43e904e505f256ab425" @@ -1332,7 +1340,7 @@ test_ecc_mul_a (unsigned curve, unsigned n, const mp_limb_t *p) "47d0e827cb1595e1470eb88580d5716c4cf22832ea2f0ff0df38ab61ca32112f" }, } }; - assert (curve < 6); + assert (curve < 7); assert (n <= 4); if (n == 0) {
nettle-bugs@lists.lysator.liu.se