diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | eddsa-verify.c | 120 | ||||
-rw-r--r-- | eddsa.h | 16 |
4 files changed, 144 insertions, 1 deletions
@@ -1,3 +1,10 @@ +2014-10-14 Niels Möller <nisse@lysator.liu.se> + + * eddsa-verify.c (_eddsa_verify, eddsa_verify_itch): New file, new + functions. + * eddsa.h: Declare new functions. + * Makefile.in (hogweed_SOURCES): Added eddsa-verify.c. + 2014-10-08 Niels Möller <nisse@lysator.liu.se> * testsuite/eddsa-sign-test.c (test_eddsa_sign): Use diff --git a/Makefile.in b/Makefile.in index f3f2b38c..7006211e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -177,7 +177,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ecc-ecdsa-verify.c ecdsa-verify.c ecdsa-keygen.c \ curve25519-mul-g.c curve25519-mul.c curve25519-eh-to-x.c \ eddsa-compress.c eddsa-decompress.c eddsa-expand.c \ - eddsa-hash.c eddsa-sign.c \ + eddsa-hash.c eddsa-sign.c eddsa-verify.c \ $(OPT_HOGWEED_SOURCES) HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \ diff --git a/eddsa-verify.c b/eddsa-verify.c new file mode 100644 index 00000000..85b751e9 --- /dev/null +++ b/eddsa-verify.c @@ -0,0 +1,120 @@ +/* eddsa-verify.c + + Copyright (C) 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 "eddsa.h" + +#include "ecc.h" +#include "ecc-internal.h" +#include "nettle-meta.h" + +/* FIXME: Use mpn_zero_p. Also duplicated in ecc-ecdsa-verify.c. */ +static int +zero_p (const mp_limb_t *xp, mp_size_t n) +{ + while (n > 0) + if (xp[--n] > 0) + return 0; + return 1; +} + +mp_size_t +_eddsa_verify_itch (const struct ecc_curve *ecc) +{ + return 8*ecc->p.size + ecc->mul_itch; +} + +int +_eddsa_verify (const struct ecc_curve *ecc, + const struct nettle_hash *H, + const uint8_t *pub, + void *ctx, + const mp_limb_t *A, + size_t length, + const uint8_t *msg, + const uint8_t *signature, + mp_limb_t *scratch) +{ + size_t nbytes; +#define R scratch +#define sp (scratch + 2*ecc->p.size) +#define hp (scratch + 3*ecc->p.size) +#define P (scratch + 5*ecc->p.size) +#define scratch_out (scratch + 8*ecc->p.size) +#define S R +#define hash ((uint8_t *) P) + + nbytes = 1 + ecc->p.bit_size / 8; + + /* Could maybe save some storage by delaying the R and S operations, + but it makes sense to check them for validity up front. */ + if (!_eddsa_decompress (ecc, R, signature, R+2*ecc->p.size)) + return 0; + + mpn_set_base256_le (sp, ecc->q.size, signature + nbytes, nbytes); + /* Check that s < q */ + if (mpn_cmp (sp, ecc->q.m, ecc->q.size) >= 0) + return 0; + + H->init (ctx); + H->update (ctx, nbytes, signature); + H->update (ctx, nbytes, pub); + H->update (ctx, length, msg); + H->digest (ctx, 2*nbytes, hash); + _eddsa_hash (&ecc->q, hp, hash); + + /* Compute h A + R - s G, which should be the neutral point */ + ecc->mul (ecc, P, hp, A, scratch_out); + /* FIXME: Introduce an ecc->add method? */ + ecc_add_eh (ecc, P, P, R, scratch_out); + /* Produces s in the range 1 <= s <= q, with no carry. */ + mpn_sub_n (hp, ecc->q.m, sp, ecc->q.size); + ecc->mul_g (ecc, S, hp, scratch_out); + ecc_add_ehh (ecc, P, P, S, scratch_out); + + /* Zero point iff x == 0 (mod p) iff (x == 0 or x == p) */ + /* FIXME: Needs to differentiate between (0,1) and (0,-1). Implement + point compare instead of the above ecc_add_ehh? + /* FIXME: Introduce zero_p method? */ + return (zero_p (P, ecc->p.size) + || mpn_cmp (P, ecc->p.m, ecc->p.size) == 0); + +#undef R +#undef sp +#undef hp +#undef P +#undef S +} @@ -50,6 +50,8 @@ extern "C" { #define _eddsa_expand_key _nettle_eddsa_expand_key #define _eddsa_sign _nettle_eddsa_sign #define _eddsa_sign_itch _nettle_eddsa_sign_itch +#define _eddsa_verify _nettle_eddsa_verify +#define _eddsa_verify_itch _nettle_eddsa_verify_itch #define ED25519_KEY_SIZE 32 @@ -88,6 +90,20 @@ _eddsa_sign (const struct ecc_curve *ecc, mp_limb_t *scratch); mp_size_t +_eddsa_verify_itch (const struct ecc_curve *ecc); + +int +_eddsa_verify (const struct ecc_curve *ecc, + const struct nettle_hash *H, + const uint8_t *pub, + void *ctx, + const mp_limb_t *A, + size_t length, + const uint8_t *msg, + const uint8_t *signature, + mp_limb_t *scratch); + +mp_size_t _eddsa_expand_key_itch (const struct ecc_curve *ecc); void |