Commit 32ca8abc authored by Dmitry Baryshkov's avatar Dmitry Baryshkov Committed by Niels Möller

Add GOST DSA according to GOST R 34.10-2001/-2012

Add GOST Digital Signature Algorithms support according to GOST R
34.10-2001/-2012. English translations of these standards are provided
as RFC 5832 and RFC 7091.
Signed-off-by: Dmitry Baryshkov's avatarDmitry Baryshkov <dbaryshkov@gmail.com>
parent 3f2d5b73
......@@ -189,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 \
......@@ -205,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 \
......
/* 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
......@@ -288,6 +289,11 @@ ecc_hash (const struct ecc_modulo *m,
mp_limb_t *hp,
size_t length, const uint8_t *digest);
void
gost_hash (const struct ecc_modulo *m,
mp_limb_t *hp,
size_t length, const uint8_t *digest);
/* Converts a point P in affine coordinates into a point R in jacobian
coordinates. */
void
......@@ -456,6 +462,7 @@ curve448_eh_to_x (mp_limb_t *xp, const mp_limb_t *p,
#endif
#define ECC_MUL_M_ITCH(size) (11*(size))
#define ECC_ECDSA_SIGN_ITCH(size) (12*(size))
#define ECC_GOSTDSA_SIGN_ITCH(size) (12*(size))
#define ECC_MOD_RANDOM_ITCH(size) (size)
#define ECC_HASH_ITCH(size) (1+(size))
......
/* gostdsa-sign.c
Copyright (C) 2015 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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include "gostdsa.h"
#include "ecc-internal.h"
#include "nettle-internal.h"
void
gostdsa_sign (const struct ecc_scalar *key,
void *random_ctx, nettle_random_func *random,
size_t digest_length,
const uint8_t *digest,
struct dsa_signature *signature)
{
/* At most 936 bytes. */
TMP_DECL(k, mp_limb_t, ECC_MAX_SIZE + ECC_GOSTDSA_SIGN_ITCH (ECC_MAX_SIZE));
mp_limb_t size = key->ecc->p.size;
mp_limb_t *rp = mpz_limbs_write (signature->r, size);
mp_limb_t *sp = mpz_limbs_write (signature->s, size);
TMP_ALLOC (k, size + ECC_GOSTDSA_SIGN_ITCH (size));
/* Timing reveals the number of rounds through this loop, but the
timing is still independent of the secret k finally used. */
do
{
do
{
ecc_mod_random (&key->ecc->q, k, random_ctx, random, k + size);
}
while (mpn_zero_p(k, size));
ecc_gostdsa_sign (key->ecc, key->p, k, digest_length, digest,
rp, sp, k + size);
mpz_limbs_finish (signature->r, size);
mpz_limbs_finish (signature->s, size);
}
while (mpz_sgn (signature->r) == 0 || mpz_sgn (signature->s) == 0);
}
/* gostdsa-verify.c
Copyright (C) 2015 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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include "gostdsa.h"
#include "gmp-glue.h"
int
gostdsa_verify (const struct ecc_point *pub,
size_t length, const uint8_t *digest,
const struct dsa_signature *signature)
{
mp_limb_t size = ecc_size (pub->ecc);
mp_size_t itch = 2*size + ecc_gostdsa_verify_itch (pub->ecc);
/* For ECC_MUL_A_WBITS == 0, at most 1512 bytes. With
ECC_MUL_A_WBITS == 4, currently needs 67 * ecc->size, at most
4824 bytes. Don't use stack allocation for this. */
mp_limb_t *scratch;
int res;
#define rp scratch
#define sp (scratch + size)
#define scratch_out (scratch + 2*size)
if (mpz_sgn (signature->r) <= 0 || mpz_size (signature->r) > size
|| mpz_sgn (signature->s) <= 0 || mpz_size (signature->s) > size)
return 0;
scratch = gmp_alloc_limbs (itch);
mpz_limbs_copy (rp, signature->r, size);
mpz_limbs_copy (sp, signature->s, size);
res = ecc_gostdsa_verify (pub->ecc, pub->p, length, digest, rp, sp, scratch_out);
gmp_free_limbs (scratch, itch);
return res;
#undef rp
#undef sp
#undef scratch_out
}
/* gostdsa.h
Copyright (C) 2015 Dmity 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/.
*/
#ifndef NETTLE_GOSTDSA_H_INCLUDED
#define NETTLE_GOSTDSA_H_INCLUDED
#include "ecc.h"
#include "dsa.h"
#include "ecdsa.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Name mangling */
#define gostdsa_sign nettle_gostdsa_sign
#define gostdsa_verify nettle_gostdsa_verify
#define ecc_gostdsa_sign nettle_ecc_gostdsa_sign
#define ecc_gostdsa_sign_itch nettle_ecc_gostdsa_sign_itch
#define ecc_gostdsa_verify nettle_ecc_gostdsa_verify
#define ecc_gostdsa_verify_itch nettle_ecc_gostdsa_verify_itch
/* Just use ECDSA function for key generation */
#define gostdsa_generate_keypair ecdsa_generate_keypair
/* High level GOST DSA functions.
*
* A public key is represented as a struct ecc_point, and a private
* key as a struct ecc_scalar. FIXME: Introduce some aliases? */
void
gostdsa_sign (const struct ecc_scalar *key,
void *random_ctx, nettle_random_func *random,
size_t digest_length,
const uint8_t *digest,
struct dsa_signature *signature);
int
gostdsa_verify (const struct ecc_point *pub,
size_t length, const uint8_t *digest,
const struct dsa_signature *signature);
/* Low-level GOSTDSA functions. */
mp_size_t
ecc_gostdsa_sign_itch (const struct ecc_curve *ecc);
void
ecc_gostdsa_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,
size_t length, const uint8_t *digest,
mp_limb_t *rp, mp_limb_t *sp,
mp_limb_t *scratch);
mp_size_t
ecc_gostdsa_verify_itch (const struct ecc_curve *ecc);
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);
#ifdef __cplusplus
}
#endif
#endif /* NETTLE_GOSTDSA_H_INCLUDED */
......@@ -43,6 +43,9 @@
/eddsa-sign-test
/eddsa-verify-test
/gcm-test
/gostdsa-keygen-test
/gostdsa-sign-test
/gostdsa-verify-test
/gosthash94-test
/hkdf-test
/hmac-test
......
......@@ -289,6 +289,15 @@ ed25519-test$(EXEEXT): ed25519-test.$(OBJEXT)
ed448-test$(EXEEXT): ed448-test.$(OBJEXT)
$(LINK) ed448-test.$(OBJEXT) $(TEST_OBJS) -o ed448-test$(EXEEXT)
gostdsa-sign-test$(EXEEXT): gostdsa-sign-test.$(OBJEXT)
$(LINK) gostdsa-sign-test.$(OBJEXT) $(TEST_OBJS) -o gostdsa-sign-test$(EXEEXT)
gostdsa-verify-test$(EXEEXT): gostdsa-verify-test.$(OBJEXT)
$(LINK) gostdsa-verify-test.$(OBJEXT) $(TEST_OBJS) -o gostdsa-verify-test$(EXEEXT)
gostdsa-keygen-test$(EXEEXT): gostdsa-keygen-test.$(OBJEXT)
$(LINK) gostdsa-keygen-test.$(OBJEXT) $(TEST_OBJS) -o gostdsa-keygen-test$(EXEEXT)
sha1-huge-test$(EXEEXT): sha1-huge-test.$(OBJEXT)
$(LINK) sha1-huge-test.$(OBJEXT) $(TEST_OBJS) -o sha1-huge-test$(EXEEXT)
......
......@@ -53,7 +53,9 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
ecdsa-sign-test.c ecdsa-verify-test.c \
ecdsa-keygen-test.c ecdh-test.c \
eddsa-compress-test.c eddsa-sign-test.c \
eddsa-verify-test.c ed25519-test.c ed448-test.c
eddsa-verify-test.c ed25519-test.c ed448-test.c \
gostdsa-sign-test.c gostdsa-verify-test.c \
gostdsa-keygen-test.c
TS_SOURCES = $(TS_NETTLE_SOURCES) $(TS_HOGWEED_SOURCES)
CXX_SOURCES = cxx-test.cxx
......
#include "testutils.h"
#include "gostdsa.h"
#include "knuth-lfib.h"
/* Check if y^2 = x^3 - 3x + b */
static int
ecc_valid_p (struct ecc_point *pub)
{
mpz_t t, x, y;
mpz_t lhs, rhs;
int res;
mp_size_t size;
size = pub->ecc->p.size;
/* First check range */
if (mpn_cmp (pub->p, pub->ecc->p.m, size) >= 0
|| mpn_cmp (pub->p + size, pub->ecc->p.m, size) >= 0)
return 0;
mpz_init (lhs);
mpz_init (rhs);
mpz_roinit_n (x, pub->p, size);
mpz_roinit_n (y, pub->p + size, size);
mpz_mul (lhs, y, y);
if (pub->ecc->p.bit_size == 255)
{
/* Check that
121666 (1 + x^2 - y^2) = 121665 x^2 y^2 */
mpz_t x2;
mpz_init (x2);
mpz_mul (x2, x, x); /* x^2 */
mpz_mul (rhs, x2, lhs); /* x^2 y^2 */
mpz_sub (lhs, x2, lhs); /* x^2 - y^2 */
mpz_add_ui (lhs, lhs, 1); /* 1 + x^2 - y^2 */
mpz_mul_ui (lhs, lhs, 121666);
mpz_mul_ui (rhs, rhs, 121665);
mpz_clear (x2);
}
else if (pub->ecc->p.bit_size == 448)
{
/* Check that
x^2 + y^2 = 1 - 39081 x^2 y^2 */
mpz_t x2, d;
mpz_init (x2);
mpz_init_set_ui (d, 39081);
mpz_mul (x2, x, x); /* x^2 */
mpz_mul (d, d, x2); /* 39081 x^2 */
mpz_set_ui (rhs, 1);
mpz_submul (rhs, d, lhs); /* 1 - 39081 x^2 y^2 */
mpz_add (lhs, x2, lhs); /* x^2 + y^2 */
mpz_clear (d);
mpz_clear (x2);
}
else
{
/* Check y^2 = x^3 - 3 x + b */
mpz_mul (rhs, x, x);
mpz_sub_ui (rhs, rhs, 3);
mpz_mul (rhs, rhs, x);
mpz_add (rhs, rhs, mpz_roinit_n (t, pub->ecc->b, size));
}
res = mpz_congruent_p (lhs, rhs, mpz_roinit_n (t, pub->ecc->p.m, size));
mpz_clear (lhs);
mpz_clear (rhs);
return res;
}
void
test_main (void)
{
unsigned i;
struct knuth_lfib_ctx rctx;
struct dsa_signature signature;
struct tstring *digest;
knuth_lfib_init (&rctx, 4711);
dsa_signature_init (&signature);
digest = SHEX (/* sha256("abc") */
"BA7816BF 8F01CFEA 414140DE 5DAE2223"
"B00361A3 96177A9C B410FF61 F20015AD");
for (i = 0; ecc_curves[i]; i++)
{
const struct ecc_curve *ecc = ecc_curves[i];
struct ecc_point pub;
struct ecc_scalar key;
if (ecc->p.bit_size == 255 || ecc->p.bit_size == 448)
/* Exclude curve25519 and curve448, not supported with GOSTDSA. */
continue;
if (verbose)
fprintf (stderr, "Curve %d\n", ecc->p.bit_size);
ecc_point_init (&pub, ecc);
ecc_scalar_init (&key, ecc);
ecdsa_generate_keypair (&pub, &key,
&rctx,
(nettle_random_func *) knuth_lfib_random);
if (verbose)
{
fprintf (stderr, "Public key:\nx = ");
write_mpn (stderr, 16, pub.p, ecc->p.size);
fprintf (stderr, "\ny = ");
write_mpn (stderr, 16, pub.p + ecc->p.size, ecc->p.size);
fprintf (stderr, "\nPrivate key: ");
write_mpn (stderr, 16, key.p, ecc->p.size);
fprintf (stderr, "\n");
}
if (!ecc_valid_p (&pub))
die ("gostdsa_generate_keypair produced an invalid point.\n");
gostdsa_sign (&key,
&rctx, (nettle_random_func *) knuth_lfib_random,
digest->length, digest->data,
&signature);
if (!gostdsa_verify (&pub, digest->length, digest->data,
&signature))
die ("gostdsa_verify failed.\n");
digest->data[3] ^= 17;
if (gostdsa_verify (&pub, digest->length, digest->data,
&signature))
die ("gostdsa_verify returned success with invalid digest.\n");
digest->data[3] ^= 17;
mpz_combit (signature.r, 117);
if (gostdsa_verify (&pub, digest->length, digest->data,
&signature))
die ("gostdsa_verify returned success with invalid signature.r.\n");
mpz_combit (signature.r, 117);
mpz_combit (signature.s, 93);
if (gostdsa_verify (&pub, digest->length, digest->data,
&signature))
die ("gostdsa_verify returned success with invalid signature.s.\n");
ecc_point_clear (&pub);
ecc_scalar_clear (&key);
}
dsa_signature_clear (&signature);
}
#include "testutils.h"
#include "gostdsa.h"
static void
test_gostdsa (const struct ecc_curve *ecc,
/* Private key */
const char *sz,
/* Random nonce */
const char *sk,
/* Hash */