Commit 7f2c9f75 authored by Niels Möller's avatar Niels Möller

Integrated ECDSA sign and verify functions.

parent c049b56d
2013-02-18 Niels Möller <nisse@lysator.liu.se>
* ecc-point.c: New file, struct ecc_point abstraction.
* ecc-scalar.c: New file, struct ecc_scalar abstraction.
* ecc-random.c (ecc_modq_random, ecc_scalar_random): New file, new
functions.
* ecc-hash.c (ecc_hash): New file and function.
* ecc-ecdsa-sign.c: New file, low-level signing interface.
* ecc-ecdsa-verify.c: New file, low-level ecdsa verify.
* ecdsa-sign.c: (ecdsa_sign): New file and function.
* ecdsa-verify.c (ecdsa_verify): New file and function.
* ecdsa.h: New header file.
* ecc.h: Declare ecc_point and ecc_scalar functions.
* ecc-internal.h: Added declarations.
* Makefile.in (hogweed_SOURCES): Added new source files.
(HEADERS): Added ecdsa.h.
* gmp-glue.c (_mpz_set_mpn): New convenience function.
(_mpn_set_base256): New function.
(_gmp_alloc_limbs): New function.
......
......@@ -130,12 +130,15 @@ hogweed_SOURCES = sexp.c sexp-format.c \
ecc-192.c ecc-224.c ecc-256.c ecc-384.c ecc-521.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-mul-g.c ecc-mul-a.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
HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \
base16.h base64.h buffer.h camellia.h cast128.h \
cbc.h ctr.h \
des.h des-compat.h dsa.h ecc-curve.h ecc.h \
des.h des-compat.h dsa.h ecc-curve.h ecc.h ecdsa.h \
gcm.h gosthash94.h hmac.h \
knuth-lfib.h \
macros.h \
......
/* ecc-ecdsa-sign.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"
/* Low-level ECDSA signing */
mp_size_t
ecc_ecdsa_sign_itch (const struct ecc_curve *ecc)
{
/* Needs 3*ecc->size + scratch for ecc_mul_g. */
return ECC_ECDSA_SIGN_ITCH (ecc->size);
}
/* NOTE: Caller should check if r or s is zero. */
void
ecc_ecdsa_sign (const struct ecc_curve *ecc,
const mp_limb_t *zp,
/* Random nonce, must be invertible mod ecc group
order. */
const mp_limb_t *kp,
unsigned length, const uint8_t *digest,
mp_limb_t *rp, mp_limb_t *sp,
mp_limb_t *scratch)
{
mp_limb_t cy;
#define P scratch
#define kinv scratch /* Needs 5*ecc->size for computation */
#define hp (scratch + ecc->size) /* NOTE: ecc->size + 1 limbs! */
#define tp (scratch + 2*ecc->size)
/* Procedure, according to RFC 6090, "KT-I". q denotes the group
order.
1. k <-- uniformly random, 0 < k < q
2. R <-- (r_x, r_y) = k g
3. s1 <-- r_x mod q
4. s2 <-- (h + z*s1)/k mod q.
*/
ecc_mul_g (ecc, P, kp, P + 3*ecc->size);
/* x coordinate only */
ecc_j_to_a (ecc, 3, rp, P, P + 3*ecc->size);
/* We need to reduce x coordinate mod ecc->q. It should already
be < 2*ecc->q, so one subtraction should suffice. */
cy = mpn_sub_n (scratch, rp, ecc->q, ecc->size);
cnd_copy (cy == 0, rp, scratch, ecc->size);
/* Invert k, uses 5 * ecc->size including scratch */
mpn_copyi (hp, kp, ecc->size);
ecc_modq_inv (ecc, kinv, hp, tp);
/* Process hash digest */
ecc_hash (ecc, hp, length, digest);
ecc_modq_mul (ecc, tp, zp, rp);
ecc_modq_add (ecc, hp, hp, tp);
ecc_modq_mul (ecc, tp, hp, kinv);
mpn_copyi (sp, tp, ecc->size);
#undef P
#undef hp
#undef kinv
#undef tp
}
/* ecc-ecdsa-verify.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"
/* Low-level ECDSA verify */
static int
zero_p (const mp_limb_t *xp, mp_size_t n)
{
while (n > 0)
if (xp[--n] > 0)
return 0;
return 1;
}
static int
ecdsa_in_range (const struct ecc_curve *ecc, const mp_limb_t *xp)
{
return !zero_p (xp, ecc->size)
&& mpn_cmp (xp, ecc->q, ecc->size) < 0;
}
mp_size_t
ecc_ecdsa_verify_itch (const struct ecc_curve *ecc)
{
/* Largest storage need is for the ecc_mul_a call, 6 * ecc->size +
ECC_MUL_A_ITCH (size) */
return ECC_ECDSA_VERIFY_ITCH (ecc->size);
}
/* FIXME: Use faster primitives, not requiring side-channel silence. */
int
ecc_ecdsa_verify (const struct ecc_curve *ecc,
const mp_limb_t *pp, /* Public key */
unsigned length, const uint8_t *digest,
const mp_limb_t *rp, const mp_limb_t *sp,
mp_limb_t *scratch)
{
/* Procedure, according to RFC 6090, "KT-I". q denotes the group
order.
1. Check 0 < r, s < q.
2. s' <-- s^{-1} (mod q)
3. u1 <-- h * s' (mod q)
4. u2 <-- r * s' (mod q)
5. R = u1 G + u2 Y
6. Signature is valid if R_x = r (mod q).
*/
#define P2 scratch
#define P1 (scratch + 3*ecc->size)
#define sinv (scratch + 3*ecc->size)
#define u2 (scratch + 4*ecc->size)
#define hp (scratch + 4*ecc->size)
#define u1 (scratch + 6*ecc->size)
if (! (ecdsa_in_range (ecc, rp)
&& ecdsa_in_range (ecc, sp)))
return 0;
/* FIXME: Micro optimizations: Either simultaneous multiplication.
Or convert to projective coordinates (can be done without
division, I think), and write an ecc_add_ppp. */
/* Compute sinv, use P2 as scratch */
mpn_copyi (sinv + ecc->size, sp, ecc->size);
ecc_modq_inv (ecc, sinv, sinv + ecc->size, P2);
/* u2 = r / s, P2 = u2 * Y */
ecc_modq_mul (ecc, u2, rp, sinv);
/* Total storage: 5*ecc->size + ECC_MUL_A_ITCH (ecc->size) */
ecc_mul_a (ecc, 1, P2, u2, pp, u2 + ecc->size);
/* u1 = h / s, P1 = u1 * G */
ecc_hash (ecc, hp, length, digest);
ecc_modq_mul (ecc, u1, hp, sinv);
/* u = 0 can happen only if h = 0 or h = q, which is extremely
unlikely. */
if (!zero_p (u1, ecc->size))
{
/* Total storage: 6*ecc->size + ECC_MUL_G_ITCH (ecc->size) */
ecc_mul_g (ecc, P1, u1, u1 + ecc->size);
/* NOTE: ecc_add_jjj and/or ecc_j_to_a will produce garbage in
case u1 G = +/- u2 V. However, anyone who gets his or her
hands on a signature where this happens during verification,
can also get the private key as z = +/- u1 / u_2 (mod q). And
then it doesn't matter very much if verification of
signatures with that key succeeds or fails.
u1 G = - u2 V can never happen for a correctly generated
signature, since it implies k = 0.
u1 G = u2 V is possible, if we are unlucky enough to get h /
s_1 = z. Hitting that is about as unlikely as finding the
private key by guessing.
*/
/* Total storage: 6*ecc->size + ECC_ADD_JJJ_ITCH (ecc->size) */
ecc_add_jjj (ecc, P1, P1, P2, u1);
}
ecc_j_to_a (ecc, 3, P2, P1, u1);
if (mpn_cmp (P2, ecc->q, ecc->size) >= 0)
mpn_sub_n (P2, P2, ecc->q, ecc->size);
return (mpn_cmp (rp, P2, ecc->size) == 0);
#undef P2
#undef P1
#undef sinv
#undef u2
#undef hp
#undef u1
}
/* ecdsa-hash.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 "ecc-internal.h"
#include "gmp-glue.h"
/* Convert hash value to an integer. If the digest is larger than
the ecc bit size, then we must truncate it and use the leftmost
bits. */
/* NOTE: We don't considered the hash value to be secret, so it's ok
if the running time of this conversion depends on h.
Requires ecc->size + 1 limbs, the extra limb may be needed for
unusual limb sizes.
*/
void
ecc_hash (const struct ecc_curve *ecc,
mp_limb_t *hp,
unsigned length, const uint8_t *digest)
{
if (length > ((unsigned) ecc->bit_size + 7) / 8)
length = (ecc->bit_size + 7) / 8;
_mpn_set_base256 (hp, ecc->size + 1, digest, length);
if (8 * length > ecc->bit_size)
/* We got a few extra bits, at the low end. Discard them. */
mpn_rshift (hp, hp, ecc->size + 1, 8*length - ecc->bit_size);
}
......@@ -27,6 +27,7 @@
#include <gmp.h>
#include "nettle-types.h"
#include "ecc-curve.h"
/* Name mangling */
......@@ -45,13 +46,17 @@
#define ecc_modq_mul _nettle_ecc_modq_mul
#define ecc_modq_add _nettle_ecc_modq_add
#define ecc_modq_inv _nettle_ecc_modq_inv
#define ecc_mod _nettle_ecc_mod
#define ecc_modq_random _nettle_ecc_modq_random
#define ecc_mod _nettle_ecc_mod
#define ecc_hash _nettle_ecc_hash
#define cnd_copy _nettle_cnd_copy
#define sec_add_1 _nettle_sec_add_1
#define sec_sub_1 _nettle_sec_sub_1
#define sec_tabselect _nettle_sec_tabselect
#define sec_modinv _nettle_sec_modinv
#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,
for both Intel x86_64 and ARM Cortex A9. For the larger curves, of
384 and 521 bits, we could improve seepd by a few percent if we go
......@@ -184,11 +189,20 @@ void
ecc_modq_inv (const struct ecc_curve *ecc, mp_limb_t *rp, mp_limb_t *ap,
mp_limb_t *scratch);
void
ecc_modq_random (const struct ecc_curve *ecc, mp_limb_t *xp,
void *ctx, nettle_random_func *random, mp_limb_t *scratch);
void
ecc_mod (mp_limb_t *rp, mp_size_t rn, mp_size_t mn,
const mp_limb_t *bp, mp_size_t bn,
const mp_limb_t *b_shifted, unsigned shift);
void
ecc_hash (const struct ecc_curve *ecc,
mp_limb_t *hp,
unsigned length, const uint8_t *digest);
#define cnd_add_n(cnd, rp, ap, n) \
mpn_addmul_1 ((rp), (ap), (n), (cnd) != 0)
......@@ -228,8 +242,10 @@ sec_modinv (mp_limb_t *vp, mp_limb_t *ap, mp_size_t n,
#define ECC_MUL_A_ITCH(size) \
(((3 << ECC_MUL_A_WBITS) + 11) * (size))
#endif
#define _ECDSA_SIGN_ITCH(size) (12*(size))
#define _ECDSA_VERIFY_ITCH(size) \
#define ECC_ECDSA_SIGN_ITCH(size) (12*(size))
#define ECC_ECDSA_VERIFY_ITCH(size) \
(6*(size) + ECC_MUL_A_ITCH ((size)))
#define ECC_MODQ_RANDOM_ITCH(size) (size)
#define ECC_HASH_ITCH(size) (1+(size))
#endif /* NETTLE_ECC_INTERNAL_H_INCLUDED */
/* ecc-point.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 "ecc.h"
#include "ecc-internal.h"
#include "gmp-glue.h"
void
ecc_point_init (struct ecc_point *p, const struct ecc_curve *ecc)
{
p->ecc = ecc;
p->p = _gmp_alloc_limbs (2*ecc->size);
}
void
ecc_point_clear (struct ecc_point *p)
{
_gmp_free_limbs (p->p, 2*p->ecc->size);
}
int
ecc_point_set (struct ecc_point *p, const mpz_t x, const mpz_t y)
{
mp_size_t size;
mpz_t lhs, rhs;
mpz_t t;
int res;
size = p->ecc->size;
if (mpz_sgn (x) < 0 || _mpz_cmp_limbs (x, p->ecc->p, size) >= 0
|| mpz_sgn (y) < 0 || _mpz_cmp_limbs (y, p->ecc->p, size) >= 0)
return 0;
mpz_init (lhs);
mpz_init (rhs);
/* Check that y^2 = x^3 - 3*x + b (mod p) */
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, p->ecc->b, size));
res = mpz_congruent_p (lhs, rhs, _mpz_init_mpn (t, p->ecc->p, size));
mpz_clear (lhs);
mpz_clear (rhs);
if (!res)
return 0;
_mpz_copy_limbs (p->p, x, size);
_mpz_copy_limbs (p->p + size, y, size);
return 1;
}
void
ecc_point_get (const struct ecc_point *p, mpz_t x, mpz_t y)
{
mp_size_t size = p->ecc->size;
_mpz_set_mpn (x, p->p, size);
_mpz_set_mpn (y, p->p + size, size);
}
/* ecc-random.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 "ecc.h"
#include "ecc-internal.h"
#include "gmp-glue.h"
#include "nettle-internal.h"
static int
zero_p (const struct ecc_curve *ecc,
const mp_limb_t *xp)
{
mp_limb_t t;
mp_size_t i;
for (i = t = 0; i < ecc->size; i++)
t |= xp[i];
return t == 0;
}
static int
ecdsa_in_range (const struct ecc_curve *ecc,
const mp_limb_t *xp, mp_limb_t *scratch)
{
/* Check if 0 < x < q, with data independent timing. */
return !zero_p (ecc, xp)
& (mpn_sub_n (scratch, xp, ecc->q, ecc->size) != 0);
}
void
ecc_modq_random (const struct ecc_curve *ecc, mp_limb_t *xp,
void *ctx, nettle_random_func *random, mp_limb_t *scratch)
{
uint8_t *buf = (uint8_t *) scratch;
unsigned nbytes = (ecc->bit_size + 7)/8;
/* The bytes ought to fit in the scratch area, unless we have very
unusual limb and byte sizes. */
assert (nbytes <= ecc->size * sizeof (mp_limb_t));
do
{
/* q and p are of the same bitsize. */
random (ctx, nbytes, buf);
buf[0] &= 0xff >> (nbytes * 8 - ecc->bit_size);
_mpn_set_base256 (xp, ecc->size, buf, nbytes);
}
while (!ecdsa_in_range (ecc, xp, scratch));
}
void
ecc_scalar_random (struct ecc_scalar *x,
void *random_ctx, nettle_random_func *random)
{
TMP_DECL (scratch, mp_limb_t, ECC_MODQ_RANDOM_ITCH (ECC_MAX_SIZE));
TMP_ALLOC (scratch, ECC_MODQ_RANDOM_ITCH (x->ecc->size));
ecc_modq_random (x->ecc, x->p, random_ctx, random, scratch);
}
/* ecc-scalar.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 "ecc.h"
#include "ecc-internal.h"
#include "gmp-glue.h"
void
ecc_scalar_init (struct ecc_scalar *s, const struct ecc_curve *ecc)
{
s->ecc = ecc;
s->p = _gmp_alloc_limbs (ecc->size);
}
void
ecc_scalar_clear (struct ecc_scalar *s)
{
_gmp_free_limbs (s->p, s->ecc->size);
}
int
ecc_scalar_set (struct ecc_scalar *s, const mpz_t z)
{
mp_size_t size = s->ecc->size;
if (mpz_sgn (z) <= 0 || _mpz_cmp_limbs (z, s->ecc->q, size) >= 0)
return 0;
_mpz_copy_limbs (s->p, z, size);
return 1;
}
void
ecc_scalar_get (const struct ecc_scalar *s, mpz_t z)
{
_mpz_set_mpn (z, s->p, s->ecc->size);
}
......@@ -25,15 +25,25 @@
#ifndef NETTLE_ECC_H_INCLUDED
#define NETTLE_ECC_H_INCLUDED
#include <stdint.h>
#include <gmp.h>
#include "nettle-types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Name mangling */
#define ecc_point_init nettle_ecc_point_init
#define ecc_point_clear nettle_ecc_point_clear
#define ecc_point_set nettle_ecc_point_set
#define ecc_point_get nettle_ecc_point_get
#define ecc_scalar_init nettle_ecc_scalar_init
#define ecc_scalar_clear nettle_ecc_scalar_clear
#define ecc_scalar_set nettle_ecc_scalar_set
#define ecc_scal