summaryrefslogtreecommitdiff
path: root/cipher
diff options
context:
space:
mode:
Diffstat (limited to 'cipher')
-rw-r--r--cipher/ChangeLog11
-rw-r--r--cipher/Makefile.am1
-rw-r--r--cipher/ecc.c3199
-rw-r--r--cipher/pubkey.c3
-rw-r--r--cipher/random.c2
5 files changed, 1746 insertions, 1470 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 025fbb26..0bd32b66 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,14 @@
+2007-03-22 Werner Koch <wk@g10code.com>
+
+ * pubkey.c (pubkey_table): Initialize ECC.
+ * Makefile.am (EXTRA_libcipher_la_SOURCES): Add ecc.c.
+ * ecc.c: New. Heavily reformatted and changed for use in libgcrypt.
+ (point_init): New.
+ (escalar_mult): Make arg R the first arg to be similar to the mpi
+ functions.
+ (duplicate_point): Ditto
+ (sum_points): Ditto
+
2007-03-14 Werner Koch <wk@g10code.com>
* random.c (MASK_LEVEL): Removed macro as it was used only at one
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index a992de0f..94958efd 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -57,6 +57,7 @@ crc.c \
des.c \
dsa.c \
elgamal.c \
+ecc.c \
md4.c \
md5.c \
rijndael.c \
diff --git a/cipher/ecc.c b/cipher/ecc.c
index b2e08478..14fff812 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1,5 +1,5 @@
/* ecc.c - ECElGamal Public Key encryption & ECDSA signature algorithm
- * Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -15,9 +15,17 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * 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
@@ -45,7 +53,7 @@
* more polite gen_k() and its calls.
* mmr: extend the check_secret_key()
* In process:
- * genBigPoint(): Randomize the point generation.
+ * 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!
@@ -58,1355 +66,1560 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "types.h"
-#include "util.h"
+
+#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
-#include "ecc.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
-
-typedef struct {
- MPI x_;
- MPI y_;
- MPI z_;
-} point; //Point representation in projective coordinates.
-
-typedef struct {
- MPI p_;
- MPI a_,b_;
- //MPI Gx,Gy,Gz;
- point G;
- MPI n_;
- //MPI h_; =1 //!! We will need to change this value in 2-isogeny
-} ellipticCurve;//doubtful name //!!
-
-typedef struct {
- ellipticCurve E;
- point Q; /*Q=[d]G*/
-} ECC_public_key;//Q
-
-typedef struct {
- ellipticCurve E;
- point Q; /*Q=[d]G*/
- MPI d;
-} ECC_secret_key;//d
-
-
-static MPI gen_k( MPI p, int secure );
-
-static void generateCurve(unsigned nbits, ellipticCurve *ECC_curve);//choice a curve of the rank
-
-static void generateKey(ECC_secret_key *sk, unsigned nbits , MPI **factors );//Generate de cryptosystem setup.
-static void testKeys( ECC_secret_key *sk, unsigned nbits );//verify correct skey
-static int check_secret_key( ECC_secret_key *sk );//check the validity of the value
-static void doEncrypt(MPI input, ECC_public_key *pkey, point *R, MPI c);
-static MPI decrypt(MPI output, ECC_secret_key *skey, point R, MPI c);
-static void sign(MPI input, ECC_secret_key *skey, MPI *r, MPI *s);
-static int verify(MPI input, ECC_public_key *pkey, MPI r, MPI s);
-
-static int genBigPoint(MPI *prime, ellipticCurve *base, point *G, unsigned nbits);//return -1 if it isn't possible
-static point genPoint(MPI prime, ellipticCurve base);//random point over an Elliptic curve
-static MPI existSquareRoot(MPI integer, MPI modulus);//return true or false
-static void Lucas(MPI n, MPI p_, MPI q_, MPI k, MPI V_n, MPI Q_0);
-
-static int PointAtInfinity(point Query);//return true(1), false(0), or error(-1) for an invalid point
-
-static void escalarMult(MPI escalar, point *P, point *R, ellipticCurve *base);//return R=escalarP
-static void sumPoints(point *P0, point *P1, point *P2, ellipticCurve *base);//P2=P0+P1
-static void duplicatePoint(point *P, point *R, ellipticCurve *base);//R=2P
-static void invertPoint(point *P, ellipticCurve *base);//P=-P
-
-static point point_copy(point P);
-static void point_free(point *P);
-static int point_affine(point *P, MPI x, MPI y, ellipticCurve *base);//turn an projective coordinate to affine, return 0 (1 if error).
-static ellipticCurve curve_copy(ellipticCurve E);
-static void curve_free(ellipticCurve *E);
-static MPI gen_bit();
-static MPI gen_y_2(MPI x, ellipticCurve *base);
-
-//Function for IFP ECElGamal Weakness.
-static void sha256_hashing(MPI input, MPI *output);//Compute a hash
-static void aes256_encrypting(MPI key, MPI input, MPI *output);//Encrypt simmetricaly
-static void aes256_decrypting(MPI key, MPI input, MPI *output);//Decrypt simmetricaly
-
-static void (*progress_cb) ( void *, int );
-static void *progress_cb_data;
-static void
-progress( int c )
+/*
+ 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
{
- if ( progress_cb )
- progress_cb ( progress_cb_data, c );
- else
- fputc( c, stderr );
-}
+ gcry_mpi_t x_;
+ gcry_mpi_t y_;
+ gcry_mpi_t z_;
+} point_t;
-/****************
- * At the begging was the same than elgamal.c
- * but mmr improve it.
- * Generate a random secret scalar k with an order of p
- * Moreover it do NOT use Wiener's table.
- */
-static MPI
-gen_k( MPI p, int secure ){
-
- MPI k = mpi_alloc_secure( 0 );
- unsigned int nbits = mpi_get_nbits(p);
- unsigned int nbytes;
-
- nbytes = (nbits+7)/8;
- if( DBG_CIPHER )
- log_debug("choosing a random k of %u bits\n", nbits);
- char *c = get_random_bits( nbits, secure, 1 );
- mpi_set_buffer( k, c, nbytes, 0 );
- xfree(c);
- mpi_fdiv_r(k,k, p);//simple module: k=k (mod p)
- if( DBG_CIPHER )
- progress('\n');
-
- return k;
-}
-/****************
- * Generate de cryptosystem setup.
- * At this time it fix the values to the ones which NIST recomend.
- * The subgroup generator point is in another function: 'genBigPoint'.
- */
-static void
-generateCurve(unsigned nbits, ellipticCurve *ECC_curve){
-
- ellipticCurve E;
- //point *G;
-
- if( nbits == 192 ){//NIST P-192
- E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.p_,\
- "0xfffffffffffffffffffffffffffffffeffffffffffffffff"))
- log_fatal("ECC operation: Curve assigments failed(p)\n");
- else ECC_curve->p_ = mpi_copy(E.p_);
- E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.a_,\
- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"))//"-0x3"))
- log_fatal("ECC operation: Curve assigments failed(a)\n");
- else ECC_curve->a_ = mpi_copy(E.a_);
- E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.b_,\
- "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"))
- log_fatal("ECC operation: Curve assigments failed(b)\n");
- else ECC_curve->b_ = mpi_copy(E.b_);
- E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.n_,\
- "0xffffffffffffffffffffffff99def836146bc9b1b4d22831"))
- log_fatal("ECC operation: Curve assigments failed(n)\n");
- else ECC_curve->n_ = mpi_copy(E.n_);
- }
- else if( nbits == 224 ){//NIST P-224
- E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.p_,\
- "0xffffffffffffffffffffffffffffffff000000000000000000000001"))
- log_fatal("ECC operation: Curve assigments failed(p)\n");
- else ECC_curve->p_ = mpi_copy(E.p_);
- E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.a_,\
- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))//"-0x3"))
- log_fatal("ECC operation: Curve assigments failed(a)\n");
- else ECC_curve->a_ = mpi_copy(E.a_);
- E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.b_,\
- "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"))
- log_fatal("ECC operation: Curve assigments failed(b)\n");
- else ECC_curve->b_ = mpi_copy(E.b_);
- E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.n_,\
- "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d"))
- log_fatal("ECC operation: Curve assigments failed(n)\n");
- else ECC_curve->n_ = mpi_copy(E.n_);
- }
- else if( nbits == 256 ){//NIST P-256
- E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.p_,\
- "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"))
- log_fatal("ECC operation: Curve assigments failed(p)\n");
- else ECC_curve->p_ = mpi_copy(E.p_);
- E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.a_,\
- "0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"))//"-0x3"))
- log_fatal("ECC operation: Curve assigments failed(a)\n");
- else ECC_curve->a_ = mpi_copy(E.a_);
- E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.b_,\
- "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"))
- log_fatal("ECC operation: Curve assigments failed(b)\n");
- else ECC_curve->b_ = mpi_copy(E.b_);
- E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.n_,\
- "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"))
- log_fatal("ECC operation: Curve assigments failed(n)\n");
- else ECC_curve->n_ = mpi_copy(E.n_);
- }
- else if( nbits == 384 ){//NIST P-384
- E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.p_,\
- "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff"))
- log_fatal("ECC operation: Curve assigments failed(p)\n");
- else ECC_curve->p_ = mpi_copy(E.p_);
- E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.a_,\
- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC"))//"-0x3"))
- log_fatal("ECC operation: Curve assigments failed(a)\n");
- else ECC_curve->a_ = mpi_copy(E.a_);
- E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.b_,\
- "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"))
- log_fatal("ECC operation: Curve assigments failed(b)\n");
- else ECC_curve->b_ = mpi_copy(E.b_);
- E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.n_,\
- "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973"))
- log_fatal("ECC operation: Curve assigments failed(n)\n");
- else ECC_curve->n_ = mpi_copy(E.n_);
- }
- else if( nbits == 521 ){//NIST P-521
- E.p_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.p_,\
- "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
- log_fatal("ECC operation: Curve assigments failed(p)\n");
- else ECC_curve->p_ = mpi_copy(E.p_);
- E.a_ =mpi_alloc((2/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.a_,\
- "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"))//"-0x3"))
- log_fatal("ECC operation: Curve assigments failed(a)\n");
- else ECC_curve->a_ = mpi_copy(E.a_);
- E.b_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.b_,\
- "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00"))
- log_fatal("ECC operation: Curve assigments failed(b)\n");
- else ECC_curve->b_ = mpi_copy(E.b_);
- E.n_ =mpi_alloc((nbits/(BYTES_PER_MPI_LIMB*8))+1);
- if (mpi_fromstr(E.n_,\
- "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409"))
- log_fatal("ECC operation: Curve assigments failed(n)\n");
- else ECC_curve->n_ = mpi_copy(E.n_);
- }
- else{
- log_fatal("ECC operation: Curve generation failed\n");
- }
- if( DBG_CIPHER ){
- progress('\n');
- log_mpidump("generation p= ", ECC_curve->p_ );
- log_mpidump("generation a= ", ECC_curve->a_ );
- log_mpidump("generation b= ", ECC_curve->b_ );
- log_mpidump("generation n= ", ECC_curve->n_ );
- }
- if ( genBigPoint(&ECC_curve->n_, ECC_curve, &ECC_curve->G, nbits) == -1){
- log_fatal("ECC operation: Point generation failed\n");
- }
- if( DBG_CIPHER ) {
- log_mpidump("generation Gx= ", ECC_curve->G.x_ );
- log_mpidump("generation Gy= ", ECC_curve->G.y_ );
- log_mpidump("generation Gz= ", ECC_curve->G.z_ );
- log_info("Setup generated\n");
- progress('\n');
- }
-}
+/* 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 */
-/****************
- * Fisrt obtain the setup.
- * Over the finite field randomize an scalar secret value, and calculat de public point.
- *
- * !! What about the **ret_factors !! //!!
- */
-static void
-generateKey(ECC_secret_key *sk, unsigned nbits , MPI **ret_factors ){
- ellipticCurve E;
- MPI d;
- point Q,G;
+typedef struct
+{
+ elliptic_curve_t E;
+ point_t Q; /* Q=[d]G */
+} ECC_public_key; /* Q */
- generateCurve(nbits,&E);
+typedef struct
+{
+ elliptic_curve_t E;
+ point_t Q; /* Q=[d]G */
+ gcry_mpi_t d;
+} ECC_secret_key; /* d */
- d = mpi_alloc_secure(nbits/BITS_PER_MPI_LIMB);
- if( DBG_CIPHER )
- log_debug("choosing a random x of size %u\n", nbits );
- d = gen_k(E.n_,2);//generate_secret_prime(nbits);
- G = point_copy(E.G);
- escalarMult(d,&E.G,&Q,&E);
+/* 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;
- /* 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!) */
- testKeys( sk, nbits - 64 );
- point_free(&Q);
- mpi_free(d);
- curve_free(&E);
-}
+
+/* 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);
-/****************
- * 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
-testKeys( ECC_secret_key *sk, unsigned nbits ){
- ECC_public_key pk;
- MPI test = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
- point R_;
- MPI c = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
- MPI out = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
- MPI r = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
- MPI s = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
+static int point_at_infinity (point_t query);
- if( DBG_CIPHER )log_info("Testing key.\n");
+static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
- pk.E = curve_copy(sk->E);
- pk.E.G = point_copy(sk->E.G);
- pk.Q = point_copy(sk->Q);
- /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/
- { char *p = get_random_bits( nbits, 0, 0 );
- mpi_set_buffer( test, p, (nbits+7)/8, 0 );
- xfree(p);
- }
- doEncrypt(test,&pk,&R_,c);
+
+void
+_gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
+ int, int, int),
+ void *cb_data)
+{
+ progress_cb = cb;
+ progress_cb_data = cb_data;
+}
- out = decrypt(out,sk,R_,c);
+static void
+progress (int c)
+{
+ if (progress_cb)
+ progress_cb (progress_cb_data, "pk_dsa", c, 0, 0);
+ else
+ fputc (c, stderr);
+}
- if( mpi_cmp( test, out ) )//test!=out
- log_fatal("ECELG operation: encrypt, decrypt failed\n");
- if( DBG_CIPHER )log_info("ECELG operation: encrypt, decrypt ok.\n");
- sign(test,sk,&r,&s);
+
+/*
- if( !verify(test,&pk,r,s) ){
- log_fatal("ECDSA operation: sign, verify failed\n");}
+ O B J E C T M A I N T E N A N C E
- if( DBG_CIPHER )log_info("ECDSA operation: sign, verify ok.\n");
+ */
- mpi_free(s);
- mpi_free(r);
- mpi_free(out);
- mpi_free(c);
- point_free(&R_);
- mpi_free(test);
+/* 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);
}
-/****************
- * 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 Q;
- MPI 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
- if (mpi_cmp(y_2,y2)){
- if( DBG_CIPHER )log_info("Bad check: Point 'G' does not belong to curve 'E'!\n");
- return (1);
- }
- //G != PaI
- if (PointAtInfinity(sk->E.G)){
- if( DBG_CIPHER )log_info("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
- escalarMult(sk->E.n_,&sk->E.G,&Q,&sk->E);
- if (!PointAtInfinity(Q)){
- if( DBG_CIPHER )log_info("Bad check: 'E' is not curve of order 'n'!\n");
- return (1);
- }
- //pubkey cannot be PaI
- if (PointAtInfinity(sk->Q)){
- if( DBG_CIPHER )log_info("Bad check: Q can not be a Point at Infinity!\n");
- return (1);
- }
- //pubkey = [d]G over E
- escalarMult(sk->d,&sk->E.G,&Q,&sk->E);
- if ((Q.x_ == sk->Q.x_) && (Q.y_ == sk->Q.y_) && (Q.z_ == sk->Q.z_)){
- if( DBG_CIPHER )log_info("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
- return (1);
- }
- point_free(&Q);
- return (0);
-}
-/****************
- * Encrypt a number and obtain and struct (R,c)
+/*
+ * Release a point object.
*/
static void
-doEncrypt(MPI input, ECC_public_key *pkey, point *R, MPI c){
-
- MPI k,p,x,y;
- point P,Q,G;
- ellipticCurve 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
- //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
- if( DBG_CIPHER ){log_info("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");}
+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;
}
-/****************
- * Undo the ciphertext
+
+/*
+ * Return a copy of a point object.
*/
-static MPI
-decrypt(MPI output, ECC_secret_key *skey, point R, MPI c){
-
- MPI p,inv,x,y;
- point P,Q;
- ellipticCurve 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
- //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
- if( DBG_CIPHER ){log_info("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);
+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;
}
-/****************
- * Return the signature struct (r,s) from the message hash.
+
+/*
+ * Release a curve object.
*/
static void
-sign(MPI input, ECC_secret_key *skey, MPI *r, MPI *s){
-
- MPI k,i,dr,sum,k_1,x,y;
- point G,I;
- ellipticCurve E;
-
- k = mpi_alloc(0); i = mpi_alloc(0); 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);
-
- while (!mpi_cmp_ui(*s,0)){//s==0
- while (!mpi_cmp_ui(*r,0)){//r==0
- k = gen_k( E.p_, 1 );
- escalarMult(k,&G,&I,&E);//I=[k]G
- if (point_affine(&I,x,y,&E)){//I cannot turn to affine coordinate
- if( DBG_CIPHER ){log_info("Sign: Cannot turn to affine. Cannot complete sign.\n");}
- }
- i = mpi_copy(x);//i=I_x
- mpi_fdiv_r(*r,i,E.n_);//simple module: 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("Sign: end\n");}
- mpi_free(y);
- mpi_free(x);
- mpi_free(k_1);
- mpi_free(sum);
- mpi_free(dr);
- mpi_free(i);
- mpi_free(k);
+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;
}
-/****************
- * Check if the struct (r,s) is for the hash value that it have.
- */
-static int
-verify(MPI input, ECC_public_key *pkey, MPI r, MPI s){
-
- MPI r_,s_,h,h1,h2,i,x,y;
- point Q,Q1,Q2,G;
- ellipticCurve E;
-
- r_ = mpi_alloc(0); s_ = 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_fdiv_r(r_,r,pkey->E.n_);//simple module
- mpi_fdiv_r(s_,s,pkey->E.n_);//simple module
-
- //check if the input parameters are valid.
- if ( mpi_cmp(r_,r) || mpi_cmp(s_,s)) {//r_!=r || s_!=s
- if( DBG_CIPHER ){log_info("Verification: No valid values.\n");}
- return 0; //not valid values.
- }
-
- mpi_invm(h,s,E.n_);//h=s^(-1) (mod n)
- mpi_mulm(h1,input,h,E.n_);//h1=hash*s^(-1) (mod n)
- escalarMult(h1,&G,&Q1,&E);//Q1=[hash*s^(-1)]G
- mpi_mulm(h2,r,h,E.n_);//h2=r*s^(-1) (mod n)
- escalarMult(h2,&pkey->Q,&Q2,&E);//Q2=[r*s^(-1)]Q
- sumPoints(&Q1,&Q2,&Q,&E);//Q=([hash*s^(-1)]G)+([r*s^(-1)]Q)
-
- if (PointAtInfinity(Q)){
- if( DBG_CIPHER ){log_info("Verification: Rejected.\n");}
- return 0;//rejected
- }
- if (point_affine(&Q,x,y,&E)){//Q cannot turn to affine coordinate
- if( DBG_CIPHER ){log_info("Verification: Cannot turn to affine. Rejected.\n");}
- return 0;//rejected
- }
- i = mpi_copy(x);//Give the x_coordinate
- mpi_fdiv_r(i,i,E.n_);//simple module
-
- if (!mpi_cmp(i,r)){//i==r => Return 0 (distance between them).
- if( DBG_CIPHER ){log_info("Verification: Accepted.\n");}
- return 1;//accepted
- }
- if( DBG_CIPHER ){log_info("Verification: Not verified.\n");}
- return 0;
-}
-/****************
- * A point of order 'n' is needed to generate a ciclic subgroup.
- * Over this ciclic subgroup it's defined the ECDLP.
- * Now it use a fix values from NIST FIPS PUB 186-2.
+/*
+ * Return a copy of a curve object.
*/
-static int
-genBigPoint(MPI *prime, ellipticCurve *base, point *G, unsigned nbits){
- ///*estandard nist
- if( nbits == 192 ){//NIST P-192
- G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->x_,\
- "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"))
- log_fatal("Generator operation: Point assigments failed(x)\n");
- G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->y_,\
- "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"))
- log_fatal("Generator operation: Point assigments failed(y)\n");
- G->z_ = mpi_alloc_set_ui(1);
- }
- else if( nbits == 224 ){//NIST P-224
- G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->x_,\
- "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"))
- log_fatal("Generator operation: Point assigments failed(x)\n");
- G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->y_,\
- "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"))
- log_fatal("Generator operation: Point assigments failed(y)\n");
- G->z_ = mpi_alloc_set_ui(1);
- }
- else if( nbits == 256 ){//NIST P-256
- G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->x_,\
- "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"))
- log_fatal("Generator operation: Point assigments failed(x)\n");
- G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->y_,\
- "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"))
- log_fatal("Generator operation: Point assigments failed(y)\n");
- G->z_ = mpi_alloc_set_ui(1);
- }
- else if( nbits == 384 ){//NIST P-384
- G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->x_,\
- "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"))
- log_fatal("Generator operation: Point assigments failed(x)\n");
- G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->y_,\
- "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"))
- log_fatal("Generator operation: Point assigments failed(y)\n");
- G->z_ = mpi_alloc_set_ui(1);
- }
- else if( nbits == 521 ){//NIST P-521
- G->x_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->x_,\
- "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66"))
- log_fatal("Generator operation: Point assigments failed(x)\n");
- G->y_ = mpi_alloc(mpi_get_nlimbs(base->n_));
- if (mpi_fromstr(G->y_,\
- "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"))
- log_fatal("Generator operation: Point assigments failed(y)\n");
- G->z_ = mpi_alloc_set_ui(1);
- }
- //end Estandard nist
- /*Randomize G
- unsigned int i=0;
- MPI one;
- point 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_MPI )log_info("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_MPI )log_info("Big point generated.\n");
- if( DBG_MPI ){
- log_mpidump("Gx=",G->x_);log_mpidump("Gy=",G->y_);log_mpidump("Gz=",G->z_);
- }
- return 0;
- *///end aleatoritzar G
- return 0;
+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;
}
-/****************
- * Generate a random point over an Elliptic curve
- * is the first step to find a random ciclic subgroup
- * generator.
- *
- * !! At this moment it isn't used !! //!!
+
+
+/*
+
+ A D D I T I O N A L M P I F U N C T I O N S
+
*/
-static point
-genPoint(MPI prime, ellipticCurve base){
-
- unsigned int i=0;
- MPI x,y_2,y;
- MPI one, one_neg,bit;
- point 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_MPI )log_info("Generating a normal point.\n");
- do{
- 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.
- 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
- if (mpi_cmp_ui(bit,1)){//choose the y coordinate
- mpi_invm(y, y, base.p_);//mpi_powm(y, y, one_neg,base.p_);
- }
- if( DBG_MPI )log_info("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);
-}
+
/****************
- * Find, if it exist, the square root of one integer module a big prime.
- * Return the square root or 0 if it is not found.
+ * 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.
*/
-static MPI
-existSquareRoot(MPI integer, MPI modulus){
-
- unsigned long int i=0;
- MPI one,two,three,four,five,eight;
- MPI k,r,z,k1;
- MPI 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_MPI )log_mpidump("?exist Square Root of ",integer);
-
- mpi_fdiv_qr(k,r,modulus,four);
- if (mpi_cmp(r,three)){//p=3 (mod 4)
- mpi_addm(k1,k,one,modulus);
- mpi_powm(z,integer,k1,modulus);
- if( DBG_MPI ){log_mpidump("z=",z);}
- return z;//value found
- }
- mpi_fdiv_qr(k,r,modulus,eight);
- if (mpi_cmp(r,five)){//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_MPI ){log_mpidump("z=",z);}
- return z;//value found
- }
- if (mpi_cmp(r,one)){//p=1 (mod 8)
- while(i<0xFF){//while not find z after 256 iterations*/
- if( DBG_MPI )log_info("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_MPI ){log_mpidump("z=",z);}
- return z;//value found
- }
- if (t4>mpi_alloc_set_ui(1) && t4<t3){
- if( DBG_MPI )log_info("Rejected.\n");
- return (0); //NULL
- }
- if( DBG_MPI )log_info("Another loop.\n");
- }
- }
- if( DBG_MPI )log_info("iterations limit.\n");
- return (0);//because this algorithm not always finish.
+#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) */
+ mpi_addm (k1, k, one, modulus);
+ mpi_powm (z, integer, k1, modulus);
+ if (DBG_CIPHER)
+ {
+ log_mpidump ("z=", z);
+ }
+ return z; /* value found */
+ }
+ mpi_fdiv_qr (k, r, modulus, eight);
+ if (mpi_cmp (r, five))
+ { /* 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 */
+ }
+ if (mpi_cmp (r, one))
+ { /* 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");
+ }
+ }
+ if (DBG_CIPHER)
+ log_debug ("iterations limit.\n");
+ 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
+ * V_0 = 2; V_1 = p
+ * V_k = (p*V_(k-1)) - (q*V_(k-2)) for k >= 2
*/
+#if 0
static void
-Lucas(MPI n, MPI p_, MPI q_, MPI k, MPI V_n, MPI Q_0){
-
- MPI v0,v1,q0,q1;
- MPI 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_MPI ){log_info("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'
- i++;
- }
- while (i<r){
- if( DBG_MPI ){
- log_info("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);
- }
- 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);
- }
- i++;
- }
- V_n = mpi_copy(v0);
- Q_0 = mpi_copy(q0);
- if( DBG_MPI ){
- log_info("Lucas sequence generated.\n");
- log_mpidump("V_n=",V_n);
- log_mpidump("Q_0=",Q_0);
- }
+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' */
+ 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));
+ }
+ 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);
+ }
+ 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);
+ }
+ 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
-PointAtInfinity(point Query){
-
- if( DBG_MPI ){log_info("?is a Point at Infinity.\n");}
-
- 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
- if( DBG_MPI )log_info("True:It is a Point at Infinite.\n");
- return (1); //true
- }
- if( DBG_MPI )log_info("Error:It isn't an elliptic curve valid point.\n");
- return (-1); //
- }
- if( DBG_MPI ){log_info("False:It isn't a Point at Infinity.\n");}
- return (0); //it is a valid curve point, but it isn't the point at infinity
+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 */
+ /* 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 ("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. */
}
-/****************
- * The modular power used without EC,
- * is this function over EC.
+
+/*
+ * Turn a projective coordinate to affine, return 0 (or 1 in error case).
+ * Returns 0 on success.
+ *
+ * Note, that Y is never used as we can do without it.
*/
-static void
-escalarMult(MPI escalar, point *P, point *R, ellipticCurve *base){
-
- MPI one,two,three;
- MPI p;
- MPI xx,yy,zz,x1,y1,z1,z2,z3,k,h;//it could use less memory!!!!
- unsigned int i,loops;
- point P1,P2,P1_;
-
- x1 = mpi_alloc(mpi_get_nlimbs(P->x_));
- y1 = mpi_alloc(mpi_get_nlimbs(P->y_));
- z2 = mpi_alloc(mpi_get_nlimbs(P->z_));
- z3 = mpi_alloc(mpi_get_nlimbs(P->z_));
- h = mpi_alloc(mpi_get_nlimbs(P->z_));
-
- if( DBG_MPI )log_info("Calculating an scalar Multiple.\n");
-
- one = mpi_alloc_set_ui(1);
- two = mpi_alloc_set_ui(2);
- three = mpi_alloc_set_ui(3);
- p = mpi_copy(base->p_);
-
- if ( !mpi_cmp_ui(escalar,0) || mpi_cmp_ui(P->z_,0)){//n=0 | Z=0 => [1:1:0]
- R->x_ = mpi_copy(one);
- R->y_ = mpi_copy(one);
- R->z_ = mpi_alloc(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
- k = mpi_copy(escalar);
- 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
- 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_mul(h,three,k);//h=3k
- loops = mpi_get_nbits(h);
- i=loops-2; // i = l-1 = loops-2
- R->x_ = mpi_copy(xx);
- R->y_ = mpi_copy(yy);
- R->z_ = mpi_copy(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
- duplicatePoint(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);
- sumPoints(&P2,&P1,R,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);
- invertPoint(&P1_,base);
- sumPoints(&P2,&P1_,R,base);//R=P2+P1_ over the base elliptic curve
- }
- i--;
- }
- if( DBG_MPI )log_info("Scalar Multiple calculated.\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);
+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: "
+ "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) */
+ 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;
}
-/****************
- * Point addition is the group operation.
+
+/*
+ * The point inversion over F_p is a simple modular inversion of the Y
+ * coordinate.
*/
static void
-sumPoints(point *P0, point *P1, point *P2, ellipticCurve *base){
-
- MPI one,two;
- MPI p;
- MPI t1,t2,t3,t4,t5,t6,t7;
-
- one = mpi_alloc_set_ui(1);
- two = mpi_alloc_set_ui(2);
- p = mpi_copy(base->p_);
- 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));
-
- if( DBG_MPI )log_info("Add two points.\n");
-
- if ((!mpi_cmp(P1->x_,P0->x_)) && (!mpi_cmp(P1->y_,P0->y_)) && (!mpi_cmp(P1->z_,P0->z_))){// P1=P0
- duplicatePoint(P0,P2,base);
- }
- else if (PointAtInfinity(*P0)){//(!mpi_cmp_ui(P0->y_,0) || !mpi_cmp_ui(P0->z_,0)){// P2=0+P1=P1
- P2->x_ = mpi_copy(P1->x_);
- P2->y_ = mpi_copy(P1->y_);
- P2->z_ = mpi_copy(P1->z_);
- }
- else if (PointAtInfinity(*P1)){//(!mpi_cmp_ui(P1->y_,0) || !mpi_cmp_ui(P1->z_,0)){// P2=P0+0=P0
- P2->x_ = mpi_copy(P0->x_);
- P2->y_ = mpi_copy(P0->y_);
- P2->z_ = mpi_copy(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
- if (mpi_cmp(P1->z_,one)){//z1!=1
- 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
- if (!mpi_cmp_ui(t4,0)){//t4==0
- if (!mpi_cmp_ui(t5,0)){//return (0:0:0), it have an special mean.
- if( DBG_MPI )log_info("Point Addition: [0:0:0]!\n");
- P2->x_ = mpi_copy(mpi_alloc_set_ui(0));
- P2->y_ = mpi_copy(mpi_alloc_set_ui(0));
- P2->z_ = mpi_copy(mpi_alloc_set_ui(0));
- }
- else {//return (1:1:0)
- if( DBG_MPI )log_info("Point Addition: [1:1:0]!\n");
- P2->x_ = mpi_copy(one);
- P2->y_ = mpi_copy(one);
- P2->z_ = mpi_copy(mpi_alloc_set_ui(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
-
- P2->x_ = mpi_copy(t1);
- P2->y_ = mpi_copy(t2);
- P2->z_ = mpi_copy(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);
+invert_point (point_t *P, elliptic_curve_t *base)
+{
+ 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
-duplicatePoint(point *P, point *R, ellipticCurve *base){
-
- MPI one,two,three,four,eight;
- MPI p,p_3,a;
- MPI t1,t2,t3,t4,t5,t6,t7;
- MPI 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));
-
- if( DBG_MPI ){log_info("Duplicate a point.\n");}
-
- 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]
- if( DBG_MPI ){log_info("t2==0 | t3==0\n");}
- R->x_ = mpi_copy(one);
- R->y_ = mpi_copy(one);
- R->z_ = mpi_copy(mpi_alloc_set_ui(0));
- }
- else{
- mpi_fdiv_r(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
- }
- 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
- }
- if( DBG_MPI ){log_info("t2!=0 & t3!=0\n");}
- 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(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
- 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
-
- R->x_ = mpi_copy(t1);
- R->y_ = mpi_copy(t2);
- R->z_ = mpi_copy(t3);
- }
- if( DBG_MPI ){log_info("Duplicated point.\n");}
-
- 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);
+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 */
+
+ if (!mpi_cmp_ui (t2, 0) || !mpi_cmp_ui (t3, 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 */
+ 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 */
+ }
+ 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 */
+ 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 (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 */
+ 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_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 */
+ 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 */
+ }
+ 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 */
+
+ if (!mpi_cmp_ui (t4, 0)) /* t4==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");
+ 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");
+ 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_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 point inversion over F_p
- * is a simple modular inversion
- * of the Y coordinate.
+ * 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
-invertPoint(point *P, ellipticCurve *base){
+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_);
- mpi_subm(P->y_,base->p_,P->y_,base->p_);//y=p-y mod 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] */
+ 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 */
+ k = mpi_copy (escalar);
+ 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 */
+ 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_mul (h, three, k); /* h=3k */
+ loops = mpi_get_nbits (h);
+ 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 */
+ 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 */
+ }
+ 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 */
+ }
+ 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);
}
+
/****************
- * Auxiliar function to made easy a struct copy.
+ * 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 */
+
+ 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
+
*/
-static point
-point_copy(point P){
- point R;
- R.x_ = mpi_copy(P.x_);
- R.y_ = mpi_copy(P.y_);
- R.z_ = mpi_copy(P.z_);
- return R;
+
+/* 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;
+}
+
+
/****************
- * Made easy the free memory for a point struct.
+ * 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 void
-point_free(point *P){
+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');
- mpi_free(P->x_);
- mpi_free(P->y_);
- mpi_free(P->z_);
+ return 0;
}
+
/****************
- * Turn a projective coordinate to affine, return 0 (or 1 in error case).
- * Needed to verify a signature.
- *
- * y_coordinate it is never used, we could do without it. //!!
+ * 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); */
+ 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 int
-point_affine(point *P, MPI x, MPI y, ellipticCurve *base){
+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);
- //MPI z;
- MPI z1,z2,z3;
+ if (DBG_CIPHER)
+ log_debug ("Testing key.\n");
- z1 = mpi_alloc(0);
- z2 = mpi_alloc(0);
- z3 = mpi_alloc(0);
+ point_init (&R_);
- if (PointAtInfinity(*P)){
- if( DBG_CIPHER )log_info("Affine: Point at Infinity does NOT exist in the affine plane!\n");
- return 1;
- }
+ pk.E = curve_copy (sk->E);
+ pk.Q = point_copy (sk->Q);
+
+ gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
- 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_);
+#if 0
+ doEncrypt (test, &pk, &R_, c);
+
+ out = decrypt (out, sk, R_, c);
+
+ 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 (!verify (test, &pk, r, s))
+ {
+ log_fatal ("ECDSA operation: sign, verify failed\n");
+ }
- mpi_free(z1);
- mpi_free(z2);
- mpi_free(z3);
- return 0;
+ 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);
}
/****************
- * Auxiliar function to made easy a struct copy.
+ * To check the validity of the value, recalculate the correspondence
+ * between the public value and de secret one.
*/
-static ellipticCurve
-curve_copy(ellipticCurve E){
+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 */
+ if (mpi_cmp (y_2, y2))
+ {
+ if (DBG_CIPHER)
+ 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");
+ 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");
+ 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");
+ 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");
+ 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)
+{
- ellipticCurve R;
+ 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 */
+ /* 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 */
+ if (DBG_CIPHER)
+ {
+ 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)
+{
- 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_);
+ 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 */
+ /* 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 */
+ if (DBG_CIPHER)
+ {
+ log_debug ("Encrypting: Cannot turn to affine.\n");
+ }
+ }
+ sha256_hashing (x, &x);
+ aes256_decrypting (x, c, &output);
- return R;
+ if (DBG_CIPHER)
+ {
+ log_debug ("decrypt: end.\n");
+ }
+ return (output);
}
+#endif /*0*/
/****************
- * Made easy the free memory for a setup struct.
+ * Return the signature struct (r,s) from the message hash.
*/
static void
-curve_free(ellipticCurve *E){
- mpi_free(E->p_);
- mpi_free(E->a_);
- mpi_free(E->b_);
- point_free(&E->G);
- mpi_free(E->n_);
+sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t *r, gcry_mpi_t *s)
+{
+ 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);
+ 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)
+ 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 */
+ }
+ if (DBG_CIPHER)
+ log_debug ("ess sign: end\n");
+
+ /* Fixme: What about releasing G and E? */
+ mpi_free (y);
+ mpi_free (x);
+ mpi_free (k_1);
+ mpi_free (sum);
+ mpi_free (dr);
+ mpi_free (i);
+ mpi_free (k);
}
/****************
- * Boolean generator to choose between to coordinates.
+ * Check if the struct (r,s) is for the hash value that it have.
+ * Returns: 0 = does not verify
+ * 1 = verifies.
*/
-static MPI
-gen_bit(){
+static int
+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;
+ point_t Q, Q1, Q2, G;
+ elliptic_curve_t E;
+
+ /* Fixme: we need to release quite some values. */
+
+ r_ = mpi_alloc (0);
+ s_ = 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 */
+ 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. */
+ }
+ if (point_affine (&Q, x, y, &E))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc verification: Cannot turn to affine. Rejected.\n");
+ return 0; /* Rejected. */
+ }
+
+ i = mpi_copy (x); /* Give the x_coordinate */
+ mpi_mod (i, i, E.n_); /* i = i mod E_n */
- MPI aux = mpi_alloc_set_ui(0);
+ if (!mpi_cmp (i, r)) /* i==r => Return 0 (distance between them). */
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc verification: Accepted.\n");
+ return 1; /* Accepted. */
+ }
+ if (DBG_CIPHER)
+ log_debug ("ecc verification: Not verified.\n");
- //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(...)
+ /* Fixme: release Q, Q1 and Q2. */
- return aux;//b;
+ return 0;
}
+
/****************
- * Solve the right side of the equation that define a curve.
+ * 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 !! //!!
*/
-static MPI
-gen_y_2(MPI x, ellipticCurve *base){
+#if 0
+static point_t
+gen_point (gcry_mpi_t prime, elliptic_curve_t base)
+{
- MPI three;
- MPI x_3,ax,axb,y;
- MPI a,b,p;
+ 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); */
+ 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. */
+ 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 */
+ if (mpi_cmp_ui (bit, 1))
+ { /* 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);
- three = mpi_alloc_set_ui(3);
- a = mpi_copy(base->a_);
- b = mpi_copy(base->b_),
- p = mpi_copy(base->p_);
- x_3 = mpi_alloc(mpi_get_nlimbs(p));
- ax = mpi_alloc(mpi_get_nlimbs(p));
- axb = mpi_alloc(mpi_get_nlimbs(p));
- y = mpi_alloc(mpi_get_nlimbs(p));
+ return (P);
+}
+#endif /*0*/
- if( DBG_MPI )log_info("solving an elliptic equation.\n");
+/****************
+ * Boolean generator to choose between to coordinates.
+ */
+#if 0
+static gcry_mpi_t
+gen_bit ()
+{
+ gcry_mpi_t aux = mpi_alloc_set_ui (0);
- 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
+ /* FIXME: This is highly ineffective but the whole function is used
+ only at one place. */
- if( DBG_MPI )log_info("solved.\n");
+ /* 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(...) */
- return y;//the quadratic value of the coordinate if it exist.
+ return aux; /* b; */
}
+#endif /*0*/
-//Function to solve an IFP ECElGamal weakness:
-// sha256_hashing()
-// aes256_encrypting()
-// aes356_decrypting()
+
+
+#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(MPI input, MPI *output){ //
+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
+ int sign;
+ byte *hash_inp_buf;
+ byte hash_out_buf[32];
+ MD_HANDLE hash = md_open (8, 1); /* algo SHA256 in secure mode */
- unsigned int nbytes;
+ unsigned int nbytes;
- hash_inp_buf = mpi_get_secure_buffer( input, &nbytes, &sign );//convert MPI 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
- xfree(hash_inp_buf);
+ 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
+ md_digest (hash, 8, hash_out_buf, 32);
+ 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. */
}
@@ -1415,33 +1628,34 @@ sha256_hashing(MPI input, MPI *output){ //
* Use AES256 algorithm.
*/
-static void
-aes256_encrypting(MPI key, MPI input, MPI *output){ //
+static void
+aes256_encrypting (gcry_mpi_t key, gcry_mpi_t input, gcry_mpi_t * output)
+{ /* */
- int sign;
- byte *key_buf;
- byte *cipher_buf;
+ int sign;
+ byte *key_buf;
+ byte *cipher_buf;
- unsigned int keylength;
- unsigned int nbytes;
+ 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
- cipher_setkey( cipher, key_buf, keylength );
- wipememory( key_buf, sizeof key_buf ); // burn temp value
- xfree(key_buf);
+ 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 */
+ 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
- xfree(cipher_buf);
+ 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);
}
/****************
@@ -1449,285 +1663,332 @@ aes256_encrypting(MPI key, MPI input, MPI *output){ //
* Use AES256 algorithm.
*/
-static void
-aes256_decrypting(MPI key, MPI input, MPI *output){ //
+static void
+aes256_decrypting (gcry_mpi_t key, gcry_mpi_t input, gcry_mpi_t * output)
+{ /* */
- int sign;
- byte *key_buf;
- byte *cipher_buf;
+ int sign;
+ byte *key_buf;
+ byte *cipher_buf;
- unsigned int keylength;
- unsigned int nbytes;
+ 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
- cipher_setkey( cipher, key_buf, keylength );
- wipememory( key_buf, sizeof key_buf ); // burn temp value
- xfree(key_buf);
+ 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 */
+ 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
- xfree(cipher_buf);
+ 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.
+
+/* End of IFP ECElGamal weakness functions. */
+#endif /*0*/
/*********************************************
************** interface ******************
*********************************************/
-int
-ecc_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
+
+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]);
+ }
- ECC_secret_key sk;
-
- if( !is_ECC(algo) )
- return G10ERR_PUBKEY_ALGO;
-
- generateKey( &sk, nbits, retfactors );
-
- 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_info("ECC key Generated.\n");}
- return 0;
+ if (DBG_CIPHER)
+ {
+ log_debug ("ECC key Generated.\n");
+ }
+ return 0;
}
-int
-ecc_check_secret_key( int algo, MPI *skey )
+static gcry_err_code_t
+ecc_check_secret_key (int algo, gcry_mpi_t *skey)
{
- ECC_secret_key sk;
-
- if( !is_ECC(algo) )
- return G10ERR_PUBKEY_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 G10ERR_BAD_MPI;
-
- if( DBG_CIPHER ){log_info("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_info("Bad check: Bad secret key.\n");
- return G10ERR_BAD_SECKEY;
- }
- return 0;
-}
+ 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;
-int
-ecc_encrypt( int algo, MPI *resarr, MPI data, MPI *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_info("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;
+ 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");
+ return GPG_ERR_BAD_SECKEY;
+ }
+ return 0;
}
-int
-ecc_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
+
+#if 0
+static int
+ecc_encrypt_FIXME (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey)
{
- 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_info("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;
+ 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_sign( int algo, MPI *resarr, MPI data, MPI *skey )
+ecc_decrypt_FIXME (int algo, gcry_mpi_t * result, gcry_mpi_t * data, gcry_mpi_t * skey)
{
- ECC_secret_key sk;
-
- if( algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_S )
- return G10ERR_PUBKEY_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 G10ERR_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;
+ 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*/
-int
-ecc_verify( int algo, MPI hash, MPI *data, MPI *pkey )
+static gcry_err_code_t
+ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
{
- ECC_public_key pk;
-
- if( algo != PUBKEY_ALGO_ECC && algo != PUBKEY_ALGO_ECC_S )
- return G10ERR_PUBKEY_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 G10ERR_BAD_MPI;
-
- if( DBG_CIPHER ){log_info("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 G10ERR_BAD_SIGN;
- return 0;
+ 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;
}
+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;
-unsigned int
-ecc_get_nbits( int algo, MPI *pkey )
-{
- if ( !is_ECC(algo) ){
- return 0;
- }
- if( DBG_CIPHER ){log_info("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] );
+ 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");
+ }
+ 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;
}
-const char *
-ecc_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, int *use )
+
+
+static unsigned int
+ecc_get_nbits (int algo, gcry_mpi_t *pkey)
{
- *npkey = 10;
- *nskey = 11;
- *nenc = 4;
- *nsig = 2;
-
- if( DBG_CIPHER ){log_info("ECC get info.\n");}
- switch( algo ) {
- case PUBKEY_ALGO_ECC:
- *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
- return "ECC";
- case PUBKEY_ALGO_ECC_S:
- *use = PUBKEY_USAGE_SIG;
- return "ECDSA";
- case PUBKEY_ALGO_ECC_E:
- *use = PUBKEY_USAGE_ENC;
- return "ECELG";
- default: *use = 0; return NULL;
+ (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/cipher/pubkey.c b/cipher/pubkey.c
index 0b14cb80..fe9ccdf6 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -59,6 +59,9 @@ static struct pubkey_table_entry
#if USE_DSA
{ &_gcry_pubkey_spec_dsa, GCRY_PK_DSA },
#endif
+#if USE_ECC
+ { &_gcry_pubkey_spec_ecdsa, GCRY_PK_ECDSA },
+#endif
{ NULL, 0 },
};
diff --git a/cipher/random.c b/cipher/random.c
index 819af4b7..cffc9ab0 100644
--- a/cipher/random.c
+++ b/cipher/random.c
@@ -1254,7 +1254,7 @@ _gcry_fast_random_poll (void)
lock_pool ();
if (rndpool)
{
- /* Yes, we are fully initalized. */
+ /* Yes, we are fully initialized. */
do_fast_random_poll ();
}
unlock_pool ();