Commit ee28a24c authored by Niels Möller's avatar Niels Möller
Browse files

Merge branch 'ecc-gost'

parents 6695f17f 1c2aba42
......@@ -45,6 +45,8 @@ core
/rotors.h
/ecc-curve25519.h
/ecc-curve448.h
/ecc-gost-gc256b.h
/ecc-gost-gc512a.h
/ecc-secp192r1.h
/ecc-secp224r1.h
/ecc-secp256r1.h
......
2020-01-26 Niels Möller <nisse@lysator.liu.se>
Support for GOST DSA, contributed by Dmitry Baryshkov.
* gostdsa-verify.c (gostdsa_verify): New file and function.
* gostdsa-sign.c (gostdsa_sign): New file and function.
* ecc-gostdsa-verify.c (ecdsa_in_range, ecc_gostdsa_verify_itch)
(ecc_gostdsa_verify): New file and functions.
* ecc-gostdsa-sign.c (ecc_gostdsa_sign_itch, ecc_gostdsa_sign):
New file and functions.
* ecc-internal.h (ECC_GOSTDSA_SIGN_ITCH): New macro.
* ecc-hash.c (gost_hash): New function.
* testsuite/gostdsa-verify-test.c: New test.
* testsuite/gostdsa-sign-test.c: New test.
* testsuite/gostdsa-keygen-test.c: New test.
* testsuite/Makefile.in (TS_HOGWEED_SOURCES): Add new tests.
Support for GOST gc256b and gc512a curves, contributed by Dmitry
Baryshkov.
* eccdata.c (ecc_curve_init): Add parameters for gost_gc256b and
gost_gc512a.
* ecc-gost-gc256b.c: New file, define _nettle_gost_gc256b.
* ecc-gost-gc512a.c: New file, define _nettle_gost_gc512a.
* Makefile.in: Add rules to generate ecc-gost-gc256b.h and
ecc-gost-gc512a.h.
(hogweed_SOURCES): Add ecc-gost-gc256b.c ecc-gost-gc512a.c.
* examples/ecc-benchmark.c (curves): Add to list.
* testsuite/testutils.c (ecc_curves): Add to list.
(test_ecc_mul_a): Reference points for new curves.
* NEWS: Started on entries for Nettle-3.6.
2020-01-25 Niels Möller <nisse@lysator.liu.se>
......
......@@ -176,6 +176,7 @@ 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-curve25519.c ecc-curve448.c \
ecc-gost-gc256b.c ecc-gost-gc512a.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 \
......@@ -188,6 +189,8 @@ hogweed_SOURCES = sexp.c sexp-format.c \
ecc-point.c ecc-scalar.c ecc-point-mul.c ecc-point-mul-g.c \
ecc-ecdsa-sign.c ecdsa-sign.c \
ecc-ecdsa-verify.c ecdsa-verify.c ecdsa-keygen.c \
ecc-gostdsa-sign.c gostdsa-sign.c \
ecc-gostdsa-verify.c gostdsa-verify.c \
curve25519-mul-g.c curve25519-mul.c curve25519-eh-to-x.c \
curve448-mul-g.c curve448-mul.c curve448-eh-to-x.c \
eddsa-compress.c eddsa-decompress.c eddsa-expand.c \
......@@ -204,7 +207,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
cbc.h ccm.h cfb.h chacha.h chacha-poly1305.h ctr.h \
curve25519.h curve448.h des.h dsa.h dsa-compat.h eax.h \
ecc-curve.h ecc.h ecdsa.h eddsa.h \
gcm.h gost28147.h gosthash94.h hmac.h \
gcm.h gost28147.h gostdsa.h gosthash94.h hmac.h \
knuth-lfib.h hkdf.h \
macros.h \
cmac.h siv-cmac.h \
......@@ -376,12 +379,31 @@ ecc-curve25519.h: eccdata.stamp
ecc-curve448.h: eccdata.stamp
./eccdata$(EXEEXT_FOR_BUILD) curve448 38 6 $(NUMB_BITS) > $@T && mv $@T $@
# Some reasonable choices for 256:
# k = 9, c = 6, S = 320, T = 54 ( 45 A + 9 D) 20 KB
# k = 11, c = 6, S = 256, T = 55 ( 44 A + 11 D) 16 KB
# k = 19, c = 7, S = 256, T = 57 ( 38 A + 19 D) 16 KB
# k = 15, c = 6, S = 192, T = 60 ( 45 A + 15 D) 12 KB
ecc-gost-gc256b.h: eccdata.stamp
./eccdata$(EXEEXT_FOR_BUILD) gost_gc256b 11 6 $(NUMB_BITS) > $@T && mv $@T $@
# Some reasonable choices for 512:
# k = 22, c = 6, S = 256, T = 110 ( 88 A + 22 D) 32 KB
# k = 29, c = 6, S = 192, T = 116 ( 87 A + 29 D) 24 KB
# k = 21, c = 5, S = 160, T = 126 (105 A + 21 D) 20 KB
# k = 43, c = 6, S = 128, T = 129 ( 86 A + 43 D) 16 KB
# k = 35, c = 5, S = 96, T = 140 (105 A + 35 D) 12 KB
ecc-gost-gc512a.h: eccdata.stamp
./eccdata$(EXEEXT_FOR_BUILD) gost_gc512a 43 6 $(NUMB_BITS) > $@T && mv $@T $@
eccdata.stamp: eccdata.c
$(MAKE) eccdata$(EXEEXT_FOR_BUILD)
echo stamp > eccdata.stamp
ecc-curve25519.$(OBJEXT): ecc-curve25519.h
ecc-curve448.$(OBJEXT): ecc-curve448.h
ecc-gost-gc256b.$(OBJEXT): ecc-gost-gc256b.h
ecc-gost-gc512a.$(OBJEXT): ecc-gost-gc512a.h
ecc-secp192r1.$(OBJEXT): ecc-secp192r1.h
ecc-secp224r1.$(OBJEXT): ecc-secp224r1.h
ecc-secp256r1.$(OBJEXT): ecc-secp256r1.h
......@@ -635,6 +657,7 @@ distcheck: dist
clean-here:
-rm -f $(TARGETS) *.$(OBJEXT) *.$(OBJEXT).d *.s *.so *.dll *.a \
ecc-curve25519.h ecc-curve448.h \
ecc-gost-gc256b.h ecc-gost-gc512a.h \
ecc-secp192r1.h ecc-secp224r1.h ecc-secp256r1.h \
ecc-secp384r1.h ecc-secp521r1.h \
aesdata$(EXEEXT_FOR_BUILD) \
......
......@@ -43,6 +43,8 @@ extern "C" {
/* The contents of this struct is internal. */
struct ecc_curve;
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_gost_gc256b(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_gost_gc512a(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_192r1(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_224r1(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_256r1(void);
......
/* ecc-gost-gc256b.c
Copyright (C) 2016-2020 Dmitry Eremin-Solenikov
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 "ecc.h"
#include "ecc-internal.h"
#define USE_REDC 0
#include "ecc-gost-gc256b.h"
static void
ecc_gost_gc256b_modp (const struct ecc_modulo *m, mp_limb_t *rp)
{
mp_size_t mn = m->size;
mp_limb_t hi;
hi = mpn_addmul_1(rp, rp + mn, mn, 0x269);
hi = sec_add_1 (rp, rp, mn, hi * 0x269);
hi = sec_add_1 (rp, rp, mn, hi * 0x269);
assert(hi == 0);
}
#define ecc_gost_gc256b_modp ecc_gost_gc256b_modp
#define ecc_gost_gc256b_modq ecc_mod
const struct ecc_curve _nettle_gost_gc256b =
{
{
256,
ECC_LIMB_SIZE,
ECC_BMODP_SIZE,
ECC_REDC_SIZE,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
ecc_p,
ecc_Bmodp,
ecc_Bmodp_shifted,
ecc_redc_ppm1,
ecc_pp1h,
ecc_gost_gc256b_modp,
ecc_gost_gc256b_modp,
ecc_mod_inv,
NULL,
},
{
256,
ECC_LIMB_SIZE,
ECC_BMODQ_SIZE,
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
ecc_q,
ecc_Bmodq,
ecc_Bmodq_shifted,
NULL,
ecc_qp1h,
ecc_gost_gc256b_modq,
ecc_gost_gc256b_modq,
ecc_mod_inv,
NULL,
},
USE_REDC,
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
ECC_J_TO_A_ITCH (ECC_LIMB_SIZE),
ecc_add_jja,
ecc_add_jjj,
ecc_dup_jj,
ecc_mul_a,
ecc_mul_g,
ecc_j_to_a,
ecc_b,
ecc_g,
ecc_unit,
ecc_table
};
const struct ecc_curve *nettle_get_gost_gc256b(void)
{
return &_nettle_gost_gc256b;
}
/* ecc-gost-gc512a.c
Copyright (C) 2016-2020 Dmitry Eremin-Solenikov
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 "ecc.h"
#include "ecc-internal.h"
#define USE_REDC 0
#include "ecc-gost-gc512a.h"
static void
ecc_gost_gc512a_modp (const struct ecc_modulo *m, mp_limb_t *rp)
{
mp_size_t mn = m->size;
mp_limb_t hi;
hi = mpn_addmul_1(rp, rp + mn, mn, 0x239);
hi = sec_add_1 (rp, rp, mn, hi * 0x239);
hi = sec_add_1 (rp, rp, mn, hi * 0x239);
assert(hi == 0);
}
#define ecc_gost_gc512a_modp ecc_gost_gc512a_modp
#define ecc_gost_gc512a_modq ecc_mod
const struct ecc_curve _nettle_gost_gc512a =
{
{
512,
ECC_LIMB_SIZE,
ECC_BMODP_SIZE,
ECC_REDC_SIZE,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
ecc_p,
ecc_Bmodp,
ecc_Bmodp_shifted,
ecc_redc_ppm1,
ecc_pp1h,
ecc_gost_gc512a_modp,
ecc_gost_gc512a_modp,
ecc_mod_inv,
NULL,
},
{
512,
ECC_LIMB_SIZE,
ECC_BMODQ_SIZE,
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
ecc_q,
ecc_Bmodq,
ecc_Bmodq_shifted,
NULL,
ecc_qp1h,
ecc_gost_gc512a_modq,
ecc_gost_gc512a_modq,
ecc_mod_inv,
NULL,
},
USE_REDC,
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
ECC_J_TO_A_ITCH (ECC_LIMB_SIZE),
ecc_add_jja,
ecc_add_jjj,
ecc_dup_jj,
ecc_mul_a,
ecc_mul_g,
ecc_j_to_a,
ecc_b,
ecc_g,
ecc_unit,
ecc_table
};
const struct ecc_curve *nettle_get_gost_gc512a(void)
{
return &_nettle_gost_gc512a;
}
/* ecc-gostdsa-sign.c
Copyright (C) 2015 Dmitry Eremin-Solenikov
Copyright (C) 2013, 2014 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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include "gostdsa.h"
#include "ecc-internal.h"
/* Low-level GOST DSA signing */
mp_size_t
ecc_gostdsa_sign_itch (const struct ecc_curve *ecc)
{
/* Needs 3*ecc->p.size + scratch for ecc->mul_g. Currently same for
ecc_mul_g and ecc_mul_g_eh. */
return ECC_GOSTDSA_SIGN_ITCH (ecc->p.size);
}
/* NOTE: Caller should check if r or s is zero. */
void
ecc_gostdsa_sign (const struct ecc_curve *ecc,
const mp_limb_t *zp,
const mp_limb_t *kp,
size_t length, const uint8_t *digest,
mp_limb_t *rp, mp_limb_t *sp,
mp_limb_t *scratch)
{
#define P scratch
#define hp (scratch + 4*ecc->p.size)
#define tp (scratch + 2*ecc->p.size)
#define t2p scratch
/* Procedure, according to GOST 34.10. q denotes the group
order.
1. k <-- uniformly random, 0 < k < q
2. C <-- (c_x, c_y) = k g
3. r <-- c_x mod q
4. s <-- (r*z + k*h) mod q.
*/
ecc->mul_g (ecc, P, kp, P + 3*ecc->p.size);
/* x coordinate only, modulo q */
ecc->h_to_a (ecc, 2, rp, P, P + 3*ecc->p.size);
/* Process hash digest */
gost_hash (&ecc->q, hp, length, digest);
if (mpn_zero_p (hp, ecc->p.size))
mpn_add_1 (hp, hp, ecc->p.size, 1);
ecc_modq_mul (ecc, tp, rp, zp);
ecc_modq_mul (ecc, t2p, kp, hp);
ecc_modq_add (ecc, sp, tp, t2p);
/* Also reduce mod ecc->q. It should already be < 2*ecc->q,
* so one subtraction should suffice. */
*scratch = mpn_sub_n (tp, sp, ecc->q.m, ecc->p.size);
cnd_copy (*scratch == 0, sp, tp, ecc->p.size);
#undef P
#undef hp
#undef tp
#undef t2p
}
/* ecc-gostdsa-verify.c
Copyright (C) 2015 Dmitry Eremin-Solenikov
Copyright (C) 2013, 2014 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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include "gostdsa.h"
#include "ecc-internal.h"
/* Low-level GOST DSA verify */
static int
ecdsa_in_range (const struct ecc_curve *ecc, const mp_limb_t *xp)
{
return !mpn_zero_p (xp, ecc->p.size)
&& mpn_cmp (xp, ecc->q.m, ecc->p.size) < 0;
}
mp_size_t
ecc_gostdsa_verify_itch (const struct ecc_curve *ecc)
{
/* Largest storage need is for the ecc->mul call. */
return 5*ecc->p.size + ecc->mul_itch;
}
/* FIXME: Use faster primitives, not requiring side-channel silence. */
int
ecc_gostdsa_verify (const struct ecc_curve *ecc,
const mp_limb_t *pp, /* Public key */
size_t length, const uint8_t *digest,
const mp_limb_t *rp, const mp_limb_t *sp,
mp_limb_t *scratch)
{
/* Procedure, according to GOST R 34.10. q denotes the group
order.
1. Check 0 < r, s < q.
2. v <-- h^{-1} (mod q)
3. z1 <-- s * v (mod q)
4. z2 <-- -r * v (mod q)
5. R = u1 G + u2 Y
6. Signature is valid if R_x = r (mod q).
*/
#define hp (scratch)
#define vp (scratch + ecc->p.size)
#define z1 (scratch + 3*ecc->p.size)
#define z2 (scratch + 4*ecc->p.size)
#define P1 (scratch + 4*ecc->p.size)
#define P2 (scratch)
if (! (ecdsa_in_range (ecc, rp)
&& ecdsa_in_range (ecc, sp)))
return 0;
gost_hash (&ecc->q, hp, length, digest);
if (mpn_zero_p (hp, ecc->p.size))
mpn_add_1 (hp, hp, ecc->p.size, 1);
/* Compute v */
ecc->q.invert (&ecc->q, vp, hp, vp + 2*ecc->p.size);
/* z1 = s / h, P1 = z1 * G */
ecc_modq_mul (ecc, z1, sp, vp);
/* z2 = - r / h, P2 = z2 * Y */
ecc_modq_mul (ecc, z2, rp, vp);
mpn_sub_n (z2, ecc->q.m, z2, ecc->p.size);
/* Total storage: 5*ecc->p.size + ecc->mul_itch */
ecc->mul (ecc, P2, z2, pp, z2 + ecc->p.size);
/* Total storage: 7*ecc->p.size + ecc->mul_g_itch (ecc->p.size) */
ecc->mul_g (ecc, P1, z1, P1 + 3*ecc->p.size);
/* Total storage: 6*ecc->p.size + ecc->add_hhh_itch */
ecc->add_hhh (ecc, P1, P1, P2, P1 + 3*ecc->p.size);
/* x coordinate only, modulo q */
ecc->h_to_a (ecc, 2, P2, P1, P1 + 3*ecc->p.size);
return (mpn_cmp (rp, P2, ecc->p.size) == 0);
#undef P2
#undef P1
#undef z2
#undef z1
#undef hp
#undef vp
}
......@@ -62,3 +62,14 @@ ecc_hash (const struct ecc_modulo *m,
/* We got a few extra bits, at the low end. Discard them. */
mpn_rshift (hp, hp, m->size + 1, 8*length - m->bit_size);
}
void
gost_hash (const struct ecc_modulo *m,
mp_limb_t *hp,
size_t length, const uint8_t *digest)
{
if (length > ((size_t) m->bit_size + 7) / 8)
length = (m->bit_size + 7) / 8;
mpn_set_base256_le (hp, m->size + 1, digest, length);
}
......@@ -53,6 +53,7 @@
#define ecc_mod _nettle_ecc_mod
#define ecc_mod_inv _nettle_ecc_mod_inv
#define ecc_hash _nettle_ecc_hash
#define gost_hash _nettle_gost_hash
#define ecc_a_to_j _nettle_ecc_a_to_j
#define ecc_j_to_a _nettle_ecc_j_to_a
#define ecc_eh_to_a _nettle_ecc_eh_to_a
......@@ -91,6 +92,10 @@ extern const struct ecc_curve _nettle_secp_521r1;
extern const struct ecc_curve _nettle_curve25519;
extern const struct ecc_curve _nettle_curve448;
/* GOST curves, visible with underscore prefix for now */
extern const struct ecc_curve _nettle_gost_gc256b;
extern const struct ecc_curve _nettle_gost_gc512a;
#define ECC_MAX_SIZE ((521 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
/* Window size for ecc_mul_a. Using 4 bits seems like a good choice,
......@@ -284,6 +289,11 @@ ecc_hash (const struct ecc_modulo *m,