Page MenuHome GnuPG

No OneTemporary

diff --git a/cipher/ecc.c b/cipher/ecc.c
index 14fff812..6f650708 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1,1994 +1,2019 @@
/* ecc.c - ECElGamal Public Key encryption & ECDSA signature algorithm
* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of 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.
*
* GnuPG 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 a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/* TODO wk
- Check whether we can LGPL the code.
*/
/* This code is a based on the
* Patch 0.1.6 for the gnupg 1.4.x branch
* as retrieved on 2007-03-21 from
* http://www.calcurco.cat/eccGnuPG/src/gnupg-1.4.6-ecc0.2.0beta1.diff.bz2
*
* Written by
* Sergi Blanch i Torne <d4372211 at alumnes.eup.udl.es>,
* Ramiro Moreno Chiral <ramiro at eup.udl.es>
* Maintainers
* Sergi Blanch i Torne
* Ramiro Moreno Chiral
* Mikael Mylnikov (mmr)
*/
/*
* This module are under development, it would not have to be used
* in a production environments. It can have bugs!
*
* Made work:
* alex: found a bug over the passphrase.
* mmr: signature bug found and solved (afine conversion).
* mmr: found too many mistakes in the mathematical background transcription.
* mmr: improve the mathematical performance.
* mmr: solve ECElGamal IFP weakness.
* more polite gen_k() and its calls.
* mmr: extend the check_secret_key()
* In process:
* gen_big_point(): Randomize the point generation.
* improve te memory uses.
* Separation between sign & encrypt keys to facility the subkeys creation.
* read & reread the code in a bug search!
* To do:
* 2-isogeny: randomize the elliptic curves.
* E(F_{2^m})
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
/*
ECC over F_p; E(F_p)
T=(p,a,b,G,n,h)
p: big odd number
a,b: curve generators
G: Subgroup generator point
n: big int, in G order
h: cofactor
y^2=x^3+ax+b --> (Y^2)Z=X^3+aX(Z^2)+b(Z^3)
Q=[d]G, 1<=d<=n-1
*/
/* Point representation in projective coordinates. */
typedef struct
{
gcry_mpi_t x_;
gcry_mpi_t y_;
gcry_mpi_t z_;
} point_t;
/* Definition of a curve. */
typedef struct
{
gcry_mpi_t p_; /* Prime specifying the field GF(p). */
gcry_mpi_t a_; /* First coefficient of the Weierstrass equation. */
gcry_mpi_t b_; /* Second coefficient of teh Weierstrass equation. */
point_t G; /* Base point (generator). */
gcry_mpi_t n_; /* Order of G. */
/*gcry_mpi_t h_; =1 fixme: We will need to change this value in 2-isogeny */
-} elliptic_curve_t; /* Fixme: doubtful name */
+} elliptic_curve_t; /* Fixme: doubtful name */
typedef struct
{
elliptic_curve_t E;
- point_t Q; /* Q=[d]G */
-} ECC_public_key; /* Q */
+ point_t Q; /* Q=[d]G */
+} ECC_public_key; /* Q */
typedef struct
{
elliptic_curve_t E;
- point_t Q; /* Q=[d]G */
+ point_t Q; /* Q=[d]G */
gcry_mpi_t d;
-} ECC_secret_key; /* d */
+} ECC_secret_key; /* d */
/* This static table defines all available curves. */
static const struct
{
const char *desc; /* Description of the curve. */
unsigned int nbits; /* Number of bits. */
const char *p, *a, *b, *n; /* Parameters. */
const char *g_x, *g_y; /* G_z is always 1. */
} domain_parms[] =
{
{
"NIST P-192", 192,
"0xfffffffffffffffffffffffffffffffeffffffffffffffff",
"0xfffffffffffffffffffffffffffffffefffffffffffffffc",
"0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
"0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
"0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
"0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
},
{
"NIST P-224", 224,
"0xffffffffffffffffffffffffffffffff000000000000000000000001",
"0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
"0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
"0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
"0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
"0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
},
{
"NIST P-256", 256,
"0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
"0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
"0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
"0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
},
{
"NIST P-384", 384,
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
"ffffffff0000000000000000ffffffff",
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
"ffffffff0000000000000000fffffffc",
"0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
"c656398d8a2ed19d2a85c8edd3ec2aef",
"0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
"581a0db248b0a77aecec196accc52973",
"0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
"5502f25dbf55296c3a545e3872760ab7",
"0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
"0a60b1ce1d7e819d7a431d7c90ea0e5f"
},
{
"NIST P-521", 521,
"0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
"0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
"9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
"0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
"0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
"baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
"62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
},
{ NULL, 0, NULL, NULL, NULL, NULL }
};
/* Registered progress function and its callback value. */
static void (*progress_cb) (void *, const char*, int, int, int);
static void *progress_cb_data;
/* Local prototypes. */
static gcry_mpi_t gen_k (gcry_mpi_t p, int secure);
static void test_keys (ECC_secret_key * sk, unsigned int nbits);
static int check_secret_key (ECC_secret_key * sk);
-static void sign (gcry_mpi_t input, ECC_secret_key * skey, gcry_mpi_t * r, gcry_mpi_t * s);
-static int verify (gcry_mpi_t input, ECC_public_key * pkey, gcry_mpi_t r, gcry_mpi_t s);
+static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey,
+ gcry_mpi_t r, gcry_mpi_t s);
+static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey,
+ gcry_mpi_t r, gcry_mpi_t s);
static int point_at_infinity (point_t query);
static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
void
_gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
int, int, int),
- void *cb_data)
+ void *cb_data)
{
progress_cb = cb;
progress_cb_data = cb_data;
}
static void
progress (int c)
{
if (progress_cb)
progress_cb (progress_cb_data, "pk_dsa", c, 0, 0);
else
fputc (c, stderr);
}
/*
O B J E C T M A I N T E N A N C E
*/
/* Intialize a point object, so that its elements may be sued directly
as MPI functions. point_free is required for each initialzied
point. */
static void
point_init (point_t *P)
{
P->x_ = mpi_new (0);
P->y_ = mpi_new (0);
P->z_ = mpi_new (0);
}
/*
* Release a point object.
*/
static void
point_free (point_t *P)
{
mpi_free (P->x_); P->x_ = NULL;
mpi_free (P->y_); P->y_ = NULL;
mpi_free (P->z_); P->z_ = NULL;
}
/*
* Return a copy of a point object.
*/
static point_t
point_copy (point_t P)
{
point_t R;
R.x_ = mpi_copy (P.x_);
R.y_ = mpi_copy (P.y_);
R.z_ = mpi_copy (P.z_);
return R;
}
/*
* Release a curve object.
*/
static void
curve_free (elliptic_curve_t *E)
{
mpi_free (E->p_); E->p_ = NULL;
mpi_free (E->a_); E->a_ = NULL;
mpi_free (E->b_); E->b_ = NULL;
point_free (&E->G);
mpi_free (E->n_); E->n_ = NULL;
}
/*
* Return a copy of a curve object.
*/
static elliptic_curve_t
curve_copy (elliptic_curve_t E)
{
elliptic_curve_t R;
R.p_ = mpi_copy (E.p_);
R.a_ = mpi_copy (E.a_);
R.b_ = mpi_copy (E.b_);
R.G = point_copy (E.G);
R.n_ = mpi_copy (E.n_);
return R;
}
/*
A D D I T I O N A L M P I F U N C T I O N S
*/
/****************
* Find, if it exist, the square root of one integer modulo a big prime.
* Return the square root or NULL if it is not found.
*/
#if 0
static gcry_mpi_t
exist_square_root (gcry_mpi_t integer, gcry_mpi_t modulus)
{
unsigned long int i = 0;
gcry_mpi_t one, two, three, four, five, eight;
gcry_mpi_t k, r, z, k1;
gcry_mpi_t t1, t2, t3, t4;
one = mpi_alloc_set_ui (1);
two = mpi_alloc_set_ui (2);
three = mpi_alloc_set_ui (3);
four = mpi_alloc_set_ui (4);
five = mpi_alloc_set_ui (5);
eight = mpi_alloc_set_ui (8);
k = mpi_alloc (mpi_get_nlimbs (modulus));
r = mpi_alloc (mpi_get_nlimbs (modulus));
z = mpi_alloc (mpi_get_nlimbs (modulus));
k1 = mpi_alloc (mpi_get_nlimbs (modulus));
t1 = mpi_alloc (mpi_get_nlimbs (modulus));
t2 = mpi_alloc (mpi_get_nlimbs (modulus));
t3 = mpi_alloc (mpi_get_nlimbs (modulus));
t4 = mpi_alloc (mpi_get_nlimbs (modulus));
if (DBG_CIPHER)
log_mpidump ("?exist Square Root of ", integer);
mpi_fdiv_qr (k, r, modulus, four);
if (mpi_cmp (r, three))
- { /* p=3 (mod 4) */
+ { /* p=3 (mod 4) */
mpi_addm (k1, k, one, modulus);
mpi_powm (z, integer, k1, modulus);
if (DBG_CIPHER)
- {
- log_mpidump ("z=", z);
- }
- return z; /* value found */
+ {
+ log_mpidump ("z=", z);
+ }
+ return z; /* value found */
}
mpi_fdiv_qr (k, r, modulus, eight);
if (mpi_cmp (r, five))
- { /* p=5 (mod 8) */
+ { /* p=5 (mod 8) */
mpi_mulm (t1, two, integer, modulus);
mpi_powm (t2, t1, k, modulus);
mpi_powm (t2, t2, two, modulus);
mpi_mulm (t2, t1, t2, modulus);
mpi_mulm (t3, integer, t1, modulus);
mpi_subm (t4, t2, one, modulus);
mpi_mulm (z, t3, t4, modulus);
if (DBG_CIPHER)
- {
- log_mpidump ("z=", z);
- }
- return z; /* value found */
+ {
+ log_mpidump ("z=", z);
+ }
+ return z; /* value found */
}
if (mpi_cmp (r, one))
- { /* p=1 (mod 8) */
+ { /* p=1 (mod 8) */
while (i < 0xFF)
- { /* while not find z after 256 iterations */
- if (DBG_CIPHER)
- log_debug ("Square root bucle.\n");
- t1 = mpi_copy (integer);
- t2 = gen_k (modulus, 0);
- mpi_add_ui (t3, modulus, 1); /* t3=p+1 */
- mpi_rshift (t3, t3, 1); /* t3=t3/2 */
- lucas (t1, t2, t3, modulus, t4, t3); /* t4=V_k */
- mpi_rshift (z, t4, 1); /* z=V/2 */
- mpi_sub_ui (t3, modulus, 1); /* t3=p-1 */
- mpi_rshift (t4, t3, 2); /* t4=t3/2 */
- lucas (t1, t2, t4, modulus, t4, t1); /* t1=Q_0 */
- mpi_powm (t2, z, two, modulus); /* t2=z^2 */
- if (mpi_cmp (t1, integer))
- {
- if (DBG_CIPHER)
- {
- log_mpidump ("z=", z);
- }
- return z; /* value found */
- }
- if (t4 > mpi_alloc_set_ui (1) && t4 < t3)
- {
- if (DBG_CIPHER)
- log_debug ("Rejected.\n");
- return (0); /* NULL */
- }
- if (DBG_CIPHER)
- log_debug ("Another loop.\n");
- }
+ { /* while not find z after 256 iterations */
+ if (DBG_CIPHER)
+ log_debug ("Square root bucle.\n");
+ t1 = mpi_copy (integer);
+ t2 = gen_k (modulus, 0);
+ mpi_add_ui (t3, modulus, 1); /* t3=p+1 */
+ mpi_rshift (t3, t3, 1); /* t3=t3/2 */
+ lucas (t1, t2, t3, modulus, t4, t3); /* t4=V_k */
+ mpi_rshift (z, t4, 1); /* z=V/2 */
+ mpi_sub_ui (t3, modulus, 1); /* t3=p-1 */
+ mpi_rshift (t4, t3, 2); /* t4=t3/2 */
+ lucas (t1, t2, t4, modulus, t4, t1); /* t1=Q_0 */
+ mpi_powm (t2, z, two, modulus); /* t2=z^2 */
+ if (mpi_cmp (t1, integer))
+ {
+ if (DBG_CIPHER)
+ {
+ log_mpidump ("z=", z);
+ }
+ return z; /* value found */
+ }
+ if (t4 > mpi_alloc_set_ui (1) && t4 < t3)
+ {
+ if (DBG_CIPHER)
+ log_debug ("Rejected.\n");
+ return (0); /* NULL */
+ }
+ if (DBG_CIPHER)
+ log_debug ("Another loop.\n");
+ }
}
if (DBG_CIPHER)
log_debug ("iterations limit.\n");
- return (0); /* because this algorithm not always finish. */
+ return (0); /* because this algorithm not always finish. */
}
#endif /*0*/
/****************
* Formal definition:
* V_0 = 2; V_1 = p
* V_k = (p*V_(k-1)) - (q*V_(k-2)) for k >= 2
*/
#if 0
static void
lucas (gcry_mpi_t n, gcry_mpi_t p_, gcry_mpi_t q_,
gcry_mpi_t k, gcry_mpi_t V_n, gcry_mpi_t Q_0)
{
gcry_mpi_t v0, v1, q0, q1;
gcry_mpi_t t1, t2;
unsigned int r, i;
v0 = mpi_alloc_set_ui (2);
v1 = mpi_copy (p_);
q0 = mpi_alloc_set_ui (1);
q1 = mpi_alloc_set_ui (1);
t1 = mpi_alloc_set_ui (0);
t2 = mpi_alloc_set_ui (0);
if (DBG_CIPHER)
{
log_debug ("Generating lucas sequence.\n");
log_mpidump ("k=", k);
}
r = mpi_get_nbits (k) - 1;
i = 0;
while (mpi_test_bit (k, i) != 1)
- { /* search the first bit with value '1' */
+ { /* search the first bit with value '1' */
i++;
}
while (i < r)
{
if (DBG_CIPHER)
- {
- log_debug ("Lucas sequence bucle.\n");
- log_mpidump ("i=", mpi_alloc_set_ui (i));
- log_mpidump ("r=", mpi_alloc_set_ui (r));
- }
+ {
+ log_debug ("Lucas sequence bucle.\n");
+ log_mpidump ("i=", mpi_alloc_set_ui (i));
+ log_mpidump ("r=", mpi_alloc_set_ui (r));
+ }
mpi_mulm (q0, q0, q1, n);
if (mpi_test_bit (k, i) == 1)
- {
- mpi_mulm (q1, q0, q_, n);
- mpi_mul (t1, v0, v1);
- mpi_mul (t2, p_, q0);
- mpi_subm (v0, t1, t2, n);
- mpi_powm (t1, v1, mpi_alloc_set_ui (2), n);
- mpi_mul (t2, mpi_alloc_set_ui (2), q1);
- mpi_subm (v1, t1, t2, n);
- }
+ {
+ mpi_mulm (q1, q0, q_, n);
+ mpi_mul (t1, v0, v1);
+ mpi_mul (t2, p_, q0);
+ mpi_subm (v0, t1, t2, n);
+ mpi_powm (t1, v1, mpi_alloc_set_ui (2), n);
+ mpi_mul (t2, mpi_alloc_set_ui (2), q1);
+ mpi_subm (v1, t1, t2, n);
+ }
else
- {
- q1 = mpi_copy (q0);
- mpi_mul (t1, v0, v1);
- mpi_mul (t2, p_, q0);
- mpi_subm (v1, t1, t2, n);
- mpi_powm (t1, v0, mpi_alloc_set_ui (2), n);
- mpi_mul (t2, mpi_alloc_set_ui (2), q0);
- mpi_subm (v0, t1, t2, n);
- }
+ {
+ q1 = mpi_copy (q0);
+ mpi_mul (t1, v0, v1);
+ mpi_mul (t2, p_, q0);
+ mpi_subm (v1, t1, t2, n);
+ mpi_powm (t1, v0, mpi_alloc_set_ui (2), n);
+ mpi_mul (t2, mpi_alloc_set_ui (2), q0);
+ mpi_subm (v0, t1, t2, n);
+ }
i++;
}
V_n = mpi_copy (v0);
Q_0 = mpi_copy (q0);
if (DBG_CIPHER)
{
log_debug ("Lucas sequence generated.\n");
log_mpidump ("V_n=", V_n);
log_mpidump ("Q_0=", Q_0);
}
}
#endif /*0*/
/*
P O I N T A N D C U R V E O P E R A T I O N S
*/
/* fixme:
* The point at infinity is needed to make
* a group structure to the elliptic curve.
* Know if one point is it, is needed so
* much times in this code.
*
* return true(1), false(0), or error(-1) for an invalid point
*/
static int
point_at_infinity (point_t query)
{
if (!mpi_cmp_ui (query.z_, 0)) /* Z == 0 */
{
if ( /*mpi_cmp_ui(Query.x_,0) && */ mpi_cmp_ui (query.y_, 0))
- {
- /* X && Y != 0 & Z == 0 */
+ {
+ /* X && Y != 0 & Z == 0 */
/* Fixme: The above condition is not asserted. We may get
to here if X is 0 ! */
- if (DBG_CIPHER)
- log_debug ("True:It is a Point at Infinite.\n");
- return 1;
- }
+ if (DBG_CIPHER)
+ log_debug ("True:It is a Point at Infinite.\n");
+ return 1;
+ }
if (DBG_CIPHER)
- log_debug ("Error:It isn't an elliptic curve valid point.\n");
+ log_debug ("Error:It isn't an elliptic curve valid point.\n");
return -1;
}
return 0; /* It is a valid curve point, but not the point at infinity. */
}
/*
- * Turn a projective coordinate to affine, return 0 (or 1 in error case).
- * Returns 0 on success.
+ * Turn a projective coordinate P to affine.
+ * Returns 0 on success and the affine coordinates at X and Y.
*
* Note, that Y is never used as we can do without it.
*/
static int
point_affine (point_t *P, gcry_mpi_t x, gcry_mpi_t y, elliptic_curve_t *base)
{
gcry_mpi_t z1, z2, z3;
- z1 = mpi_new (0);
- z2 = mpi_new (0);
- z3 = mpi_new (0);
-
if (point_at_infinity (*P))
{
if (DBG_CIPHER)
- log_debug ("ecc point_affine: "
+ log_debug ("ecc point_affine: "
"Point at Infinity does NOT exist in the affine plane!\n");
return 1;
}
- mpi_invm (z1, P->z_, base->p_); /* z1 =Z^{-1} (mod p) */
- mpi_mulm (z2, z1, z1, base->p_); /* z2 =Z^(-2) (mod p) */
- mpi_mulm (z3, z2, z1, base->p_); /* z3 =Z^(-3) (mod p) */
+ z1 = mpi_new (0);
+ z2 = mpi_new (0);
+ z3 = mpi_new (0);
+
+ mpi_invm (z1, P->z_, base->p_); /* z1 =Z^{-1} (mod p) */
+ mpi_mulm (z2, z1, z1, base->p_); /* z2 =Z^(-2) (mod p) */
+ mpi_mulm (z3, z2, z1, base->p_); /* z3 =Z^(-3) (mod p) */
mpi_mulm (x, P->x_, z2, base->p_);
mpi_mulm (y, P->y_, z3, base->p_);
mpi_free (z1);
mpi_free (z2);
mpi_free (z3);
return 0;
}
/*
* The point inversion over F_p is a simple modular inversion of the Y
* coordinate.
*/
static void
invert_point (point_t *P, elliptic_curve_t *base)
{
- mpi_subm (P->y_, base->p_, P->y_, base->p_); /* y = p - y mod p */
+ mpi_subm (P->y_, base->p_, P->y_, base->p_); /* y = p - y mod p */
}
/*
* Scalar multiplication of one point, with the integer fixed to 2.
* R = 2P
*/
static void
duplicate_point (point_t *R, point_t *P, elliptic_curve_t * base)
{
gcry_mpi_t one, two, three, four, eight;
gcry_mpi_t p, p_3, a;
gcry_mpi_t t1, t2, t3, t4, t5, t6, t7;
gcry_mpi_t aux;
one = mpi_alloc_set_ui (1);
two = mpi_alloc_set_ui (2);
three = mpi_alloc_set_ui (3);
four = mpi_alloc_set_ui (4);
eight = mpi_alloc_set_ui (8);
p = mpi_copy (base->p_);
p_3 = mpi_alloc (mpi_get_nlimbs (p));
mpi_sub_ui (p_3, p, 3);
a = mpi_copy (base->a_);
t1 = mpi_alloc (mpi_get_nlimbs (p));
t2 = mpi_alloc (mpi_get_nlimbs (p));
t3 = mpi_alloc (mpi_get_nlimbs (p));
t4 = mpi_alloc (mpi_get_nlimbs (p));
t5 = mpi_alloc (mpi_get_nlimbs (p));
t6 = mpi_alloc (mpi_get_nlimbs (p));
t7 = mpi_alloc (mpi_get_nlimbs (p));
aux = mpi_alloc (mpi_get_nlimbs (p));
- t1 = mpi_copy (P->x_); /* t1=x1 */
- t2 = mpi_copy (P->y_); /* t2=y1 */
- t3 = mpi_copy (P->z_); /* t3=z1 */
+ t1 = mpi_copy (P->x_); /* t1=x1 */
+ t2 = mpi_copy (P->y_); /* t2=y1 */
+ t3 = mpi_copy (P->z_); /* t3=z1 */
if (!mpi_cmp_ui (t2, 0) || !mpi_cmp_ui (t3, 0))
- { /* t2==0 | t3==0 => [1:1:0] */
+ { /* t2==0 | t3==0 => [1:1:0] */
mpi_set_ui (R->x_, 1);
mpi_set_ui (R->y_, 1);
mpi_set_ui (R->z_, 0);
}
else
{
- mpi_mod (a, a, p); /* a mod p */
+ mpi_mod (a, a, p); /* a mod p */
if (!mpi_cmp (a, p_3))
- { /* a==p-3 */
- mpi_powm (t4, t3, two, p); /* t4=t3^2 mod p */
- mpi_subm (t5, t1, t4, p); /* t5=t1-t4 mod p */
- mpi_addm (t4, t1, t4, p); /* t4=t1+t4 mod p */
- mpi_mulm (t5, t4, t5, p); /* t5=t4*t5 mod p */
- mpi_mulm (t4, three, t5, p); /* t4=3*t5 mod p */
- }
+ { /* a==p-3 */
+ mpi_powm (t4, t3, two, p); /* t4=t3^2 mod p */
+ mpi_subm (t5, t1, t4, p); /* t5=t1-t4 mod p */
+ mpi_addm (t4, t1, t4, p); /* t4=t1+t4 mod p */
+ mpi_mulm (t5, t4, t5, p); /* t5=t4*t5 mod p */
+ mpi_mulm (t4, three, t5, p); /* t4=3*t5 mod p */
+ }
else
- {
- t4 = mpi_copy (a); /* t4=a */
- mpi_powm (t5, t3, two, p); /* t5=t3^2 mod p */
- mpi_powm (t5, t5, two, p); /* t5=t5^2 mod p */
- mpi_mulm (t5, t4, t5, p); /* t5=t4*t5 mod p */
- mpi_powm (t4, t1, two, p); /* t4=t1^2 mod p */
- mpi_mulm (t4, three, t4, p); /* t4=3*t4 mod p */
- mpi_addm (t4, t4, t5, p); /* t4=t4+t5 mod p */
- }
- mpi_mulm (t3, t2, t3, p); /* t3=t2*t3 mod p */
- mpi_mulm (t3, two, t3, p); /* t3=2*t3 mod p */
- mpi_powm (aux, t2, two, p); /* t2=t2^2 mod p */
+ {
+ t4 = mpi_copy (a); /* t4=a */
+ mpi_powm (t5, t3, two, p); /* t5=t3^2 mod p */
+ mpi_powm (t5, t5, two, p); /* t5=t5^2 mod p */
+ mpi_mulm (t5, t4, t5, p); /* t5=t4*t5 mod p */
+ mpi_powm (t4, t1, two, p); /* t4=t1^2 mod p */
+ mpi_mulm (t4, three, t4, p); /* t4=3*t4 mod p */
+ mpi_addm (t4, t4, t5, p); /* t4=t4+t5 mod p */
+ }
+ mpi_mulm (t3, t2, t3, p); /* t3=t2*t3 mod p */
+ mpi_mulm (t3, two, t3, p); /* t3=2*t3 mod p */
+ mpi_powm (aux, t2, two, p); /* t2=t2^2 mod p */
t2 = mpi_copy (aux);
- mpi_mulm (t5, t1, t2, p); /* t5=t1*t2 mod p */
- mpi_mulm (t5, four, t5, p); /* t5=4*t5 mod p */
- mpi_powm (t1, t4, two, p); /* t1=t4^2 mod p */
+ mpi_mulm (t5, t1, t2, p); /* t5=t1*t2 mod p */
+ mpi_mulm (t5, four, t5, p); /* t5=4*t5 mod p */
+ mpi_powm (t1, t4, two, p); /* t1=t4^2 mod p */
mpi_mulm (aux, two, t5, p);
- mpi_subm (t1, t1, aux, p); /* t1=t1-2*t5 mod p */
- mpi_powm (aux, t2, two, p); /* t2=t2^2 mod p */
+ mpi_subm (t1, t1, aux, p); /* t1=t1-2*t5 mod p */
+ mpi_powm (aux, t2, two, p); /* t2=t2^2 mod p */
t2 = mpi_copy (aux);
- mpi_mulm (t2, eight, t2, p); /* t2=8*t2 mod p */
- mpi_subm (t5, t5, t1, p); /* t5=t5-t1 mod p */
- mpi_mulm (t5, t4, t5, p); /* t5=t4*t5 mod p */
- mpi_subm (t2, t5, t2, p); /* t2=t5-t2 mod p */
+ mpi_mulm (t2, eight, t2, p); /* t2=8*t2 mod p */
+ mpi_subm (t5, t5, t1, p); /* t5=t5-t1 mod p */
+ mpi_mulm (t5, t4, t5, p); /* t5=t4*t5 mod p */
+ mpi_subm (t2, t5, t2, p); /* t2=t5-t2 mod p */
mpi_set (R->x_, t1);
mpi_set (R->y_, t2);
mpi_set (R->z_, t3);
}
mpi_free (aux);
mpi_free (t7);
mpi_free (t6);
mpi_free (t5);
mpi_free (t4);
mpi_free (t3);
mpi_free (t2);
mpi_free (t1);
mpi_free (p);
mpi_free (p_3);
mpi_free (a);
mpi_free (eight);
mpi_free (four);
mpi_free (three);
mpi_free (two);
mpi_free (one);
}
/*
Point addition is the group operation.
R = P0 + P1
*/
static void
sum_points (point_t *R, point_t *P0, point_t *P1, elliptic_curve_t * base)
{
gcry_mpi_t one, two;
gcry_mpi_t p;
gcry_mpi_t t1, t2, t3, t4, t5, t6, t7;
unsigned int nbits;
one = mpi_alloc_set_ui (1);
two = mpi_alloc_set_ui (2);
p = mpi_copy (base->p_);
nbits = mpi_get_nbits (p);
t1 = mpi_new (nbits);
t2 = mpi_new (nbits);
t3 = mpi_new (nbits);
t4 = mpi_new (nbits);
t5 = mpi_new (nbits);
t6 = mpi_new (nbits);
t7 = mpi_new (nbits);
if ( (!mpi_cmp (P1->x_, P0->x_))
&& (!mpi_cmp (P1->y_, P0->y_))
&& (!mpi_cmp (P1->z_, P0->z_)) ) /* P1 == P0 */
- {
+ {
duplicate_point (R, P0, base);
}
else if (point_at_infinity (*P0)) /* R == 0 && P1 == P1 */
- {
+ {
/* (!mpi_cmp_ui(P0->y_,0) || !mpi_cmp_ui(P0->z_,0))*/
mpi_set (R->x_, P1->x_);
mpi_set (R->y_, P1->y_);
mpi_set (R->z_, P1->z_);
}
else if (point_at_infinity (*P1)) /* R == P0 && P0 == 0 */
- {
+ {
/* (!mpi_cmp_ui(P1->y_,0) || !mpi_cmp_ui(P1->z_,0)) */
mpi_set (R->x_, P0->x_);
mpi_set (R->y_, P0->y_);
mpi_set (R->z_, P0->z_);
}
else
{
- t1 = mpi_copy (P0->x_); /* t1=x0 */
- t2 = mpi_copy (P0->y_); /* t2=y0 */
- t3 = mpi_copy (P0->z_); /* t3=z0 */
- t4 = mpi_copy (P1->x_); /* t4=x1 */
- t5 = mpi_copy (P1->y_); /* t5=y2 */
+ t1 = mpi_copy (P0->x_); /* t1=x0 */
+ t2 = mpi_copy (P0->y_); /* t2=y0 */
+ t3 = mpi_copy (P0->z_); /* t3=z0 */
+ t4 = mpi_copy (P1->x_); /* t4=x1 */
+ t5 = mpi_copy (P1->y_); /* t5=y2 */
if (mpi_cmp (P1->z_, one)) /* z1 != 1 */
- {
+ {
/* fixme: Release old t6 or just set it. */
- t6 = mpi_copy (P1->z_); /* t6=z1 */
- mpi_powm (t7, t6, two, p); /* t7=t6^2 mod p */
- mpi_mulm (t1, t1, t7, p); /* t1=t1*t7 mod p */
- mpi_mulm (t7, t6, t7, p); /* t7=t6*t7 mod p */
- mpi_mulm (t2, t2, t7, p); /* t2=t2*t7 mod p */
- }
+ t6 = mpi_copy (P1->z_); /* t6=z1 */
+ mpi_powm (t7, t6, two, p); /* t7=t6^2 mod p */
+ mpi_mulm (t1, t1, t7, p); /* t1=t1*t7 mod p */
+ mpi_mulm (t7, t6, t7, p); /* t7=t6*t7 mod p */
+ mpi_mulm (t2, t2, t7, p); /* t2=t2*t7 mod p */
+ }
mpi_powm (t7, t3, two, p);/* t7=t3^2 mod p */
- mpi_mulm (t4, t4, t7, p); /* t4=t4*t7 mod p */
- mpi_mulm (t7, t3, t7, p); /* t7=t3*t7 mod p */
- mpi_mulm (t5, t5, t7, p); /* t5=t5*t7 mod p */
- mpi_subm (t4, t1, t4, p); /* t4=t1-t4 mod p */
- mpi_subm (t5, t2, t5, p); /* t5=t2-t5 mod p */
+ mpi_mulm (t4, t4, t7, p); /* t4=t4*t7 mod p */
+ mpi_mulm (t7, t3, t7, p); /* t7=t3*t7 mod p */
+ mpi_mulm (t5, t5, t7, p); /* t5=t5*t7 mod p */
+ mpi_subm (t4, t1, t4, p); /* t4=t1-t4 mod p */
+ mpi_subm (t5, t2, t5, p); /* t5=t2-t5 mod p */
if (!mpi_cmp_ui (t4, 0)) /* t4==0 */
- {
- if (!mpi_cmp_ui (t5, 0))
- {
+ {
+ if (!mpi_cmp_ui (t5, 0))
+ {
/* return (0:0:0), it has a special mean. */
- if (DBG_CIPHER)
- log_debug ("ecc sum_points: [0:0:0]!\n");
+ if (DBG_CIPHER)
+ log_debug ("ecc sum_points: [0:0:0]!\n");
mpi_set_ui (R->x_, 0);
mpi_set_ui (R->y_, 0);
mpi_set_ui (R->z_, 0);
- }
- else
- {
- if (DBG_CIPHER)
- log_debug ("ecc sum_points: [1:1:0]!\n");
+ }
+ else
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc sum_points: [1:1:0]!\n");
mpi_set_ui (R->x_, 1);
mpi_set_ui (R->y_, 1);
mpi_set_ui (R->z_, 0);
- }
- }
+ }
+ }
else
- {
- mpi_mulm (t1, two, t1, p);
- mpi_subm (t1, t1, t4, p); /* t1=2*t1-t4 mod p */
- mpi_mulm (t2, two, t2, p);
- mpi_subm (t2, t2, t5, p); /* t2=2*t2-t5 mod p */
- if (mpi_cmp (P1->z_, one)) /* z1 != 1 */
- {
- mpi_mulm (t3, t3, t6, p); /* t3=t3*t6 */
- }
- mpi_mulm (t3, t3, t4, p); /* t3=t3*t4 mod p */
- mpi_powm (t7, t4, two, p); /* t7=t4^2 mod p */
- mpi_mulm (t4, t4, t7, p); /* t4=t4*t7 mod p */
- mpi_mulm (t7, t1, t7, p); /* t7=t1*t7 mod p */
- mpi_powm (t1, t5, two, p); /* t1=t5^2 mod p */
- mpi_subm (t1, t1, t7, p); /* t1=t1-t7 mod p */
- mpi_mulm (t6, two, t1, p);
- mpi_subm (t7, t7, t6, p); /* t7=t7-2*t1 mod p */
- mpi_mulm (t5, t5, t7, p); /* t5=t5*t7 mod p */
- mpi_mulm (t4, t2, t4, p); /* t4=t2*t4 mod p */
- mpi_subm (t2, t5, t4, p); /* t2=t5-t4 mod p */
- mpi_invm (t6, two, p);
- mpi_mulm (t2, t2, t6, p); /* t2 = t2/2 */
-
- mpi_set (R->x_, t1);
- mpi_set (R->y_, t2);
- mpi_set (R->z_, t3);
- }
+ {
+ mpi_mulm (t1, two, t1, p);
+ mpi_subm (t1, t1, t4, p); /* t1=2*t1-t4 mod p */
+ mpi_mulm (t2, two, t2, p);
+ mpi_subm (t2, t2, t5, p); /* t2=2*t2-t5 mod p */
+ if (mpi_cmp (P1->z_, one)) /* z1 != 1 */
+ {
+ mpi_mulm (t3, t3, t6, p); /* t3=t3*t6 */
+ }
+ mpi_mulm (t3, t3, t4, p); /* t3=t3*t4 mod p */
+ mpi_powm (t7, t4, two, p); /* t7=t4^2 mod p */
+ mpi_mulm (t4, t4, t7, p); /* t4=t4*t7 mod p */
+ mpi_mulm (t7, t1, t7, p); /* t7=t1*t7 mod p */
+ mpi_powm (t1, t5, two, p); /* t1=t5^2 mod p */
+ mpi_subm (t1, t1, t7, p); /* t1=t1-t7 mod p */
+ mpi_mulm (t6, two, t1, p);
+ mpi_subm (t7, t7, t6, p); /* t7=t7-2*t1 mod p */
+ mpi_mulm (t5, t5, t7, p); /* t5=t5*t7 mod p */
+ mpi_mulm (t4, t2, t4, p); /* t4=t2*t4 mod p */
+ mpi_subm (t2, t5, t4, p); /* t2=t5-t4 mod p */
+ mpi_invm (t6, two, p);
+ mpi_mulm (t2, t2, t6, p); /* t2 = t2/2 */
+
+ mpi_set (R->x_, t1);
+ mpi_set (R->y_, t2);
+ mpi_set (R->z_, t3);
+ }
}
mpi_free (t7);
mpi_free (t6);
mpi_free (t5);
mpi_free (t4);
mpi_free (t3);
mpi_free (t2);
mpi_free (t1);
mpi_free (p);
mpi_free (two);
mpi_free (one);
}
/****************
* The modular power used without EC,
* is this function over EC.
return R = escalarP
ESCALAR = input
P = input
BASE = input
R = output (caller must have intialized this point)
*/
static void
escalar_mult (point_t *R, gcry_mpi_t escalar, point_t *P,
elliptic_curve_t *base)
{
gcry_mpi_t one, two, three;
gcry_mpi_t p;
gcry_mpi_t x1, y1, z1, z2, z3, k, h;
gcry_mpi_t xx, yy, zz;
unsigned int i, loops;
point_t P1, P2, P1_;
if (DBG_CIPHER)
log_debug ("escalar_mult: begin\n");
one = mpi_alloc_set_ui (1);
two = mpi_alloc_set_ui (2);
three = mpi_alloc_set_ui (3);
p = mpi_copy (base->p_);
x1 = mpi_alloc_like (P->x_);
y1 = mpi_alloc_like (P->y_);
/* z1 is not yet intialized. */
z2 = mpi_alloc_like (P->z_);
z3 = mpi_alloc_like (P->z_);
/* k is not yet intialized. */
h = mpi_alloc_like (P->z_);
if (!mpi_cmp_ui (escalar, 0) || mpi_cmp_ui (P->z_, 0))
- { /* n=0 | Z=0 => [1:1:0] */
+ { /* n=0 | Z=0 => [1:1:0] */
mpi_set_ui (R->x_, 1);
mpi_set_ui (R->y_, 1);
mpi_set_ui (R->z_, 0);
}
xx = mpi_copy (P->x_);
zz = mpi_copy (P->z_);
z1 = mpi_copy (one);
if (mpi_is_neg (escalar))
- { /* (-n)P=n(-P) */
- escalar->sign = 0; /* +n */
+ { /* (-n)P=n(-P) */
+ escalar->sign = 0; /* +n */
k = mpi_copy (escalar);
- yy = mpi_copy (P->y_); /* -P */
+ yy = mpi_copy (P->y_); /* -P */
mpi_invm (yy, yy, p);
}
else
{
k = mpi_copy (escalar);
yy = mpi_copy (P->y_);
}
if (!mpi_cmp (zz, one))
- { /* zz==1 */
+ { /* zz==1 */
x1 = mpi_copy (xx);
y1 = mpi_copy (yy);
}
else
{
- mpi_mulm (z2, zz, zz, p); /* z^2 */
- mpi_mulm (z3, zz, z2, p); /* z^3 */
- mpi_invm (z2, z2, p); /* 1/Z^2 */
- mpi_mulm (x1, xx, z2, p); /* xx/z^2 */
- mpi_invm (z3, z3, p); /* 1/z^3 */
- mpi_mulm (y1, yy, z3, p); /* yy/z^3 */
+ mpi_mulm (z2, zz, zz, p); /* z^2 */
+ mpi_mulm (z3, zz, z2, p); /* z^3 */
+ mpi_invm (z2, z2, p); /* 1/Z^2 */
+ mpi_mulm (x1, xx, z2, p); /* xx/z^2 */
+ mpi_invm (z3, z3, p); /* 1/z^3 */
+ mpi_mulm (y1, yy, z3, p); /* yy/z^3 */
}
- mpi_mul (h, three, k); /* h=3k */
+ mpi_mul (h, three, k); /* h=3k */
loops = mpi_get_nbits (h);
- i = loops - 2; /* i = l-1 = loops-2 */
+ i = loops - 2; /* i = l-1 = loops-2 */
mpi_set (R->x_, xx);
mpi_set (R->y_, yy);
mpi_set (R->z_, zz);
P1.x_ = mpi_copy (x1);
P1.y_ = mpi_copy (y1);
P1.z_ = mpi_copy (z1);
while (i > 0)
- { /* A.10.9. step 11 i from l-1 downto 1 */
+ { /* A.10.9. step 11 i from l-1 downto 1 */
duplicate_point (R, R, base);
if (mpi_test_bit (h, i) == 1 && mpi_test_bit (k, i) == 0)
- { /* h_i=1 & k_i=0 */
- P2 = point_copy (*R);
- sum_points (R, &P2, &P1, base); /* R=P2+P1 over the base elliptic curve */
- }
+ { /* h_i=1 & k_i=0 */
+ P2 = point_copy (*R);
+ sum_points (R, &P2, &P1, base); /* R=P2+P1 over the base elliptic curve */
+ }
if (mpi_test_bit (h, i) == 0 && mpi_test_bit (k, i) == 1)
- { /* h_i=0 & k_i=1 */
- P2 = point_copy (*R);
- P1_ = point_copy (P1);
- invert_point (&P1_, base);
- sum_points (R, &P2, &P1_, base); /* R=P2+P1_ over the base elliptic curve */
- }
+ { /* h_i=0 & k_i=1 */
+ P2 = point_copy (*R);
+ P1_ = point_copy (P1);
+ invert_point (&P1_, base);
+ sum_points (R, &P2, &P1_, base); /* R=P2+P1_ over the base elliptic curve */
+ }
i--;
}
if (DBG_CIPHER)
log_debug ("escalar_mult: ready\n");
point_free (&P1);
point_free (&P2);
point_free (&P1_);
mpi_free (h);
mpi_free (k);
mpi_free (z3);
mpi_free (z2);
mpi_free (z1);
mpi_free (y1);
mpi_free (x1);
mpi_free (zz);
mpi_free (yy);
mpi_free (xx);
mpi_free (p);
mpi_free (three);
mpi_free (two);
mpi_free (one);
}
/****************
* Solve the right side of the equation that defines a curve.
*/
static gcry_mpi_t
gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
{
gcry_mpi_t three;
gcry_mpi_t x_3, ax, axb, y;
gcry_mpi_t a, b, p;
unsigned int nbits;
three = mpi_alloc_set_ui (3);
a = mpi_copy (base->a_);
b = mpi_copy (base->b_);
p = mpi_copy (base->p_);
nbits = mpi_get_nbits (p);
x_3 = mpi_new (nbits);
ax = mpi_new (nbits);
axb = mpi_new (nbits);
y = mpi_new (nbits);
if (DBG_CIPHER)
log_debug ("ecc gen_y_2: Solving an elliptic equation.\n");
- mpi_powm (x_3, x, three, p); /* x_3=x^3 mod p */
- mpi_mulm (ax, a, x, p); /* ax=a*x mod p */
- mpi_addm (axb, ax, b, p); /* axb=ax+b mod p */
- mpi_addm (y, x_3, axb, p); /* y=x^3+ax+b mod p */
+ mpi_powm (x_3, x, three, p); /* x_3=x^3 mod p */
+ mpi_mulm (ax, a, x, p); /* ax=a*x mod p */
+ mpi_addm (axb, ax, b, p); /* axb=ax+b mod p */
+ mpi_addm (y, x_3, axb, p); /* y=x^3+ax+b mod p */
if (DBG_CIPHER)
log_debug ("ecc gen_y_2: Solved.\n");
return y; /* The quadratic value of the coordinate if it exist. */
}
/*
E C C C O R E F U N C T I O N S
*/
/* Generate a random secret scalar k with an order of p
At the beginning this was identical to the code is in elgamal.c.
Later imporved by mmr. Further simplified by wk. */
static gcry_mpi_t
gen_k (gcry_mpi_t p, int secure)
{
gcry_mpi_t k;
unsigned int nbits;
nbits = mpi_get_nbits (p);
k = (secure
? mpi_alloc_secure ( mpi_get_nlimbs (p) )
: mpi_alloc ( mpi_get_nlimbs (p) ));
if (DBG_CIPHER)
log_debug ("choosing a random k of %u bits\n", nbits);
gcry_mpi_randomize (k, nbits, GCRY_STRONG_RANDOM);
mpi_mod (k, k, p); /* k = k mod p */
if (DBG_CIPHER)
progress ('\n');
return k;
}
/* Helper to scan a hex string. */
static gcry_mpi_t
scanval (const char *string)
{
gpg_error_t err;
gcry_mpi_t val;
err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
if (err)
log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err));
return val;
}
/****************
* Generate the crypto system setup.
* As of now the fix NIST recommended values are used.
* The subgroup generator point is in another function: gen_big_point.
*/
static gpg_err_code_t
generate_curve (unsigned int nbits, elliptic_curve_t *curve)
{
int idx;
for (idx = 0; domain_parms[idx].desc; idx++)
if (nbits == domain_parms[idx].nbits)
break;
if (!domain_parms[idx].desc)
return GPG_ERR_INV_VALUE;
curve->p_ = scanval (domain_parms[idx].p);
curve->a_ = scanval (domain_parms[idx].a);
curve->b_ = scanval (domain_parms[idx].b);
curve->n_ = scanval (domain_parms[idx].n);
curve->G.x_ = scanval (domain_parms[idx].g_x);
curve->G.y_ = scanval (domain_parms[idx].g_y);
curve->G.z_ = mpi_alloc_set_ui (1);
/* Gx, Gy, Gz are planned to be generated by code like this:
if ( gen_big_point (&curve->n_, curve, &curve->G, nbits) == -1)
{
log_fatal ("ECC operation: Point generation failed\n");
}
A point of order 'n' is needed to generate a cyclic subgroup.
Over this cyclic subgroup it's defined the ECDLP. Now it use a
fix values from NIST FIPS PUB 186-2. Returns -1 if it isn't
possible.
static int
gen_big_point (gcry_mpi_t * prime, elliptic_curve_t * base, point_t * G,
unsigned int nbits)
{
unsigned int i=0;
gcry_mpi_t one;
point_t Big, P;
one = mpi_alloc_set_ui(1);
G->x_ = mpi_alloc(mpi_get_nlimbs(*prime));
G->y_ = mpi_alloc(mpi_get_nlimbs(*prime));
G->z_ = mpi_alloc(mpi_get_nlimbs(*prime));
if( DBG_CIPHER )log_debug("Generating a Big point.\n");
do{
do{
*P = genPoint(*prime,*base);
}while(PointAtInfinity(*P));//A random point in the curve that it's not PaI
escalarMult(base.h,&P,&G,&base);//cofactor (1 o 2), could be improved
}while(PointAtInfinity(G));
if( DBG_CIPHER )log_debug("Big point generated.\n");
if( DBG_CIPHER ){
log_mpidump("Gx=",G->x_);log_mpidump("Gy=",G->y_);log_mpidump("Gz=",G->z_);
}
return 0;
}
*/
if (DBG_CIPHER)
{
progress ('\n');
log_mpidump ("ecc generation p= ", curve->p_);
log_mpidump ("ecc generation a= ", curve->a_);
log_mpidump ("ecc generation b= ", curve->b_);
log_mpidump ("ecc generation n= ", curve->n_);
log_mpidump ("ecc generation Gx= ", curve->G.x_);
log_mpidump ("ecc generation Gy= ", curve->G.y_);
log_mpidump ("ecc generation Gz= ", curve->G.z_);
}
if (DBG_CIPHER)
progress ('\n');
return 0;
}
/****************
* First obtain the setup. Over the finite field randomize an scalar
* secret value, and calculate the public point.
*/
static gpg_err_code_t
generate_key (ECC_secret_key *sk, unsigned int nbits)
{
gpg_err_code_t err;
elliptic_curve_t E;
gcry_mpi_t d;
point_t Q, G;
err = generate_curve (nbits, &E);
if (err)
return err;
d = mpi_snew (nbits);
if (DBG_CIPHER)
log_debug ("choosing a random x of size %u\n", nbits);
- d = gen_k (E.n_, 2); /* generate_secret_prime(nbits); */
+ d = gen_k (E.n_, 2); /* generate_secret_prime(nbits); */
G = point_copy (E.G);
/* Compute Q. */
point_init (&Q);
escalar_mult (&Q, d, &E.G, &E);
/* Copy the stuff to the key structures. */
sk->E.p_ = mpi_copy (E.p_);
sk->E.a_ = mpi_copy (E.a_);
sk->E.b_ = mpi_copy (E.b_);
sk->E.G = point_copy (E.G);
sk->E.n_ = mpi_copy (E.n_);
sk->Q = point_copy (Q);
sk->d = mpi_copy (d);
/* Now we can test our keys (this should never fail!). */
test_keys (sk, nbits - 64);
point_free (&Q);
mpi_free (d);
curve_free (&E);
return 0;
}
/****************
* To verify correct skey it use a random information.
* First, encrypt and decrypt this dummy value,
* test if the information is recuperated.
* Second, test with the sign and verify functions.
*/
static void
test_keys (ECC_secret_key *sk, unsigned int nbits)
{
ECC_public_key pk;
gcry_mpi_t test = mpi_new (nbits);
point_t R_;
gcry_mpi_t c = mpi_new (nbits);
gcry_mpi_t out = mpi_new (nbits);
gcry_mpi_t r = mpi_new (nbits);
gcry_mpi_t s = mpi_new (nbits);
if (DBG_CIPHER)
log_debug ("Testing key.\n");
point_init (&R_);
pk.E = curve_copy (sk->E);
pk.Q = point_copy (sk->Q);
gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
#if 0
doEncrypt (test, &pk, &R_, c);
out = decrypt (out, sk, R_, c);
- if (mpi_cmp (test, out)) /* test!=out */
+ if (mpi_cmp (test, out)) /* test!=out */
log_fatal ("ECELG operation: encrypt, decrypt failed\n");
if (DBG_CIPHER)
log_debug ("ECELG operation: encrypt, decrypt ok.\n");
#endif
- sign (test, sk, &r, &s);
+ if (sign (test, sk, r, s) )
+ log_fatal ("ECDSA operation: sign failed\n");
- if (!verify (test, &pk, r, s))
+ if (verify (test, &pk, r, s))
{
log_fatal ("ECDSA operation: sign, verify failed\n");
}
if (DBG_CIPHER)
log_debug ("ECDSA operation: sign, verify ok.\n");
point_free (&pk.Q);
curve_free (&pk.E);
point_free (&R_);
mpi_free (s);
mpi_free (r);
mpi_free (out);
mpi_free (c);
mpi_free (test);
}
/****************
* To check the validity of the value, recalculate the correspondence
* between the public value and de secret one.
*/
static int
check_secret_key (ECC_secret_key * sk)
{
point_t Q;
gcry_mpi_t y_2, y2 = mpi_alloc (0);
/* ?primarity test of 'p' */
/* (...) //!! */
/* G in E(F_p) */
- y_2 = gen_y_2 (sk->E.G.x_, &sk->E); /* y^2=x^3+a*x+b */
- mpi_mulm (y2, sk->E.G.y_, sk->E.G.y_, sk->E.p_); /* y^2=y*y */
+ y_2 = gen_y_2 (sk->E.G.x_, &sk->E); /* y^2=x^3+a*x+b */
+ mpi_mulm (y2, sk->E.G.y_, sk->E.G.y_, sk->E.p_); /* y^2=y*y */
if (mpi_cmp (y_2, y2))
{
if (DBG_CIPHER)
- log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
+ log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
return (1);
}
/* G != PaI */
if (point_at_infinity (sk->E.G))
{
if (DBG_CIPHER)
- log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
+ log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
return (1);
}
/* ?primarity test of 'n' */
/* (...) //!! */
/* ?(p-sqrt(p)) < n < (p+sqrt(p)) */
/* ?n!=p */
/* ?(n^k) mod p !=1 for k=1 to 31 (from GOST) or k=1 to 50 (from MIRACL) */
/* Q=[n]G over E = PaI */
point_init (&Q);
escalar_mult (&Q, sk->E.n_, &sk->E.G, &sk->E);
if (!point_at_infinity (Q))
{
if (DBG_CIPHER)
- log_debug ("check_secret_key: E is not a curve of order n\n");
+ log_debug ("check_secret_key: E is not a curve of order n\n");
point_free (&Q);
return 1;
}
/* pubkey cannot be PaI */
if (point_at_infinity (sk->Q))
{
if (DBG_CIPHER)
- log_debug ("Bad check: Q can not be a Point at Infinity!\n");
+ log_debug ("Bad check: Q can not be a Point at Infinity!\n");
return (1);
}
/* pubkey = [d]G over E */
escalar_mult (&Q, sk->d, &sk->E.G, &sk->E);
if ((Q.x_ == sk->Q.x_) && (Q.y_ == sk->Q.y_) && (Q.z_ == sk->Q.z_))
{
if (DBG_CIPHER)
- log_debug
- ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
+ log_debug
+ ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
return (1);
}
point_free (&Q);
return 0;
}
#if 0
/****************
* Encrypt a number and obtain and struct (R,c)
*/
static void
doEncrypt (gcry_mpi_t input, ECC_public_key * pkey, point_t * R, gcry_mpi_t c)
{
gcry_mpi_t k, p, x, y;
point_t P, Q, G;
elliptic_curve_t E;
k = mpi_alloc (0);
p = mpi_copy (pkey->E.p_);
x = mpi_alloc (0);
y = mpi_alloc (0);
Q = point_copy (pkey->Q);
G = point_copy (pkey->E.G);
E = curve_copy (pkey->E);
- k = gen_k (p, 1); /* 2nd parametre: how much security? */
- escalarMult (k, &Q, &P, &E); /* P=[k]Q=[k]([d]G) */
- escalarMult (k, &G, R, &E); /* R=[k]G */
+ k = gen_k (p, 1); /* 2nd parametre: how much security? */
+ escalarMult (k, &Q, &P, &E); /* P=[k]Q=[k]([d]G) */
+ escalarMult (k, &G, R, &E); /* R=[k]G */
/* IFP weakness//mpi_mul(c,input,Q.x_);//c=input*Q_x */
/* MMR Use affine conversion befor extract x-coordinate */
if (point_affine (&P, x, y, &E))
- { /* Q cannot turn to affine coordinate */
+ { /* Q cannot turn to affine coordinate */
if (DBG_CIPHER)
- {
- log_debug ("Encrypting: Cannot turn to affine.\n");
- }
+ {
+ log_debug ("Encrypting: Cannot turn to affine.\n");
+ }
}
/* MMR According to the standard P1363 we can not use x-coordinate directly. */
/* It is necessary to add hash-operation later. */
/* As the maximal length of a key for the symmetric cipher is 256 bit it is possible to take hash-function SHA256. */
sha256_hashing (x, &x);
aes256_encrypting (x, input, &c);
if (DBG_CIPHER)
{
log_debug ("doEncrypt: end.\n");
}
}
#endif /*0*/
#if 0
/****************
* Undo the ciphertext
*/
static gcry_mpi_t
decrypt (gcry_mpi_t output, ECC_secret_key * skey, point_t R, gcry_mpi_t c)
{
gcry_mpi_t p, inv, x, y;
point_t P, Q;
elliptic_curve_t E;
p = mpi_copy (skey->E.p_);
inv = mpi_alloc (0);
x = mpi_alloc (0);
y = mpi_alloc (0);
Q = point_copy (skey->Q);
E = curve_copy (skey->E);
- escalarMult (skey->d, &R, &P, &E); /* P=[d]R */
+ escalarMult (skey->d, &R, &P, &E); /* P=[d]R */
/* That is like: mpi_fdiv_q(output,c,Q.x_); */
/* IFP weakness//mpi_invm(inv,Q.x_,p);//inv=Q{_x}^-1 (mod p) */
/* IFP weakness//mpi_mulm(output,c,inv,p);//output=c*inv (mod p) */
/* MMR Use affine conversion befor extract x-coordinate */
if (point_affine (&P, x, y, &E))
- { /* Q cannot turn to affine coordinate */
+ { /* Q cannot turn to affine coordinate */
if (DBG_CIPHER)
- {
- log_debug ("Encrypting: Cannot turn to affine.\n");
- }
+ {
+ log_debug ("Encrypting: Cannot turn to affine.\n");
+ }
}
sha256_hashing (x, &x);
aes256_decrypting (x, c, &output);
if (DBG_CIPHER)
{
log_debug ("decrypt: end.\n");
}
return (output);
}
#endif /*0*/
-/****************
- * Return the signature struct (r,s) from the message hash.
+
+/*
+ * Return the signature struct (r,s) from the message hash. The caller
+ * must have allocated R and S.
*/
-static void
-sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t *r, gcry_mpi_t *s)
+static gpg_err_code_t
+sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s)
{
+ gpg_err_code_t err = 0;
gcry_mpi_t k, i, dr, sum, k_1, x, y;
point_t G, I;
elliptic_curve_t E;
- k = mpi_alloc (0);
- i = mpi_alloc (0);
+ k = NULL;
+ i = mpi_alloc (0); /* Fixme: we could do trivially without it. */
dr = mpi_alloc (0);
sum = mpi_alloc (0);
k_1 = mpi_alloc (0);
x = mpi_alloc (0);
y = mpi_alloc (0);
G = point_copy (skey->E.G);
E = curve_copy (skey->E);
- *r = mpi_alloc (0);
- *s = mpi_alloc (0);
-
point_init (&I);
- while (!mpi_cmp_ui (*s, 0)) /* s == 0 */
- {
- while (!mpi_cmp_ui (*r, 0)) /* r == 0 */
- {
- k = gen_k (E.p_, 1);
- escalar_mult (&I, k, &G, &E); /* I = [k]G */
- if (point_affine (&I, x, y, &E))
- {
- if (DBG_CIPHER)
+ mpi_set_ui (s, 0);
+ mpi_set_ui (r, 0);
+
+ while (!mpi_cmp_ui (s, 0)) /* s == 0 */
+ {
+ while (!mpi_cmp_ui (r, 0)) /* r == 0 */
+ {
+ /* Note, that we are guaranteed to enter this loop at least
+ once because r has been intialized to 0. We casn use a
+ do_while because we want to keep the value of R value
+ even if S has to be recomputed. */
+ mpi_free (k);
+ k = gen_k (E.p_, 1);
+ escalar_mult (&I, k, &G, &E); /* I = [k]G */
+ if (point_affine (&I, x, y, &E))
+ {
+ if (DBG_CIPHER)
log_debug ("ecc sign: Cannot turn to affine. "
" Cannot complete sign.\n");
- /* FIXME: Shouldn't we return an error now? */
- }
- i = mpi_copy (x); /* i = I_x */
- mpi_mod (*r, i, E.n_); /* r = i mod n */
- /* Fixme: release k, i and I? */
- }
- mpi_mulm (dr, skey->d, *r, E.n_); /* dr = d*r mod n */
- mpi_addm (sum, input, dr, E.n_); /* sum = hash + (d*r) mod n */
- mpi_invm (k_1, k, E.n_); /* k_1 = k^(-1) mod n */
- mpi_mulm (*s, k_1, sum, E.n_); /* s = k^(-1)*(hash+(d*r)) mod n */
+ err = GPG_ERR_BAD_SIGNATURE;
+ goto leave;
+ }
+ mpi_set (i, x); /* i = I_x */
+ mpi_mod (r, i, E.n_); /* r = i mod n */
+ }
+ mpi_mulm (dr, skey->d, r, E.n_); /* dr = d*r mod n */
+ mpi_addm (sum, input, dr, E.n_); /* sum = hash + (d*r) mod n */
+ mpi_invm (k_1, k, E.n_); /* k_1 = k^(-1) mod n */
+ mpi_mulm (s, k_1, sum, E.n_); /* s = k^(-1)*(hash+(d*r)) mod n */
}
- if (DBG_CIPHER)
- log_debug ("ess sign: end\n");
- /* Fixme: What about releasing G and E? */
+ /* Fixme: What about releasing G and E? Why do we need copies at all? */
+ leave:
+ point_free (&I);
mpi_free (y);
mpi_free (x);
mpi_free (k_1);
mpi_free (sum);
mpi_free (dr);
mpi_free (i);
mpi_free (k);
+
+ return err;
}
-/****************
- * Check if the struct (r,s) is for the hash value that it have.
- * Returns: 0 = does not verify
- * 1 = verifies.
+/*
+ * Check if R and S verifies INPUT.
*/
-static int
+static gpg_err_code_t
verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
{
- gcry_mpi_t r_, s_, h, h1, h2, i, x, y;
+ gpg_err_code_t err = 0;
+ gcry_mpi_t h, h1, h2, x, y;
point_t Q, Q1, Q2, G;
elliptic_curve_t E;
- /* Fixme: we need to release quite some values. */
+ /* Check that the input parameters are valid. */
+ {
+ gcry_mpi_t r_ = mpi_alloc_like (r);
+ gcry_mpi_t s_ = mpi_alloc_like (s);
+ mpi_mod (r_, r, pkey->E.n_); /* r = r mod E_n */
+ mpi_mod (s_, s, pkey->E.n_); /* s = s mod E_n */
+ err = (mpi_cmp (r_, r) || mpi_cmp (s_, s));
+ mpi_free (r_);
+ mpi_free (s_);
+ if (err)
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc verification: No valid values.\n");
+ return GPG_ERR_BAD_SIGNATURE;
+ }
+ }
- r_ = mpi_alloc (0);
- s_ = mpi_alloc (0);
- h = mpi_alloc (0);
+ h = mpi_alloc (0);
h1 = mpi_alloc (0);
h2 = mpi_alloc (0);
x = mpi_alloc (0);
y = mpi_alloc (0);
- G = point_copy (pkey->E.G);
- E = curve_copy (pkey->E);
-
- mpi_mod (r_, r, pkey->E.n_); /* r = r mod E_n */
- mpi_mod (s_, s, pkey->E.n_); /* s = s mod E_n */
-
- /* Check that the input parameters are valid. */
- if (mpi_cmp (r_, r) || mpi_cmp (s_, s)) /* r_ != r || s_ != s */
- {
- if (DBG_CIPHER)
- log_debug ("ecc verification: No valid values.\n");
- return 0;
- }
-
point_init (&Q);
point_init (&Q1);
point_init (&Q2);
-
- mpi_invm (h, s, E.n_); /* h = s^(-1) (mod n) */
- mpi_mulm (h1, input, h, E.n_); /* h1 = hash * s^(-1) (mod n) */
- escalar_mult (&Q1, h1, &G, &E); /* Q1 = [ hash * s^(-1) ]G */
- mpi_mulm (h2, r, h, E.n_); /* h2 = r * s^(-1) (mod n) */
- escalar_mult (&Q2, h2, &pkey->Q, &E); /* Q2 = [ r * s^(-1) ]Q */
+ G = point_copy (pkey->E.G); /* Fixme: We don't need the copy. */
+ E = curve_copy (pkey->E); /* Fixme: We don't need the copy. */
+
+ mpi_invm (h, s, E.n_); /* h = s^(-1) (mod n) */
+ mpi_mulm (h1, input, h, E.n_); /* h1 = hash * s^(-1) (mod n) */
+ escalar_mult (&Q1, h1, &G, &E); /* Q1 = [ hash * s^(-1) ]G */
+ mpi_mulm (h2, r, h, E.n_); /* h2 = r * s^(-1) (mod n) */
+ escalar_mult (&Q2, h2, &pkey->Q, &E); /* Q2 = [ r * s^(-1) ]Q */
sum_points (&Q, &Q1, &Q2, &E);/* Q = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
if (point_at_infinity (Q))
{
if (DBG_CIPHER)
- log_debug ("ecc verification: Rejected.\n");
- return 0; /* Rejected. */
+ log_debug ("ecc verification: Rejected.\n");
+ err = GPG_ERR_BAD_SIGNATURE;
+ goto leave;
}
if (point_affine (&Q, x, y, &E))
- {
+ {
if (DBG_CIPHER)
log_debug ("ecc verification: Cannot turn to affine. Rejected.\n");
- return 0; /* Rejected. */
+ err = GPG_ERR_BAD_SIGNATURE;
+ goto leave;
}
-
- i = mpi_copy (x); /* Give the x_coordinate */
- mpi_mod (i, i, E.n_); /* i = i mod E_n */
-
- if (!mpi_cmp (i, r)) /* i==r => Return 0 (distance between them). */
- {
+ mpi_mod (x, x, E.n_); /* x = x mod E_n */
+ if (mpi_cmp (x, r)) /* x != r */
+ {
if (DBG_CIPHER)
- log_debug ("ecc verification: Accepted.\n");
- return 1; /* Accepted. */
+ log_debug ("ecc verification: Not verified.\n");
+ err = GPG_ERR_BAD_SIGNATURE;
+ goto leave;
}
if (DBG_CIPHER)
- log_debug ("ecc verification: Not verified.\n");
+ log_debug ("ecc verification: Accepted.\n");
- /* Fixme: release Q, Q1 and Q2. */
-
- return 0;
+ leave:
+ curve_free (&E);
+ point_free (&G);
+ point_free (&Q2);
+ point_free (&Q1);
+ point_free (&Q);
+ mpi_free (y);
+ mpi_free (x);
+ mpi_free (h2);
+ mpi_free (h1);
+ mpi_free (h);
+ return err;
}
/****************
* Generate a random point over an Elliptic curve is the first step to
* find a random cyclic subgroup generator.
*
* !! At this moment it isn't used !! //!!
*/
#if 0
static point_t
gen_point (gcry_mpi_t prime, elliptic_curve_t base)
{
unsigned int i = 0;
gcry_mpi_t x, y_2, y;
gcry_mpi_t one, one_neg, bit;
point_t P;
x = mpi_alloc (mpi_get_nlimbs (base.p_));
y_2 = mpi_alloc (mpi_get_nlimbs (base.p_));
y = mpi_alloc (mpi_get_nlimbs (base.p_));
one = mpi_alloc_set_ui (1);
one_neg = mpi_alloc (mpi_get_nlimbs (one));
mpi_invm (one_neg, one, base.p_);
if (DBG_CIPHER)
log_debug ("Generating a normal point.\n");
do
{
- x = gen_k (base.p_, 1); /* generate_public_prime(mpi_get_nlimbs(base.n_)*BITS_PER_MPI_LIMB); */
+ x = gen_k (base.p_, 1); /* generate_public_prime(mpi_get_nlimbs(base.n_)*BITS_PER_MPI_LIMB); */
do
- {
- y_2 = gen_y_2 (x, &base); /* x^3+ax+b (mod p) */
- mpi_add_ui (x, x, 1);
- i++;
- }
- while (!mpi_cmp_ui (y_2, 0) && i < 0xf); /* Try to find a valid value until 16 iterations. */
+ {
+ y_2 = gen_y_2 (x, &base); /* x^3+ax+b (mod p) */
+ mpi_add_ui (x, x, 1);
+ i++;
+ }
+ while (!mpi_cmp_ui (y_2, 0) && i < 0xf); /* Try to find a valid value until 16 iterations. */
i = 0;
y = existSquareRoot (y_2, base.p_);
}
- while (!mpi_cmp_ui (y, 0)); /* Repeat until a valid coordinate is found. */
- bit = gen_bit (); /* generate one bit */
+ while (!mpi_cmp_ui (y, 0)); /* Repeat until a valid coordinate is found. */
+ bit = gen_bit (); /* generate one bit */
if (mpi_cmp_ui (bit, 1))
- { /* choose the y coordinate */
- mpi_invm (y, y, base.p_); /* mpi_powm(y, y, one_neg,base.p_); */
+ { /* choose the y coordinate */
+ mpi_invm (y, y, base.p_); /* mpi_powm(y, y, one_neg,base.p_); */
}
if (DBG_CIPHER)
log_debug ("Normal point generated.\n");
P.x_ = mpi_copy (x);
P.y_ = mpi_copy (y);
P.z_ = mpi_copy (one);
mpi_free (bit);
mpi_free (one_neg);
mpi_free (one);
mpi_free (y);
mpi_free (y_2);
mpi_free (x);
return (P);
}
#endif /*0*/
/****************
* Boolean generator to choose between to coordinates.
*/
#if 0
static gcry_mpi_t
gen_bit ()
{
gcry_mpi_t aux = mpi_alloc_set_ui (0);
/* FIXME: This is highly ineffective but the whole function is used
only at one place. */
/* Get one random bit, with less security level, and translate it to
an MPI. */
- mpi_set_buffer (aux, get_random_bits (1, 0, 1), 1, 0); /* gen_k(...) */
+ mpi_set_buffer (aux, get_random_bits (1, 0, 1), 1, 0); /* gen_k(...) */
- return aux; /* b; */
+ return aux; /* b; */
}
#endif /*0*/
#if 0
/* Function to solve an IFP ECElGamal weakness: */
/* sha256_hashing() */
/* aes256_encrypting() */
/* aes356_decrypting() */
/****************
* Compute 256 bit hash value from input MPI.
* Use SHA256 Algorithm.
*/
static void
sha256_hashing (gcry_mpi_t input, gcry_mpi_t * output)
-{ /* */
+{ /* */
int sign;
byte *hash_inp_buf;
byte hash_out_buf[32];
- MD_HANDLE hash = md_open (8, 1); /* algo SHA256 in secure mode */
+ MD_HANDLE hash = md_open (8, 1); /* algo SHA256 in secure mode */
unsigned int nbytes;
- hash_inp_buf = mpi_get_secure_buffer (input, &nbytes, &sign); /* convert gcry_mpi_t input to string */
+ hash_inp_buf = mpi_get_secure_buffer (input, &nbytes, &sign); /* convert gcry_mpi_t input to string */
- md_write (hash, hash_inp_buf, nbytes); /* hashing input string */
- wipememory (hash_inp_buf, sizeof hash_inp_buf); /* burn temp value */
+ md_write (hash, hash_inp_buf, nbytes); /* hashing input string */
+ wipememory (hash_inp_buf, sizeof hash_inp_buf); /* burn temp value */
xfree (hash_inp_buf);
md_digest (hash, 8, hash_out_buf, 32);
- mpi_set_buffer (*output, hash_out_buf, 32, 0); /* convert 256 bit digest to MPI */
+ mpi_set_buffer (*output, hash_out_buf, 32, 0); /* convert 256 bit digest to MPI */
- wipememory (hash_out_buf, sizeof hash_out_buf); /* burn temp value */
- md_close (hash); /* destroy and free hash state. */
+ wipememory (hash_out_buf, sizeof hash_out_buf); /* burn temp value */
+ md_close (hash); /* destroy and free hash state. */
}
/****************
* Encrypt input MPI.
* Use AES256 algorithm.
*/
static void
aes256_encrypting (gcry_mpi_t key, gcry_mpi_t input, gcry_mpi_t * output)
-{ /* */
+{ /* */
int sign;
byte *key_buf;
byte *cipher_buf;
unsigned int keylength;
unsigned int nbytes;
- CIPHER_HANDLE cipher = cipher_open (9, CIPHER_MODE_CFB, 1); /* algo AES256 CFB mode in secure memory */
- cipher_setiv (cipher, NULL, 0); /* Zero IV */
+ CIPHER_HANDLE cipher = cipher_open (9, CIPHER_MODE_CFB, 1); /* algo AES256 CFB mode in secure memory */
+ cipher_setiv (cipher, NULL, 0); /* Zero IV */
- key_buf = mpi_get_secure_buffer (key, &keylength, &sign); /* convert MPI key to string */
+ key_buf = mpi_get_secure_buffer (key, &keylength, &sign); /* convert MPI key to string */
cipher_setkey (cipher, key_buf, keylength);
- wipememory (key_buf, sizeof key_buf); /* burn temp value */
+ wipememory (key_buf, sizeof key_buf); /* burn temp value */
xfree (key_buf);
- cipher_buf = mpi_get_secure_buffer (input, &nbytes, &sign); /* convert MPI input to string */
+ cipher_buf = mpi_get_secure_buffer (input, &nbytes, &sign); /* convert MPI input to string */
- cipher_encrypt (cipher, cipher_buf + 1, cipher_buf + 1, nbytes - 1); /* */
- cipher_close (cipher); /* destroy and free cipher state. */
+ cipher_encrypt (cipher, cipher_buf + 1, cipher_buf + 1, nbytes - 1); /* */
+ cipher_close (cipher); /* destroy and free cipher state. */
- mpi_set_buffer (*output, cipher_buf, nbytes, 0); /* convert encrypted string to MPI */
- wipememory (cipher_buf, sizeof cipher_buf); /* burn temp value */
+ mpi_set_buffer (*output, cipher_buf, nbytes, 0); /* convert encrypted string to MPI */
+ wipememory (cipher_buf, sizeof cipher_buf); /* burn temp value */
xfree (cipher_buf);
}
/****************
* Decrypt input MPI.
* Use AES256 algorithm.
*/
static void
aes256_decrypting (gcry_mpi_t key, gcry_mpi_t input, gcry_mpi_t * output)
-{ /* */
+{ /* */
int sign;
byte *key_buf;
byte *cipher_buf;
unsigned int keylength;
unsigned int nbytes;
- CIPHER_HANDLE cipher = cipher_open (9, CIPHER_MODE_CFB, 1); /* algo AES256 CFB mode in secure memory */
- cipher_setiv (cipher, NULL, 0); /* Zero IV */
+ CIPHER_HANDLE cipher = cipher_open (9, CIPHER_MODE_CFB, 1); /* algo AES256 CFB mode in secure memory */
+ cipher_setiv (cipher, NULL, 0); /* Zero IV */
- key_buf = mpi_get_secure_buffer (key, &keylength, &sign); /* convert MPI input to string */
+ key_buf = mpi_get_secure_buffer (key, &keylength, &sign); /* convert MPI input to string */
cipher_setkey (cipher, key_buf, keylength);
- wipememory (key_buf, sizeof key_buf); /* burn temp value */
+ wipememory (key_buf, sizeof key_buf); /* burn temp value */
xfree (key_buf);
- cipher_buf = mpi_get_secure_buffer (input, &nbytes, &sign); /* convert MPI input to string; */
+ cipher_buf = mpi_get_secure_buffer (input, &nbytes, &sign); /* convert MPI input to string; */
- cipher_decrypt (cipher, cipher_buf + 1, cipher_buf + 1, nbytes - 1); /* */
- cipher_close (cipher); /* destroy and free cipher state. */
+ cipher_decrypt (cipher, cipher_buf + 1, cipher_buf + 1, nbytes - 1); /* */
+ cipher_close (cipher); /* destroy and free cipher state. */
- mpi_set_buffer (*output, cipher_buf, nbytes, 0); /* convert encrypted string to MPI */
- wipememory (cipher_buf, sizeof cipher_buf); /* burn temp value */
+ mpi_set_buffer (*output, cipher_buf, nbytes, 0); /* convert encrypted string to MPI */
+ wipememory (cipher_buf, sizeof cipher_buf); /* burn temp value */
xfree (cipher_buf);
}
/* End of IFP ECElGamal weakness functions. */
#endif /*0*/
/*********************************************
************** interface ******************
*********************************************/
static gcry_err_code_t
ecc_generate (int algo, unsigned int nbits, unsigned long dummy,
gcry_mpi_t *skey, gcry_mpi_t **retfactors)
{
gpg_err_code_t err;
ECC_secret_key sk;
(void)algo;
/* Make an empty list of factors. */
*retfactors = gcry_calloc ( 1, sizeof **retfactors );
if (!*retfactors)
return gpg_err_code_from_syserror ();
err = generate_key (&sk, nbits);
if (err)
{
gcry_free (*retfactors);
*retfactors = NULL;
return err;
}
skey[0] = sk.E.p_;
skey[1] = sk.E.a_;
skey[2] = sk.E.b_;
skey[3] = sk.E.G.x_;
skey[4] = sk.E.G.y_;
skey[5] = sk.E.G.z_;
skey[6] = sk.E.n_;
skey[7] = sk.Q.x_;
skey[8] = sk.Q.y_;
skey[9] = sk.Q.z_;
skey[10] = sk.d;
if (DBG_CIPHER)
{
progress ('\n');
log_mpidump ("[ecc] p= ", skey[0]);
log_mpidump ("[ecc] a= ", skey[1]);
log_mpidump ("[ecc] b= ", skey[2]);
log_mpidump ("[ecc] Gx= ", skey[3]);
log_mpidump ("[ecc] Gy= ", skey[4]);
log_mpidump ("[ecc] Gz= ", skey[5]);
log_mpidump ("[ecc] n= ", skey[6]);
log_mpidump ("[ecc] Qx= ", skey[7]);
log_mpidump ("[ecc] Qy= ", skey[8]);
log_mpidump ("[ecc] Qz= ", skey[9]);
log_mpidump ("[ecc] d= ", skey[10]);
}
if (DBG_CIPHER)
{
log_debug ("ECC key Generated.\n");
}
return 0;
}
static gcry_err_code_t
ecc_check_secret_key (int algo, gcry_mpi_t *skey)
{
ECC_secret_key sk;
(void)algo;
if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
|| !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10])
return GPG_ERR_BAD_MPI;
if (DBG_CIPHER)
{
log_debug ("ECC check secret key.\n");
}
sk.E.p_ = skey[0];
sk.E.a_ = skey[1];
sk.E.b_ = skey[2];
sk.E.G.x_ = skey[3];
sk.E.G.y_ = skey[4];
sk.E.G.z_ = skey[5];
sk.E.n_ = skey[6];
sk.Q.x_ = skey[7];
sk.Q.y_ = skey[8];
sk.Q.z_ = skey[9];
sk.d = skey[10];
if (check_secret_key (&sk))
{
if (DBG_CIPHER)
- log_debug ("Bad check: Bad secret key.\n");
+ log_debug ("Bad check: Bad secret key.\n");
return GPG_ERR_BAD_SECKEY;
}
return 0;
}
#if 0
static int
ecc_encrypt_FIXME (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
{
ECC_public_key pk;
point R;
if (algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_E)
return G10ERR_PUBKEY_ALGO;
if (!data || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4]
|| !pkey[5] || !pkey[6] || !pkey[7] || !pkey[8] || !pkey[9])
return G10ERR_BAD_MPI;
if (DBG_CIPHER)
{
log_debug ("ECC encrypt.\n");
}
pk.E.p_ = pkey[0];
pk.E.a_ = pkey[1];
pk.E.b_ = pkey[2];
pk.E.G.x_ = pkey[3];
pk.E.G.y_ = pkey[4];
pk.E.G.z_ = pkey[5];
pk.E.n_ = pkey[6];
pk.Q.x_ = pkey[7];
pk.Q.y_ = pkey[8];
pk.Q.z_ = pkey[9];
R.x_ = resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.Q.x_));
R.y_ = resarr[1] = mpi_alloc (mpi_get_nlimbs (pk.Q.y_));
R.z_ = resarr[2] = mpi_alloc (mpi_get_nlimbs (pk.Q.z_));
resarr[3] = mpi_alloc (mpi_get_nlimbs (pk.E.p_));
doEncrypt (data, &pk, &R, resarr[3]);
resarr[0] = mpi_copy (R.x_);
resarr[1] = mpi_copy (R.y_);
resarr[2] = mpi_copy (R.z_);
return 0;
}
int
ecc_decrypt_FIXME (int algo, gcry_mpi_t * result, gcry_mpi_t * data, gcry_mpi_t * skey)
{
ECC_secret_key sk;
point R;
if (algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_E)
return G10ERR_PUBKEY_ALGO;
if (!data[0] || !data[1] || !data[2] || !data[3] || !skey[0] || !skey[1]
|| !skey[2] || !skey[3] || !skey[4] || !skey[5] || !skey[6] || !skey[7]
|| !skey[8] || !skey[9] || !skey[10])
return G10ERR_BAD_MPI;
if (DBG_CIPHER)
{
log_debug ("ECC decrypt.\n");
}
R.x_ = data[0];
R.y_ = data[1];
R.z_ = data[2];
sk.E.p_ = skey[0];
sk.E.a_ = skey[1];
sk.E.b_ = skey[2];
sk.E.G.x_ = skey[3];
sk.E.G.y_ = skey[4];
sk.E.G.z_ = skey[5];
sk.E.n_ = skey[6];
sk.Q.x_ = skey[7];
sk.Q.y_ = skey[8];
sk.Q.z_ = skey[9];
sk.d = skey[10];
*result = mpi_alloc_secure (mpi_get_nlimbs (sk.E.p_));
*result = decrypt (*result, &sk, R, data[3]);
return 0;
}
#endif /*0*/
static gcry_err_code_t
ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
{
+ gpg_err_code_t err;
ECC_secret_key sk;
(void)algo;
if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4]
|| !skey[5] || !skey[6] || !skey[7] || !skey[8] || !skey[9]
|| !skey[10])
return GPG_ERR_BAD_MPI;
sk.E.p_ = skey[0];
sk.E.a_ = skey[1];
sk.E.b_ = skey[2];
sk.E.G.x_ = skey[3];
sk.E.G.y_ = skey[4];
sk.E.G.z_ = skey[5];
sk.E.n_ = skey[6];
sk.Q.x_ = skey[7];
sk.Q.y_ = skey[8];
sk.Q.z_ = skey[9];
sk.d = skey[10];
resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p_));
resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p_));
- sign (data, &sk, &resarr[0], &resarr[1]);
- return 0;
+ err = sign (data, &sk, resarr[0], resarr[1]);
+ if (err)
+ {
+ mpi_free (resarr[0]);
+ mpi_free (resarr[1]);
+ resarr[0] = NULL; /* Mark array as released. */
+ }
+ return err;
}
static gcry_err_code_t
ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
int (*cmp)(void *, gcry_mpi_t), void *opaquev)
{
ECC_public_key pk;
(void)algo;
if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2]
|| !pkey[3] || !pkey[4] || !pkey[5] || !pkey[6] || !pkey[7] || !pkey[8]
|| !pkey[9])
return GPG_ERR_BAD_MPI;
if (DBG_CIPHER)
- {
- log_debug ("ECC verify.\n");
- }
+ log_debug ("ECC verify.\n");
pk.E.p_ = pkey[0];
pk.E.a_ = pkey[1];
pk.E.b_ = pkey[2];
pk.E.G.x_ = pkey[3];
pk.E.G.y_ = pkey[4];
pk.E.G.z_ = pkey[5];
pk.E.n_ = pkey[6];
pk.Q.x_ = pkey[7];
pk.Q.y_ = pkey[8];
pk.Q.z_ = pkey[9];
- if (!verify (hash, &pk, data[0], data[1]))
- return GPG_ERR_BAD_SIGNATURE;
- return 0;
+ return verify (hash, &pk, data[0], data[1]);
}
static unsigned int
ecc_get_nbits (int algo, gcry_mpi_t *pkey)
{
(void)algo;
if (DBG_CIPHER)
{
log_debug ("ECC get nbits.\n");
}
if (DBG_CIPHER)
{
progress ('\n');
log_mpidump ("[ecc] p= ", pkey[0]);
log_mpidump ("[ecc] a= ", pkey[1]);
log_mpidump ("[ecc] b= ", pkey[2]);
log_mpidump ("[ecc] Gx= ", pkey[3]);
log_mpidump ("[ecc] Gy= ", pkey[4]);
log_mpidump ("[ecc] Gz= ", pkey[5]);
log_mpidump ("[ecc] n= ", pkey[6]);
log_mpidump ("[ecc] Qx= ", pkey[7]);
log_mpidump ("[ecc] Qy= ", pkey[8]);
log_mpidump ("[ecc] Qz= ", pkey[9]);
}
return mpi_get_nbits (pkey[0]);
}
static const char *ecdsa_names[] =
{
"ecdsa",
NULL,
};
gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
{
"ECDSA", ecdsa_names,
"pabxyznXYZ", "pabxyznXYZd", "", "rs", "pabxyznXYZ",
GCRY_PK_USAGE_SIGN,
ecc_generate,
ecc_check_secret_key,
NULL,
NULL,
ecc_sign,
ecc_verify,
ecc_get_nbits
};
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 1240d869..07e48d42 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,467 +1,470 @@
2007-03-22 Werner Koch <wk@g10code.com>
- * pkbench.c (main): Reworked to privide proper option handling.
+ * benchmark.c (die): New.
+ (ecc_bench): New.
+
+ * pkbench.c (main): Reworked to provide proper option handling.
2007-03-13 Werner Koch <wk@g10code.com>
* mpitests.c: Reformatted to GNU standards.
(main): Add options --verbose and --debug for future use.
2007-03-13 Werner Dittmann <Werner.Dittmann@t-online.de> (wk)
* mpitests.c: New.
2007-02-23 Werner Koch <wk@g10code.com>
* Makefile.am (TEST): Run benchmark as last.
* ac-data.c (check_sexp_conversion): Print label only in verbose
mode.
* pubkey.c (main): Run test just 2 times instead of 10.
(get_elg_key_new): New.
(check_run): Also run tests with Elgamal keys.
(check_keys): New arg NBITS_DATA.
(get_elg_key_new): Use only 400 for the 512 bit Elgamal test.
* random.c: New.
2007-02-22 Werner Koch <wk@g10code.com>
* basic.c (check_pubkey_sign): Also try signing using an OID.
* Makefile.am (TESTS) [W32]: Removed pkbench for now.
* pkbench.c (benchmark): Fixed for W32.
2007-02-21 Werner Koch <wk@g10code.com>
* hmac.c (check_one_mac): Make pointer args const.
* basic.c (check_one_md): Ditto.
(check_one_hmac): Ditto.
* keygen.c (progress_cb): Filter out line feeds.
* basic.c (progress_handler): Ditto.
2006-12-18 Werner Koch <wk@g10code.com>
* Makefile.am (AM_CFLAGS, AM_CPPFLAGS): Splitted and merged with
Moritz' changes.
(INCLUDES): Removed.
* keygen.c (progress_handler): New.
(main): Use it in verbose mode.
2006-11-05 Moritz Schulte <moritz@g10code.com>
* Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the
new gcrypt.h is used, not the one installed in the system.
2006-10-17 Werner Koch <wk@g10code.com>
* keygen.c (check_rsa_keys): Also create an 1536 bit DSA key.
2006-08-03 Werner Koch <wk@g10code.com>
* t-mpi-bit.c: New.
2006-07-06 Werner Koch <wk@g10code.com>
* benchmark.c (main): New option --use-random-daemon. New command
strongrandom.
(random_bench): New arg VERY_STRONG.
2006-03-14 Werner Koch <wk@g10code.com>
* benchmark.c (main): Allow for seed file argument to random bench.
* basic.c (main): Use progress handler only in verbose mode.
(main): Speed up test key generation.
* ac-data.c (check_sexp_conversion, check_run): Take care of VERBOSE.
* ac.c (main): Ditto.
* pubkey.c (main): Ditto.
* pkbench.c (main): Ditto.
* keygen.c (main): Ditto.
(check_rsa_keys): Print key only in verbose mode.
2006-03-10 Brad Hards <bradh@frogmouth.net> (wk, patch 2006-02-18)
* basic.c (check_one_hmac, check_hmac): New.
2006-03-07 Werner Koch <wk@g10code.com>
* benchmark.c (cipher_bench): Add OFB mode.
2006-01-18 Brad Hards <bradh@frogmouth.net> (wk 2006-03-07)
* basic.c: Added test cases for OFB and CFB modes. Fixed some
compiler warnings for signedness.
2005-11-12 Moritz Schulte <moritz@g10code.com>
* ac-data.c: Added way more test cases.
2005-09-15 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added keygrip.
* keygrip.c: New.
2005-09-19 Werner Koch <wk@g10code.com>
* benchmark.c (dsa_bench): New.
2005-08-19 Werner Koch <wk@g10code.com>
* hmac.c (main): Added all FIPS tests.
2005-08-18 Werner Koch <wk@g10code.com>
* hmac.c: New.
2005-04-22 Moritz Schulte <moritz@g10code.com>
* tsexp.c: Include <config.h> in case HAVE_CONFIG_H is defined;
thanks to Albert Chin.
* testapi.c: Likewise.
* register.c: Likewise.
* pubkey.c: Likewise.
* prime.c: Likewise.
* pkbench.c: Likewise.
* keygen.c: Likewise.
* benchmark.c: Likewise.
* basic.c: Likewise.
* ac-schemes.c: Likewise.
* ac-data.c: Likewise.
* ac.c: Likewise.
2005-04-16 Moritz Schulte <moritz@g10code.com>
* ac-data.c (check_run): Include new test.
2005-04-11 Moritz Schulte <moritz@g10code.com>
* basic.c (check_digests): Add tests for Whirlpool.
2005-03-30 Moritz Schulte <moritz@g10code.com>
* ac-schemes.c: New file.
* ac-data.c: New file.
* Makefile.am (TESTS): Added ac-schemes and ac-data.
2004-09-15 Moritz Schulte <moritz@g10code.com>
* pkbench.c: Include <time.h>.
2004-08-24 Moritz Schulte <moritz@g10code.com>
* pkbench.c (context_init): Improve generation of test data.
2004-08-23 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added: pkbench.
* pkbench.c: New file.
2004-02-25 Werner Koch <wk@gnupg.org>
* Makefile.am (TEST): Add benchmark.
* benchmark.c (md_bench, cipher_bench): Allow NULL arg to to run
tests for all algorithms.
(main): Run all tests by default.
2004-02-03 Werner Koch <wk@gnupg.org>
* tsexp.c (basic): New pass to check secure memory switching.
2004-01-12 Moritz Schulte <mo@g10code.com>
* ac.c (check_one): Adjust to new ac API.
2003-11-22 Werner Koch <wk@gnupg.org>
* pubkey.c (check_keys_crypt): Fixed my last patch.
2003-11-11 Werner Koch <wk@gnupg.org>
* tsexp.c (basic): Add pass structure and a test for the %b
format.
2003-11-04 Werner Koch <wk@gnupg.org>
* Makefile.am (noinst_PROGRAMS): Use this so that test programs
get always build.
* keygen.c (check_nonce): New.
(main): Add a basic check for the nocen function.
2003-10-31 Werner Koch <wk@gnupg.org>
* basic.c (check_aes128_cbc_cts_cipher): Make it a prototype
* ac.c (check_run): Comment unused variable.
2003-10-10 Werner Koch <wk@gnupg.org>
* prime.c (check_primes): Generate a generator and avoid printing
unless in verbose mode.
2003-10-07 Werner Koch <wk@gnupg.org>
* tsexp.c (check_sscan): New.
2003-09-04 Werner Koch <wk@gnupg.org>
* pubkey.c (check_keys_crypt): Fix for compatibility mode.
2003-09-02 Moritz Schulte <mo@g10code.com>
* Makefile.am (TESTS): Added: prime.
* prime.c: New file.
2003-08-27 Moritz Schulte <mo@g10code.com>
* basic.c (check_ciphers): Added: Serpent.
Write braces around flags.
2003-08-04 Moritz Schulte <moritz@g10code.com>
* benchmark.c (do_powm): Adjust for new gcry_mpi_scan interface.
2003-07-23 Moritz Schulte <moritz@g10code.com>
* ac.c (key_copy): New function...
(check_one): ... use it.
2003-07-22 Moritz Schulte <moritz@g10code.com>
* basic.c (check_ciphers): Use gcry_cipher_map_name.
2003-07-18 Moritz Schulte <moritz@g10code.com>
* ac.c (check_run): Renamed to ...
(check_one): ... this, changed calling interface.
(check_run): New function.
* register.c: Adjust gcry_cipher_spec_t structure.
2003-07-14 Moritz Schulte <moritz@g10code.com>
* register.c: Adjust cipher specification structure.
* benchmark.c: New file.
* testapi.c: New file.
* Makefile.am (EXTRA_PROGRAMS): Set to: benchmark testapi.
(check_PROGRAMS): Set to: $(TESTS).
2003-07-12 Moritz Schulte <moritz@g10code.com>
* ac.c, basic.c, keygen.c, register.c, sexp.c, tsexp.c: Used
gcry_err* wrappers for libgpg symbols.
* basic.c (check_ciphers): Added: GCRY_CIPHER_TWOFISH128.
2003-07-08 Moritz Schulte <moritz@g10code.com>
* Makefile.am (LIBS): Remove: -lpthread.
* basic.c (check_one_cipher): Fix variable initialization. Thanks
to Simon Joseffson <jas@extundo.com>.
2003-07-07 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added: register.
2003-07-05 Moritz Schulte <moritz@g10code.com>
* register.c (check_run): Adjusted for new gcry_cipher_register API.
2003-07-02 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added: ac.
* ac.c: New file.
2003-06-18 Werner Koch <wk@gnupg.org>
* basic.c (check_cbc_mac_cipher): Adjusted for new API of get_blklen
and get_keylen.
(check_ctr_cipher): Ditto.
(check_one_cipher): Ditto.
(check_one_md): Adjusted for new API of gcry_md_copy.
2003-06-18 Moritz Schulte <moritz@g10code.com>
* register.c: Replace old type GcryModule with newer one:
gcry_module_t.
Adjusted for new API.
* Makefile.am (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@.
2003-06-15 Moritz Schulte <moritz@g10code.com>
* basic.c (get_keys_new): New function.
(do_check_one_pubkey): New function ...
(check_one_pubkey): ... use it.
(progress_handler): New function.
(main): Use gcry_set_progress_handler.
2003-06-14 Moritz Schulte <moritz@g10code.com>
* basic.c: Replaced calls to gcry_strerror with calls to
gpg_strerror.
(check_one_md): Adjust for new gcry_md_copy API.
* tsexp.c: Likewise.
* keygen.c: Likewise.
2003-06-12 Moritz Schulte <moritz@g10code.com>
* basic.c: Changed here and there, reorganized pubkey checks,
added DSA and ELG keys.
2003-06-09 Moritz Schulte <moritz@g10code.com>
* basic.c, keygen.c, pubkey.c, register.c, tsexp.c: Changed to use
new API.
2003-06-01 Moritz Schulte <moritz@g10code.com>
* tsexp.c (canon_len): Adjust for new gcry_sexp_canon_len API.
2003-05-26 Moritz Schulte <moritz@g10code.com>
* basic.c (verify_one_signature): Adjust for libgpg-error.
(check_pubkey_sign): Likewise.
(check_pubkey): Likewise.
* basic.c (check_pubkey_sign): Likewise.
* tsexp.c (canon_len): Likewise.
(back_and_forth_one): Likewise.
2003-04-27 Moritz Schulte <moritz@g10code.com>
* pubkey.c: Changed the sample private key to contain the
identifier `openpgp-rsa' instead of `rsa'.
* basic.c (check_digests): Enabled/fixed some tests for TIGER.
2003-04-17 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Removed `register' for now.
2003-04-17 Moritz Schulte <moritz@g10code.com>
* basic.c (check_digests): Include checks for SHA512 and SHA384.
2003-04-16 Moritz Schulte <moritz@g10code.com>
* basic.c (check_one_md): Also test md_copy.
2003-04-07 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added register.
* register.c: New file.
2003-03-30 Simon Josefsson <jas@extundo.com>
* basic.c (check_one_cipher): New. Test CTR.
(main): Call it.
(check_ciphers): Check CTR mode.
2003-03-26 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added pubkey.
* pubkey.c: New file.
2003-03-22 Simon Josefsson <jas@extundo.com>
* basic.c (check_cbc_mac_cipher): New.
(main): Use it.
2003-03-19 Werner Koch <wk@gnupg.org>
* keygen.c (check_rsa_keys): Don't expect an exponent when asking
for e=0.
(check_generated_rsa_key): Just print exponent if EXPECTED_E is 0.
2003-03-02 Moritz Schulte <moritz@g10code.com>
* basic.c (check_one_cipher): Use gcry_cipher_reset() instead of
gcry_cipher_close(), gcry_cipher_open and gcry_cipher_setkey().
2003-01-23 Werner Koch <wk@gnupg.org>
* keygen.c: New.
2003-01-20 Simon Josefsson <jas@extundo.com>
* basic.c (check_digests): Add CRC.
(check_one_md): Print computed and expected values on error.
2003-01-20 Werner Koch <wk@gnupg.org>
* basic.c (check_one_md): Kludge to check a one million "a".
(check_digests): Add checks for SHA-256.
2003-01-20 Werner Koch <wk@gnupg.org>
* basic.c (check_pubkey): Check the keygrip for the sample key.
2003-01-15 Werner Koch <wk@gnupg.org>
* basic.c (verify_one_signature,check_pubkey_sign)
(check_pubkey): New.
(main): Check public key functions. Add a --debug option.
2002-11-23 Werner Koch <wk@gnupg.org>
* basic.c (check_digests): Add another test for MD4. By Simon
Josefsson.
2002-11-10 Simon Josefsson <jas@extundo.com>
* basic.c (check_aes128_cbc_cts_cipher): New function.
(check_one_cipher): Add flags parameter.
(check_ciphers): Support flags parameter.
(main): Check CTS.
2002-11-10 Werner Koch <wk@gnupg.org>
* basic.c (check_one_md): New. By Simon Josefsson.
(check_digests): New tests for MD4. By Simon.
2002-08-26 Werner Koch <wk@gnupg.org>
* basic.c (check_ciphers): Check simple DES.
2002-05-16 Werner Koch <wk@gnupg.org>
* tsexp.c (back_and_forth): Very minimal test of the new functions.
2002-05-14 Werner Koch <wk@gnupg.org>
Changed license of all files to the LGPL.
2002-05-02 Werner Koch <wk@gnupg.org>
* basic.c: Add option --verbose.
2002-01-11 Werner Koch <wk@gnupg.org>
* tsexp.c (canon_len): Fixed tests.
2001-12-18 Werner Koch <wk@gnupg.org>
* tsexp.c: New.
Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/tests/benchmark.c b/tests/benchmark.c
index 9469d3e0..9a5dd9fc 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -1,762 +1,877 @@
/* benchmark.c - for libgcrypt
* Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt 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.
*
* Libgcrypt 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
+#include <stdarg.h>
#ifndef _WIN32
#include <sys/times.h>
#endif
#include <gcrypt.h>
#define PGM "benchmark"
static const char sample_private_dsa_key_1024[] =
"(private-key\n"
" (dsa\n"
" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685"
"03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A"
"853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF"
"C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n"
" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n"
" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622"
"B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312"
"FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3"
"85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n"
" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4"
"ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6"
"66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155"
"D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n"
" (x #4186F8A58C5DF46C5BCFC7006BEEBF05E93C0CA7#)\n"
"))\n";
static const char sample_public_dsa_key_1024[] =
"(public-key\n"
" (dsa\n"
" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685"
"03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A"
"853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF"
"C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n"
" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n"
" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622"
"B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312"
"FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3"
"85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n"
" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4"
"ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6"
"66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155"
"D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n"
"))\n";
static const char sample_private_dsa_key_2048[] =
"(private-key\n"
" (dsa\n"
" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365"
"A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C"
"308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150"
"C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970"
"71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405"
"D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179"
"0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4"
"2F9C9F315ED409171EC35CA04CC06B275577B3#)\n"
" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n"
" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78"
"98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3"
"5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F"
"B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508"
"4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F"
"0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44"
"2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3"
"6EE4425A553AF8885FEA15A88135BE133520#)\n"
" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C"
"2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB"
"4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79"
"328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F"
"8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3"
"E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923"
"79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7"
"14A264330AECCB24DE2A1107847B23490897#)\n"
" (x #477BD14676E22563C5ABA68025CEBA2A48D485F5B2D4AD4C0EBBD6D0#)\n"
"))\n";
static const char sample_public_dsa_key_2048[] =
"(public-key\n"
" (dsa\n"
" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365"
"A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C"
"308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150"
"C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970"
"71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405"
"D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179"
"0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4"
"2F9C9F315ED409171EC35CA04CC06B275577B3#)\n"
" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n"
" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78"
"98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3"
"5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F"
"B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508"
"4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F"
"0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44"
"2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3"
"6EE4425A553AF8885FEA15A88135BE133520#)\n"
" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C"
"2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB"
"4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79"
"328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F"
"8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3"
"E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923"
"79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7"
"14A264330AECCB24DE2A1107847B23490897#)\n"
"))\n";
static const char sample_private_dsa_key_3072[] =
"(private-key\n"
" (dsa\n"
" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938"
"877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5"
"62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83"
"B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988"
"AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46"
"0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2"
"AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902"
"D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60"
"B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E"
"95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7"
"62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33"
"8015353D3778B02B892AF7#)\n"
" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n"
" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4"
"DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474"
"7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98"
"9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC"
"134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C"
"7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89"
"F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB"
"120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6"
"374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0"
"21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F"
"D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC"
"4997AF9EB55C6660B01A#)\n"
" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE"
"4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053"
"A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492"
"8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15"
"DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71"
"CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997"
"437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026"
"73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B"
"FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD"
"F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765"
"3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561"
"2703D518D8D49FF0EBE6#)\n"
" (x #00A9FFFC88E67D6F7B810E291C050BAFEA7FC4A75E8D2F16CFED3416FD77607232#)\n"
"))\n";
static const char sample_public_dsa_key_3072[] =
"(public-key\n"
" (dsa\n"
" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938"
"877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5"
"62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83"
"B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988"
"AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46"
"0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2"
"AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902"
"D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60"
"B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E"
"95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7"
"62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33"
"8015353D3778B02B892AF7#)\n"
" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n"
" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4"
"DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474"
"7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98"
"9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC"
"134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C"
"7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89"
"F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB"
"120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6"
"374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0"
"21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F"
"D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC"
"4997AF9EB55C6660B01A#)\n"
" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE"
"4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053"
"A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492"
"8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15"
"DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71"
"CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997"
"437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026"
"73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B"
"FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD"
"F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765"
"3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561"
"2703D518D8D49FF0EBE6#)\n"
"))\n";
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
#define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\
exit(2);} while(0)
/* Helper for the start and stop timer. */
static clock_t started_at, stopped_at;
+static void
+die (const char *format, ...)
+{
+ va_list arg_ptr ;
+
+ va_start( arg_ptr, format ) ;
+ putchar ('\n');
+ fputs ( PGM ": ", stderr);
+ vfprintf (stderr, format, arg_ptr );
+ va_end(arg_ptr);
+ exit (1);
+}
+
+
static void
start_timer (void)
{
#ifdef _WIN32
started_at = stopped_at = clock ();
#else
struct tms tmp;
times (&tmp);
started_at = stopped_at = tmp.tms_utime;
#endif
}
static void
stop_timer (void)
{
#ifdef _WIN32
stopped_at = clock ();
#else
struct tms tmp;
times (&tmp);
stopped_at = tmp.tms_utime;
#endif
}
static const char *
elapsed_time (void)
{
static char buf[50];
sprintf (buf, "%5.0fms",
(((double) (stopped_at - started_at))/CLOCKS_PER_SEC)*10000000);
return buf;
}
static void
random_bench (int very_strong)
{
char buf[128];
int i;
printf ("%-10s", "random");
if (!very_strong)
{
start_timer ();
for (i=0; i < 100; i++)
gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM);
stop_timer ();
printf (" %s", elapsed_time ());
}
start_timer ();
for (i=0; i < 100; i++)
gcry_randomize (buf, 8,
very_strong? GCRY_VERY_STRONG_RANDOM:GCRY_STRONG_RANDOM);
stop_timer ();
printf (" %s", elapsed_time ());
putchar ('\n');
}
static void
md_bench ( const char *algoname )
{
int algo;
gcry_md_hd_t hd;
int i;
char buf[1000];
gcry_error_t err = GPG_ERR_NO_ERROR;
if (!algoname)
{
for (i=1; i < 400; i++)
if ( !gcry_md_test_algo (i) )
md_bench (gcry_md_algo_name (i));
return;
}
algo = gcry_md_map_name (algoname);
if (!algo)
{
fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname);
exit (1);
}
err = gcry_md_open (&hd, algo, 0);
if (err)
{
fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname);
exit (1);
}
for (i=0; i < sizeof buf; i++)
buf[i] = i;
printf ("%-12s", gcry_md_algo_name (algo));
start_timer ();
for (i=0; i < 1000; i++)
gcry_md_write (hd, buf, sizeof buf);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time ());
gcry_md_reset (hd);
start_timer ();
for (i=0; i < 10000; i++)
gcry_md_write (hd, buf, sizeof buf/10);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time ());
gcry_md_reset (hd);
start_timer ();
for (i=0; i < 1000000; i++)
gcry_md_write (hd, "", 1);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time ());
gcry_md_close (hd);
putchar ('\n');
}
static void
cipher_bench ( const char *algoname )
{
static int header_printed;
int algo;
gcry_cipher_hd_t hd;
int i;
int keylen, blklen;
char key[128];
char outbuf[1000], buf[1000];
size_t buflen;
static struct { int mode; const char *name; int blocked; } modes[] = {
{ GCRY_CIPHER_MODE_ECB, "ECB", 1 },
{ GCRY_CIPHER_MODE_CBC, "CBC", 1 },
{ GCRY_CIPHER_MODE_CFB, "CFB", 0 },
{ GCRY_CIPHER_MODE_OFB, "OFB", 0 },
{ GCRY_CIPHER_MODE_CTR, "CTR", 0 },
{ GCRY_CIPHER_MODE_STREAM, "STREAM", 0 },
{0}
};
int modeidx;
gcry_error_t err = GPG_ERR_NO_ERROR;
if (!algoname)
{
for (i=1; i < 400; i++)
if ( !gcry_cipher_test_algo (i) )
cipher_bench (gcry_cipher_algo_name (i));
return;
}
if (!header_printed)
{
printf ("%-10s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
printf (" %-15s", modes[modeidx].name );
putchar ('\n');
printf ("%-10s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
printf (" ---------------" );
putchar ('\n');
header_printed = 1;
}
algo = gcry_cipher_map_name (algoname);
if (!algo)
{
fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname);
exit (1);
}
keylen = gcry_cipher_get_algo_keylen (algo);
if (!keylen)
{
fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
algoname);
exit (1);
}
if ( keylen > sizeof key )
{
fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n",
algo, keylen );
exit (1);
}
for (i=0; i < keylen; i++)
key[i] = i + (clock () & 0xff);
blklen = gcry_cipher_get_algo_blklen (algo);
if (!blklen)
{
fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n",
algoname);
exit (1);
}
printf ("%-10s", gcry_cipher_algo_name (algo));
fflush (stdout);
for (modeidx=0; modes[modeidx].mode; modeidx++)
{
if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
| (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
{
printf (" " );
continue;
}
for (i=0; i < sizeof buf; i++)
buf[i] = i;
err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname);
exit (1);
}
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
buflen = sizeof buf;
if (modes[modeidx].blocked)
buflen = (buflen / blklen) * blklen;
start_timer ();
for (i=err=0; !err && i < 1000; i++)
err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
gcry_cipher_close (hd);
if (err)
{
fprintf (stderr, "gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err) );
exit (1);
}
err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname);
exit (1);
}
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
start_timer ();
for (i=err=0; !err && i < 1000; i++)
err = gcry_cipher_decrypt ( hd, outbuf, buflen, buf, buflen);
stop_timer ();
printf (" %s", elapsed_time ());
fflush (stdout);
gcry_cipher_close (hd);
if (err)
{
fprintf (stderr, "gcry_cipher_decrypt failed: %s\n",
gpg_strerror (err) );
exit (1);
}
}
putchar ('\n');
}
static void
dsa_bench (void)
{
gpg_error_t err;
gcry_sexp_t pub_key[3], sec_key[3];
int p_sizes[3] = { 1024, 2048, 3072 };
int q_sizes[3] = { 160, 224, 256 };
gcry_sexp_t data;
gcry_sexp_t sig;
int i, j;
err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024,
strlen (sample_public_dsa_key_1024));
if (!err)
err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024,
strlen (sample_private_dsa_key_1024));
if (!err)
err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048,
strlen (sample_public_dsa_key_2048));
if (!err)
err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048,
strlen (sample_private_dsa_key_2048));
if (!err)
err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072,
strlen (sample_public_dsa_key_3072));
if (!err)
err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072,
strlen (sample_private_dsa_key_3072));
if (err)
{
fprintf (stderr, PGM ": converting sample keys failed: %s\n",
gcry_strerror (err));
exit (1);
}
- fputs ("DSA 100 times sign verify\n"
- "-----------------------------\n", stdout);
+ fputs ("Algorithm generate 100*sign 100*verify\n"
+ "----------------------------------------------\n", stdout);
for (i=0; i < DIM (q_sizes); i++)
{
gcry_mpi_t x;
x = gcry_mpi_new (q_sizes[i]);
gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
if (err)
{
fprintf (stderr, PGM ": converting data failed: %s\n",
gcry_strerror (err));
exit (1);
}
- printf ("DSA %d/%d ", p_sizes[i], q_sizes[i]);
+ printf ("DSA %d/%d -", p_sizes[i], q_sizes[i]);
+ fflush (stdout);
+
start_timer ();
for (j=0; j < 100; j++)
{
err = gcry_pk_sign (&sig, data, sec_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": signing failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
- printf (" %s", elapsed_time ());
+ printf (" %s", elapsed_time ());
+ fflush (stdout);
start_timer ();
for (j=0; j < 100; j++)
{
err = gcry_pk_verify (sig, data, pub_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": verify failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
- printf (" %s\n", elapsed_time ());
+ printf (" %s\n", elapsed_time ());
+ fflush (stdout);
gcry_sexp_release (sig);
gcry_sexp_release (data);
}
for (i=0; i < DIM (q_sizes); i++)
{
gcry_sexp_release (sec_key[i]);
gcry_sexp_release (pub_key[i]);
}
}
+static void
+ecc_bench (void)
+{
+#if USE_ECC
+ gpg_error_t err;
+ int p_sizes[] = { 192, 256, 521 };
+ int testno;
+
+
+ fputs ("Algorithm generate 100*sign 100*verify\n"
+ "----------------------------------------------\n", stdout);
+ for (testno=0; testno < DIM (p_sizes); testno++)
+ {
+ gcry_sexp_t key_spec, key_pair, pub_key, sec_key;
+ gcry_mpi_t x;
+ gcry_sexp_t data;
+ gcry_sexp_t sig = NULL;
+ int count;
+
+ printf ("ECDSA %3d bit ", p_sizes[testno]);
+ fflush (stdout);
+
+ err = gcry_sexp_build (&key_spec, NULL,
+ "(genkey (ECDSA (nbits %d)))", p_sizes[testno]);
+ if (err)
+ die ("creating S-expression failed: %s\n", gcry_strerror (err));
+
+
+ start_timer ();
+ err = gcry_pk_genkey (&key_pair, key_spec);
+ if (err)
+ die ("creating %d bit ECC key failed: %s\n",
+ p_sizes[testno], gcry_strerror (err));
+
+ pub_key = gcry_sexp_find_token (key_pair, "public-key", 0);
+ if (! pub_key)
+ die ("public part missing in key\n");
+ sec_key = gcry_sexp_find_token (key_pair, "private-key", 0);
+ if (! sec_key)
+ die ("private part missing in key\n");
+ gcry_sexp_release (key_pair);
+
+ stop_timer ();
+ printf (" %s", elapsed_time ());
+ fflush (stdout);
+
+ x = gcry_mpi_new (p_sizes[testno]);
+ gcry_mpi_randomize (x, p_sizes[testno], GCRY_WEAK_RANDOM);
+ err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
+ gcry_mpi_release (x);
+ if (err)
+ die ("converting data failed: %s\n", gcry_strerror (err));
+
+ start_timer ();
+ for (count=0; count < 100; count++)
+ {
+ gcry_sexp_release (sig);
+ err = gcry_pk_sign (&sig, data, sec_key);
+ if (err)
+ die ("signing failed: %s\n", gpg_strerror (err));
+ }
+ stop_timer ();
+ printf (" %s", elapsed_time ());
+ fflush (stdout);
+
+ start_timer ();
+ for (count=0; count < 100; count++)
+ {
+ err = gcry_pk_verify (sig, data, pub_key);
+ if (err)
+ {
+ putchar ('\n');
+ fprintf (stderr, PGM ": verify failed: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+ }
+ stop_timer ();
+ printf (" %s\n", elapsed_time ());
+ fflush (stdout);
+
+ gcry_sexp_release (sig);
+ gcry_sexp_release (data);
+ gcry_sexp_release (sec_key);
+ gcry_sexp_release (pub_key);
+ }
+#endif /*USE_ECC*/
+}
+
+
static void
do_powm ( const char *n_str, const char *e_str, const char *m_str)
{
gcry_mpi_t e, n, msg, cip;
gcry_error_t err;
int i;
err = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, n_str, 0, 0);
if (err) BUG ();
err = gcry_mpi_scan (&e, GCRYMPI_FMT_HEX, e_str, 0, 0);
if (err) BUG ();
err = gcry_mpi_scan (&msg, GCRYMPI_FMT_HEX, m_str, 0, 0);
if (err) BUG ();
cip = gcry_mpi_new (0);
start_timer ();
for (i=0; i < 1000; i++)
gcry_mpi_powm (cip, msg, e, n);
stop_timer ();
printf (" %s", elapsed_time ()); fflush (stdout);
/* { */
/* char *buf; */
/* if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, NULL, cip)) */
/* BUG (); */
/* printf ("result: %s\n", buf); */
/* gcry_free (buf); */
/* } */
gcry_mpi_release (cip);
gcry_mpi_release (msg);
gcry_mpi_release (n);
gcry_mpi_release (e);
}
static void
mpi_bench (void)
{
printf ("%-10s", "powm"); fflush (stdout);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E4",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8"
);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847"
);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA4071620A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847"
);
putchar ('\n');
}
int
main( int argc, char **argv )
{
if (argc)
{ argc--; argv++; }
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
if (!gcry_check_version (GCRYPT_VERSION))
{
fprintf (stderr, PGM ": version mismatch\n");
exit (1);
}
if (argc && !strcmp (*argv, "--use-random-daemon"))
{
gcry_control (GCRYCTL_USE_RANDOM_DAEMON, 1);
argc--; argv++;
}
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if ( !argc )
{
md_bench (NULL);
putchar ('\n');
cipher_bench (NULL);
putchar ('\n');
mpi_bench ();
putchar ('\n');
random_bench (0);
}
else if ( !strcmp (*argv, "--help"))
fputs ("usage: benchmark [md|cipher|random|mpi|dsa [algonames]]\n",
stdout);
else if ( !strcmp (*argv, "random") || !strcmp (*argv, "strongrandom"))
{
if (argc == 1)
random_bench ((**argv == 's'));
else if (argc == 2)
{
gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, argv[1]);
random_bench ((**argv == 's'));
gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
}
else
fputs ("usage: benchmark [strong]random [seedfile]\n", stdout);
}
else if ( !strcmp (*argv, "md"))
{
if (argc == 1)
md_bench (NULL);
else
for (argc--, argv++; argc; argc--, argv++)
md_bench ( *argv );
}
else if ( !strcmp (*argv, "cipher"))
{
if (argc == 1)
cipher_bench (NULL);
else
for (argc--, argv++; argc; argc--, argv++)
cipher_bench ( *argv );
}
else if ( !strcmp (*argv, "mpi"))
{
mpi_bench ();
}
else if ( !strcmp (*argv, "dsa"))
{
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
dsa_bench ();
}
+ else if ( !strcmp (*argv, "ecc"))
+ {
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+ ecc_bench ();
+ }
else
{
fprintf (stderr, PGM ": bad arguments\n");
return 1;
}
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 26, 7:01 PM (19 h, 10 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
96/73/81f24f54f90425f377356e3fc33b

Event Timeline