diff options
author | Niels Möller <nisse@lysator.liu.se> | 2022-09-14 16:02:41 +0200 |
---|---|---|
committer | Niels Möller <nisse@lysator.liu.se> | 2022-09-14 16:02:41 +0200 |
commit | daabcc72a87a61f69188c26cf8ddabfc98ef64f0 (patch) | |
tree | 52735f09ac8c958c3e9756639d1de994ac9b3bb9 | |
parent | 8e2adda2c48152e6d7270035547ae5477756ceb8 (diff) | |
download | nettle-daabcc72a87a61f69188c26cf8ddabfc98ef64f0.tar.gz |
New function ecc_nonsec_add_jjj
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | ecc-internal.h | 9 | ||||
-rw-r--r-- | ecc-nonsec-add-jjj.c | 162 | ||||
-rw-r--r-- | testsuite/ecc-add-test.c | 44 |
5 files changed, 209 insertions, 16 deletions
@@ -1,3 +1,11 @@ +2022-09-14 Niels Möller <nisse@lysator.liu.se> + + * ecc-nonsec-add-jjj.c (ecc_nonsec_add_jjj): New file and + function. + * ecc-internal.h: Declare it. + * Makefile.in (hogweed_SOURCES): Add ecc-nonsec-add-jjj.c. + * testsuite/ecc-add-test.c (test_main): Add tests for ecc_nonsec_add_jjj. + 2022-09-08 Niels Möller <nisse@lysator.liu.se> * eccdata.c (string_toupper): New utility function. diff --git a/Makefile.in b/Makefile.in index ca1466b7..944fff0a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -198,7 +198,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ecc-secp192r1.c ecc-secp224r1.c ecc-secp256r1.c \ ecc-secp384r1.c ecc-secp521r1.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-add-jja.c ecc-add-jjj.c ecc-nonsec-add-jjj.c \ ecc-eh-to-a.c \ ecc-dup-eh.c ecc-add-eh.c ecc-add-ehh.c \ ecc-dup-th.c ecc-add-th.c ecc-add-thh.c \ diff --git a/ecc-internal.h b/ecc-internal.h index b04d80ce..6201bf05 100644 --- a/ecc-internal.h +++ b/ecc-internal.h @@ -66,6 +66,7 @@ #define ecc_dup_jj _nettle_ecc_dup_jj #define ecc_add_jja _nettle_ecc_add_jja #define ecc_add_jjj _nettle_ecc_add_jjj +#define ecc_nonsec_add_jjj _nettle_ecc_nonsec_add_jjj #define ecc_dup_eh _nettle_ecc_dup_eh #define ecc_add_eh _nettle_ecc_add_eh #define ecc_add_ehh _nettle_ecc_add_ehh @@ -390,6 +391,14 @@ ecc_add_jjj (const struct ecc_curve *ecc, mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q, mp_limb_t *scratch); +/* Variant that handles the checks for the special cases P = ±Q. + Returns 1 on success, 0 if result is infinite. Not side-channel + silent, so must not be used with secret inputs. */ +int +ecc_nonsec_add_jjj (const struct ecc_curve *ecc, + mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q, + mp_limb_t *scratch); + /* Point doubling on a twisted Edwards curve, with homogeneous cooordinates. */ void diff --git a/ecc-nonsec-add-jjj.c b/ecc-nonsec-add-jjj.c new file mode 100644 index 00000000..439c0a52 --- /dev/null +++ b/ecc-nonsec-add-jjj.c @@ -0,0 +1,162 @@ +/* ecc-non-sec-add-jjj.c + + Copyright (C) 2013, 2022 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" + +/* Similar to ecc_add_jjj, but checks if x coordinates are equal (H = + 0) below, and if so, performs doubling if also y coordinates are + equal, or returns 0 (failure) indicating that the result is the + infinity point. */ +int +ecc_nonsec_add_jjj (const struct ecc_curve *ecc, + mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q, + mp_limb_t *scratch) +{ +#define x1 p +#define y1 (p + ecc->p.size) +#define z1 (p + 2*ecc->p.size) + +#define x2 q +#define y2 (q + ecc->p.size) +#define z2 (q + 2*ecc->p.size) + +#define x3 r +#define y3 (r + ecc->p.size) +#define z3 (r + 2*ecc->p.size) + /* Formulas, from djb, + http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl: + + Computation Operation Live variables + + Z1Z1 = Z1^2 sqr Z1Z1 + Z2Z2 = Z2^2 sqr Z1Z1, Z2Z2 + U1 = X1*Z2Z2 mul Z1Z1, Z2Z2, U1 + U2 = X2*Z1Z1 mul Z1Z1, Z2Z2, U1, U2 + H = U2-U1 Z1Z1, Z2Z2, U1, H + Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H sqr, mul Z1Z1, Z2Z2, U1, H + S1 = Y1*Z2*Z2Z2 mul, mul Z1Z1, U1, H, S1 + S2 = Y2*Z1*Z1Z1 mul, mul U1, H, S1, S2 + W = 2*(S2-S1) (djb: r) U1, H, S1, W + I = (2*H)^2 sqr U1, H, S1, W, I + J = H*I mul U1, S1, W, J, V + V = U1*I mul S1, W, J, V + X3 = W^2-J-2*V sqr S1, W, J, V + Y3 = W*(V-X3)-2*S1*J mul, mul + */ + +#define h scratch +#define z1z1 (scratch + ecc->p.size) +#define z2z2 z1z1 +#define z1z2 (scratch + 2*ecc->p.size) + +#define w (scratch + ecc->p.size) +#define i (scratch + 2*ecc->p.size) +#define j h +#define v i + +#define tp (scratch + 3*ecc->p.size) + + ecc_mod_sqr (&ecc->p, z2z2, z2, tp); /* z2z2 */ + /* Store u1 at x3 */ + ecc_mod_mul (&ecc->p, x3, x1, z2z2, tp); /* z2z2 */ + + ecc_mod_add (&ecc->p, z1z2, z1, z2); /* z2z2, z1z2 */ + ecc_mod_sqr (&ecc->p, z1z2, z1z2, tp); + ecc_mod_sub (&ecc->p, z1z2, z1z2, z2z2); /* z2z2, z1z2 */ + + /* Do s1 early, store at y3 */ + ecc_mod_mul (&ecc->p, z2z2, z2z2, z2, tp); /* z2z2, z1z2 */ + ecc_mod_mul (&ecc->p, y3, z2z2, y1, tp); /* z1z2 */ + + ecc_mod_sqr (&ecc->p, z1z1, z1, tp); /* z1z1, z1z2 */ + ecc_mod_sub (&ecc->p, z1z2, z1z2, z1z1); + ecc_mod_mul (&ecc->p, h, x2, z1z1, tp); /* z1z1, z1z2, h */ + ecc_mod_sub (&ecc->p, h, h, x3); + + /* z1^3 */ + ecc_mod_mul (&ecc->p, z1z1, z1z1, z1, tp); + + /* z3 <-- h z1 z2 delayed until now, since that may clobber z1. */ + ecc_mod_mul (&ecc->p, z3, z1z2, h, tp); /* z1z1, h */ + /* w = 2 (s2 - s1) */ + ecc_mod_mul (&ecc->p, w, z1z1, y2, tp); /* h, w */ + ecc_mod_sub (&ecc->p, w, w, y3); + + /* Note that use of ecc_mod_zero_p depends 0 <= h,w < 2p. */ + if (ecc_mod_zero_p (&ecc->p, h)) + { + /* X1 == X2 */ + if (ecc_mod_zero_p (&ecc->p, w)) { + /* Y1 == Y2. Do point duplication. Note that q input is + unclobbered, and that scratch need is smaller. Implies some + unnecessary recomputation, but performance it not so + important for this very unlikely corner case. */ + ecc_dup_jj (ecc, r, q, scratch); + return 1; + } + + /* We must have Y1 == -Y2, and then the result is the infinity + point, */ + mpn_zero (r, 3*ecc->p.size); + return 0; + } + ecc_mod_add (&ecc->p, w, w, w); + + /* i = (2h)^2 */ + ecc_mod_add (&ecc->p, i, h, h); /* h, w, i */ + ecc_mod_sqr (&ecc->p, i, i, tp); + + /* j and h can overlap */ + ecc_mod_mul (&ecc->p, j, h, i, tp); /* j, w, i */ + + /* v and i can overlap */ + ecc_mod_mul (&ecc->p, v, x3, i, tp); /* j, w, v */ + + /* x3 <-- w^2 - j - 2v */ + ecc_mod_sqr (&ecc->p, x3, w, tp); + ecc_mod_sub (&ecc->p, x3, x3, j); + ecc_mod_submul_1 (&ecc->p, x3, v, 2); + + /* y3 <-- w (v - x3) - 2 s1 j */ + ecc_mod_mul (&ecc->p, j, j, y3, tp); + ecc_mod_sub (&ecc->p, v, v, x3); + ecc_mod_mul (&ecc->p, y3, v, w, tp); + ecc_mod_submul_1 (&ecc->p, y3, j, 2); + + return 1; +} diff --git a/testsuite/ecc-add-test.c b/testsuite/ecc-add-test.c index 6f58a3bb..4793a4bf 100644 --- a/testsuite/ecc-add-test.c +++ b/testsuite/ecc-add-test.c @@ -19,6 +19,24 @@ test_main (void) test_ecc_get_g (i, g); + ecc->dup (ecc, g2, g, scratch); + test_ecc_mul_h (i, 2, g2); + + ecc->add_hhh (ecc, g3, g, g2, scratch); + test_ecc_mul_h (i, 3, g3); + + ecc->add_hhh (ecc, g3, g2, g, scratch); + test_ecc_mul_h (i, 3, g3); + + ecc->add_hhh (ecc, p, g, g3, scratch); + test_ecc_mul_h (i, 4, p); + + ecc->add_hhh (ecc, p, g3, g, scratch); + test_ecc_mul_h (i, 4, p); + + ecc->dup (ecc, p, g2, scratch); + test_ecc_mul_h (i, 4, p); + if (ecc->p.bit_size == 255 || ecc->p.bit_size == 448) { mp_limb_t *z = xalloc_limbs (ecc_size_j (ecc)); @@ -49,24 +67,20 @@ test_main (void) free (z); } + else + { + ASSERT (ecc_nonsec_add_jjj (ecc, g2, g, g, scratch)); + test_ecc_mul_h (i, 2, g2); - ecc->dup (ecc, g2, g, scratch); - test_ecc_mul_h (i, 2, g2); - - ecc->add_hhh (ecc, g3, g, g2, scratch); - test_ecc_mul_h (i, 3, g3); - - ecc->add_hhh (ecc, g3, g2, g, scratch); - test_ecc_mul_h (i, 3, g3); - - ecc->add_hhh (ecc, p, g, g3, scratch); - test_ecc_mul_h (i, 4, p); + ASSERT (ecc_nonsec_add_jjj (ecc, g3, g2, g, scratch)); + test_ecc_mul_h (i, 3, g3); - ecc->add_hhh (ecc, p, g3, g, scratch); - test_ecc_mul_h (i, 4, p); + ASSERT (ecc_nonsec_add_jjj (ecc, p, g, g3, scratch)); + test_ecc_mul_h (i, 4, p); - ecc->dup (ecc, p, g2, scratch); - test_ecc_mul_h (i, 4, p); + ASSERT (ecc_nonsec_add_jjj (ecc, p, g2, g2, scratch)); + test_ecc_mul_h (i, 4, p); + } free (g); free (g2); |