瀏覽代碼

Attempt to implement support for "a" in ECC (not working yet)

Mark Karpelès 15 年之前
父節點
當前提交
69f70d911e

+ 8 - 4
src/headers/tomcrypt_math.h

@@ -338,29 +338,32 @@ typedef struct {
        @param G   The point to multiply
        @param R   The destination for kG  
        @param modulus  The modulus for the field
+       @param a   The "a" curve parameter
        @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only)
        @return CRYPT_OK on success
    */
-   int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
+   int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, void *a, int map);
 
    /** ECC GF(p) point addition 
        @param P    The first point
        @param Q    The second point
        @param R    The destination of P + Q
        @param modulus  The modulus
+       @param a    The curve "a" parameter
        @param mp   The "b" value from montgomery_setup()
        @return CRYPT_OK on success
    */
-   int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
+   int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *a, void *mp);
 
    /** ECC GF(p) point double 
        @param P    The first point
        @param R    The destination of 2P
        @param modulus  The modulus
+       @param a    The curve "a" parameter
        @param mp   The "b" value from montgomery_setup()
        @return CRYPT_OK on success
    */
-   int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp);
+   int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *a, void *mp);
 
    /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1)
        @param P     The point to map
@@ -379,12 +382,13 @@ typedef struct {
        @param kB       What to multiple B by
        @param C        [out] Destination point (can overlap with A or B
        @param modulus  Modulus for curve 
+       @param a        A parameter for curve 
        @return CRYPT_OK on success
    */ 
    int (*ecc_mul2add)(ecc_point *A, void *kA,
                       ecc_point *B, void *kB,
                       ecc_point *C,
-                           void *modulus);
+                           void *modulus, void *a);
 
 /* ---- (optional) rsa optimized math (for internal CRT) ---- */
 

+ 7 - 4
src/headers/tomcrypt_pk.h

@@ -219,6 +219,9 @@ typedef struct {
    /** The prime that defines the field the curve is in (encoded in hex) */
    char *prime;
 
+	 /** The fields A param (hex) */
+	 char *A;
+
    /** The fields B param (hex) */
    char *B;
 
@@ -309,10 +312,10 @@ int        ltc_ecc_is_valid_idx(int n);
 /* point ops (mp == montgomery digit) */
 #if !defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC) || defined(GMP_LTC_DESC)
 /* R = 2P */
-int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp);
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *a, void *mp);
 
 /* R = P + Q */
-int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *a, void *mp);
 #endif
 
 #if defined(LTC_MECC_FP)
@@ -330,14 +333,14 @@ void ltc_ecc_fp_tablelock(int lock);
 #endif
 
 /* R = kG */
-int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
+int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, void *a, int map);
 
 #ifdef LTC_ECC_SHAMIR
 /* kA*A + kB*B = C */
 int ltc_ecc_mul2add(ecc_point *A, void *kA,
                     ecc_point *B, void *kB,
                     ecc_point *C,
-                         void *modulus);
+                         void *modulus, void *a);
 
 #ifdef LTC_MECC_FP
 /* Shamir's trick with optimized point multiplication using fixed point cache */

+ 10 - 1
src/pk/ecc/ecc.c

@@ -9,7 +9,7 @@
  * Tom St Denis, [email protected], http://libtom.org
  */
 
-/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - a x + b
  *
  * All curves taken from NIST recommendation paper of July 1999
  * Available at http://csrc.nist.gov/cryptval/dss.htm
@@ -24,12 +24,14 @@
 #ifdef LTC_MECC
 
 /* This holds the key settings.  ***MUST*** be organized by size from smallest to largest. */
+// prime, A, B, order, Gx, Gy
 const ltc_ecc_set_type ltc_ecc_sets[] = {
 #ifdef ECC112
 {
         14,
         "SECP112R1",
         "DB7C2ABF62E35E668076BEAD208B",
+        "DB7C2ABF62E35E668076BEAD2088",
         "659EF8BA043916EEDE8911702B22",
         "DB7C2ABF62E35E7628DFAC6561C5",
         "09487239995A5EE76B55F9C2F098",
@@ -41,6 +43,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
         16,
         "SECP128R1",
         "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
+        "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
         "E87579C11079F43DD824993C2CEE5ED3",
         "FFFFFFFE0000000075A30D1B9038A115",
         "161FF7528B899B2D0C28607CA52C5B86",
@@ -52,6 +55,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
         20,
         "SECP160R1",
         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
         "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
         "0100000000000000000001F4C8F927AED3CA752257",
         "4A96B5688EF573284664698968C38BB913CBFC82",
@@ -63,6 +67,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
         24,
         "ECC-192",
         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
         "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
         "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
         "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
@@ -74,6 +79,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
         28,
         "ECC-224",
         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
         "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
         "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
         "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
@@ -85,6 +91,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
         32,
         "ECC-256",
         "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+        "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
         "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
         "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
         "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
@@ -96,6 +103,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
         48,
         "ECC-384",
         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
         "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
         "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
@@ -107,6 +115,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
         66,
         "ECC-521",
         "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+        "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
         "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
         "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
         "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",

+ 6 - 5
src/pk/ecc/ecc_make_key.c

@@ -9,7 +9,7 @@
  * Tom St Denis, [email protected], http://libtom.org
  */
 
-/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - a x + b
  *
  * All curves taken from NIST recommendation paper of July 1999
  * Available at http://csrc.nist.gov/cryptval/dss.htm
@@ -51,7 +51,7 @@ int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set
 {
    int            err;
    ecc_point     *base;
-   void          *prime, *order;
+   void          *prime, *order, *a;
    unsigned char *buf;
    int            keysize;
 
@@ -82,7 +82,7 @@ int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set
    }
 
    /* setup the key variables */
-   if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, NULL)) != CRYPT_OK) {
+   if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, &a, NULL)) != CRYPT_OK) {
       goto ERR_BUF;
    }
    base = ltc_ecc_new_point();
@@ -94,6 +94,7 @@ int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set
    /* read in the specs for this key */
    if ((err = mp_read_radix(prime,   (char *)key->dp->prime, 16)) != CRYPT_OK)                  { goto errkey; }
    if ((err = mp_read_radix(order,   (char *)key->dp->order, 16)) != CRYPT_OK)                  { goto errkey; }
+   if ((err = mp_read_radix(a,       (char *)key->dp->A, 16)) != CRYPT_OK)                      { goto errkey; }
    if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK)                     { goto errkey; }
    if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK)                     { goto errkey; }
    if ((err = mp_set(base->z, 1)) != CRYPT_OK)                                                  { goto errkey; }
@@ -104,7 +105,7 @@ int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set
        if((err = mp_mod(key->k, order, key->k)) != CRYPT_OK)                                    { goto errkey; }
    }
    /* make the public key */
-   if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK)              { goto errkey; }
+   if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, a, 1)) != CRYPT_OK)           { goto errkey; }
    key->type = PK_PRIVATE;
 
    /* free up ram */
@@ -114,7 +115,7 @@ errkey:
    mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
 cleanup:
    ltc_ecc_del_point(base);
-   mp_clear_multi(prime, order, NULL);
+   mp_clear_multi(prime, order, a, NULL);
 ERR_BUF:
 #ifdef LTC_CLEAN_STACK
    zeromem(buf, ECC_MAXSIZE);

+ 5 - 4
src/pk/ecc/ecc_shared_secret.c

@@ -36,7 +36,7 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
 {
    unsigned long  x;
    ecc_point     *result;
-   void          *prime;
+   void          *prime, *a;
    int            err;
 
    LTC_ARGCHK(private_key != NULL);
@@ -63,13 +63,14 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
       return CRYPT_MEM;
    }
 
-   if ((err = mp_init(&prime)) != CRYPT_OK) {
+   if ((err = mp_init_multi(&prime, &a, NULL)) != CRYPT_OK) {
       ltc_ecc_del_point(result);
       return err;
    }
 
    if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK)                               { goto done; }
-   if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1)) != CRYPT_OK)                { goto done; }
+   if ((err = mp_read_radix(a, (char *)private_key->dp->A, 16)) != CRYPT_OK)                                       { goto done; }
+   if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, a, 1)) != CRYPT_OK)             { goto done; }
 
    x = (unsigned long)mp_unsigned_bin_size(prime);
    if (*outlen < x) {
@@ -83,7 +84,7 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
    err     = CRYPT_OK;
    *outlen = x;
 done:
-   mp_clear(prime);
+   ltc_deinit_multi(prime, a, NULL);
    ltc_ecc_del_point(result);
    return err;
 }

+ 5 - 4
src/pk/ecc/ecc_test.c

@@ -29,11 +29,11 @@
 */
 int ecc_test(void)
 {
-   void     *modulus, *order;
+   void     *modulus, *order, *a;
    ecc_point  *G, *GG;
    int i, err, primality;
 
-   if ((err = mp_init_multi(&modulus, &order, NULL)) != CRYPT_OK) {
+   if ((err = mp_init_multi(&modulus, &order, &a, NULL)) != CRYPT_OK) {
       return err;
    }
 
@@ -52,6 +52,7 @@ int ecc_test(void)
        #endif
        if ((err = mp_read_radix(modulus, (char *)ltc_ecc_sets[i].prime, 16)) != CRYPT_OK)   { goto done; }
        if ((err = mp_read_radix(order, (char *)ltc_ecc_sets[i].order, 16)) != CRYPT_OK)     { goto done; }
+       if ((err = mp_read_radix(a, (char *)ltc_ecc_sets[i].A, 16)) != CRYPT_OK)             { goto done; }
 
        /* is prime actually prime? */
        if ((err = mp_prime_is_prime(modulus, 8, &primality)) != CRYPT_OK)                   { goto done; }
@@ -73,7 +74,7 @@ int ecc_test(void)
 
        /* then we should have G == (order + 1)G */
        if ((err = mp_add_d(order, 1, order)) != CRYPT_OK)                                   { goto done; }
-       if ((err = ltc_mp.ecc_ptmul(order, G, GG, modulus, 1)) != CRYPT_OK)                  { goto done; }
+       if ((err = ltc_mp.ecc_ptmul(order, G, GG, modulus, a, 1)) != CRYPT_OK)               { goto done; }
        if (mp_cmp(G->x, GG->x) != LTC_MP_EQ || mp_cmp(G->y, GG->y) != LTC_MP_EQ) {
           err = CRYPT_FAIL_TESTVECTOR;
           goto done;
@@ -83,7 +84,7 @@ int ecc_test(void)
 done:
    ltc_ecc_del_point(GG);
    ltc_ecc_del_point(G);
-   mp_clear_multi(order, modulus, NULL);
+   mp_clear_multi(order, modulus, a, NULL);
    return err;
 }
 

+ 10 - 7
src/pk/ecc/ecc_verify_hash.c

@@ -48,7 +48,7 @@ int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
                     int *stat, ecc_key *key)
 {
    ecc_point    *mG, *mQ;
-   void          *r, *s, *v, *w, *u1, *u2, *e, *p, *m;
+   void          *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a;
    void          *mp;
    int           err;
 
@@ -67,7 +67,7 @@ int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
    }
 
    /* allocate ints */
-   if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {
+   if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, &a, NULL)) != CRYPT_OK) {
       return CRYPT_MEM;
    }
 
@@ -93,6 +93,9 @@ int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
    /* get the modulus */
    if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK)                                { goto error; }
 
+   /* get the value for A */
+   if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK)                                    { goto error; }
+
    /* check for zero */
    if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
       err = CRYPT_INVALID_PACKET;
@@ -122,20 +125,20 @@ int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
 
    /* compute u1*mG + u2*mQ = mG */
    if (ltc_mp.ecc_mul2add == NULL) {
-      if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK)                                       { goto error; }
-      if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK)                                       { goto error; }
+      if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, a, 0)) != CRYPT_OK)                                    { goto error; }
+      if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, a, 0)) != CRYPT_OK)                                    { goto error; }
   
       /* find the montgomery mp */
       if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK)                                              { goto error; }
 
       /* add them */
-      if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK)                                      { goto error; }
+      if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, a, mp)) != CRYPT_OK)                                   { goto error; }
    
       /* reduce */
       if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK)                                                { goto error; }
    } else {
       /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
-      if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m)) != CRYPT_OK)                                { goto error; }
+      if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m, a)) != CRYPT_OK)                             { goto error; }
    }
 
    /* v = X_x1 mod n */
@@ -151,7 +154,7 @@ int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
 error:
    ltc_ecc_del_point(mG);
    ltc_ecc_del_point(mQ);
-   mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL);
+   mp_clear_multi(r, s, v, w, u1, u2, p, e, m, a, NULL);
    if (mp != NULL) { 
       mp_montgomery_free(mp);
    }

+ 10 - 9
src/pk/ecc/ltc_ecc_mul2add.c

@@ -37,7 +37,7 @@
 int ltc_ecc_mul2add(ecc_point *A, void *kA,
                     ecc_point *B, void *kB,
                     ecc_point *C,
-                         void *modulus)
+                         void *modulus, void *a)
 {
   ecc_point     *precomp[16];
   unsigned       bitbufA, bitbufB, lenA, lenB, len, y, nA, nB, nibble;
@@ -52,6 +52,7 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
   LTC_ARGCHK(kA      != NULL);
   LTC_ARGCHK(kB      != NULL);
   LTC_ARGCHK(modulus != NULL);
+  LTC_ARGCHK(a       != NULL);
 
   /* allocate memory */
   tA = XCALLOC(1, ECC_BUF_SIZE);
@@ -114,17 +115,17 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
   if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK)                                      { goto ERR_MU; }
 
   /* precomp [i,0](A + B) table */
-  if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, mp)) != CRYPT_OK)                               { goto ERR_MU; }
-  if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, mp)) != CRYPT_OK)                   { goto ERR_MU; }
+  if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, a, mp)) != CRYPT_OK)                            { goto ERR_MU; }
+  if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, a, mp)) != CRYPT_OK)                { goto ERR_MU; }
 
   /* precomp [0,i](A + B) table */
-  if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], modulus, mp)) != CRYPT_OK)                         { goto ERR_MU; }
-  if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], modulus, mp)) != CRYPT_OK)          { goto ERR_MU; }
+  if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], modulus, a, mp)) != CRYPT_OK)                      { goto ERR_MU; }
+  if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], modulus, a, mp)) != CRYPT_OK)       { goto ERR_MU; }
 
   /* precomp [i,j](A + B) table (i != 0, j != 0) */
   for (x = 1; x < 4; x++) {
      for (y = 1; y < 4; y++) {
-        if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+        if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, a, mp)) != CRYPT_OK) { goto ERR_MU; }
      }
   }   
 
@@ -157,8 +158,8 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
      /* double twice, only if this isn't the first */
      if (first == 0) {
         /* double twice */
-        if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK)                  { goto ERR_MU; }
-        if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK)                  { goto ERR_MU; }
+        if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, a, mp)) != CRYPT_OK)               { goto ERR_MU; }
+        if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, a, mp)) != CRYPT_OK)               { goto ERR_MU; }
      }
 
      /* if not both zero */
@@ -171,7 +172,7 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
            if ((err = mp_copy(precomp[nA + (nB<<2)]->z, C->z)) != CRYPT_OK)           { goto ERR_MU; }
         } else {
            /* if not first, add from table */
-           if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+           if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, modulus, a, mp)) != CRYPT_OK) { goto ERR_MU; }
         }
      }
   }

+ 13 - 11
src/pk/ecc/ltc_ecc_mulmod.c

@@ -9,7 +9,7 @@
  * Tom St Denis, [email protected], http://libtom.org
  */
 
-/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+/* Implements ECC over Z/pZ for curve y^2 = x^3 + ax + b
  *
  * All curves taken from NIST recommendation paper of July 1999
  * Available at http://csrc.nist.gov/cryptval/dss.htm
@@ -33,10 +33,11 @@
    @param G    The base point
    @param R    [out] Destination for kG
    @param modulus  The modulus of the field the ECC curve is in
+   @param a    The A parameter of the ECC curve
    @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
    @return CRYPT_OK on success
 */
-int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
+int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, void *a, int map)
 {
    ecc_point *tG, *M[8];
    int        i, j, err;
@@ -48,6 +49,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
    LTC_ARGCHK(G       != NULL);
    LTC_ARGCHK(R       != NULL);
    LTC_ARGCHK(modulus != NULL);
+   LTC_ARGCHK(a       != NULL);
 
    /* init montgomery reduction */
    if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
@@ -95,13 +97,13 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
    
    /* calc the M tab, which holds kG for k==8..15 */
    /* M[0] == 8G */
-   if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK)                 { goto done; }
-   if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK)               { goto done; }
-   if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK)               { goto done; }
+   if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, a, mp)) != CRYPT_OK)              { goto done; }
+   if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, a, mp)) != CRYPT_OK)            { goto done; }
+   if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, a, mp)) != CRYPT_OK)            { goto done; }
 
    /* now find (8+k)G for k=1..7 */
    for (j = 9; j < 16; j++) {
-       if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK)   { goto done; }
+       if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, a, mp)) != CRYPT_OK) { goto done; }
    }
 
    /* setup sliding window */
@@ -135,7 +137,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
 
      /* if the bit is zero and mode == 1 then we double */
      if (mode == 1 && i == 0) {
-        if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK)                 { goto done; }
+        if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, a, mp)) != CRYPT_OK)              { goto done; }
         continue;
      }
 
@@ -156,11 +158,11 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
          /* ok window is filled so double as required and add  */
          /* double first */
          for (j = 0; j < WINSIZE; j++) {
-           if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK)              { goto done; }
+           if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, a, mp)) != CRYPT_OK)           { goto done; }
          }
 
          /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
-         if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK)   { goto done; }
+         if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, a, mp)) != CRYPT_OK) { goto done; }
        }
        /* empty window and reset */
        bitcpy = bitbuf = 0;
@@ -174,7 +176,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
      for (j = 0; j < bitcpy; j++) {
        /* only double if we have had at least one add first */
        if (first == 0) {
-          if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK)              { goto done; }
+          if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, a, mp)) != CRYPT_OK)           { goto done; }
        }
 
        bitbuf <<= 1;
@@ -187,7 +189,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
             first = 0;
          } else {
             /* then add */
-            if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK)        { goto done; }
+            if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, a, mp)) != CRYPT_OK)     { goto done; }
          }
        }
      }

+ 3 - 2
src/pk/ecc/ltc_ecc_projective_add_point.c

@@ -29,10 +29,11 @@
    @param Q        The point to add
    @param R        [out] The destination of the double
    @param modulus  The modulus of the field the ECC curve is in
+   @param a        The A parameter of the ECC curve
    @param mp       The "b" value from montgomery_setup()
    @return CRYPT_OK on success
 */
-int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp)
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *a, void *mp)
 {
    void  *t1, *t2, *x, *y, *z;
    int    err;
@@ -54,7 +55,7 @@ int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void
         (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) &&
         (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) {
         mp_clear_multi(t1, t2, x, y, z, NULL);
-        return ltc_ecc_projective_dbl_point(P, R, modulus, mp);
+        return ltc_ecc_projective_dbl_point(P, R, modulus, a, mp);
    }
 
    if ((err = mp_copy(P->x, x)) != CRYPT_OK)                                   { goto done; }

+ 35 - 28
src/pk/ecc/ltc_ecc_projective_dbl_point.c

@@ -9,7 +9,7 @@
  * Tom St Denis, [email protected], http://libtom.org
  */
 
-/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+/* Implements ECC over Z/pZ for curve y^2 = x^3 + ax + b
  *
  * All curves taken from NIST recommendation paper of July 1999
  * Available at http://csrc.nist.gov/cryptval/dss.htm
@@ -28,10 +28,11 @@
    @param P   The point to double
    @param R   [out] The destination of the double
    @param modulus  The modulus of the field the ECC curve is in
+   @param          The a parameter of the ECC curve
    @param mp       The "b" value from montgomery_setup()
    @return CRYPT_OK on success
 */
-int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp)
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *a, void *mp)
 {
    void *t1, *t2;
    int   err;
@@ -39,6 +40,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void
    LTC_ARGCHK(P       != NULL);
    LTC_ARGCHK(R       != NULL);
    LTC_ARGCHK(modulus != NULL);
+   LTC_ARGCHK(a       != NULL);
    LTC_ARGCHK(mp      != NULL);
 
    if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
@@ -51,9 +53,38 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void
       if ((err = mp_copy(P->z, R->z)) != CRYPT_OK)                                { goto done; }
    }
 
-   /* t1 = Z * Z */
-   if ((err = mp_sqr(R->z, t1)) != CRYPT_OK)                                      { goto done; }
+   /* T1 = X * X */
+   if ((err = mp_sqr(R->x, t1)) != CRYPT_OK)                                      { goto done; }
    if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)                 { goto done; }
+
+   /* T2 = 2T1 */
+   if ((err = mp_add(t1, t1, t2)) != CRYPT_OK)                                    { goto done; }
+   if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+     if ((err = mp_sub(t2, modulus, t1)) != CRYPT_OK)                             { goto done; }
+   }
+   /* T2 = T2 + T1 */
+   if ((err = mp_add(t1, t2, t2)) != CRYPT_OK)                                    { goto done; }
+   if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+     if ((err = mp_sub(t2, modulus, t1)) != CRYPT_OK)                             { goto done; }
+   }
+   if (mp_iszero(a)) {
+      /* T1 = T2 */
+      mp_copy(t2, t1);
+   } else {
+      /* T1 = Z ^ 4 */
+      if ((err = mp_sqr(R->z, t1)) != CRYPT_OK)                                      { goto done; }
+      if ((err = mp_sqr(t1, t1)) != CRYPT_OK)                                        { goto done; }
+      if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)                 { goto done; }
+      /* T1 = T1 * A */
+      if ((err = mp_mul(t1, a, t1)) != CRYPT_OK)                                     { goto done; }
+      if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)                 { goto done; }
+      /* T1 = T1 + T2 */
+      if ((err = mp_add(t1, t2, t1)) != CRYPT_OK)                                    { goto done; }
+      if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+         if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                            { goto done; }
+      }
+   }
+
    /* Z = Y * Z */
    if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK)                              { goto done; }
    if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK)               { goto done; }
@@ -63,30 +94,6 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void
       if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK)                        { goto done; }
    }
    
-   /* T2 = X - T1 */
-   if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK)                                  { goto done; }
-   if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
-      if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK)                            { goto done; }
-   }
-   /* T1 = X + T1 */
-   if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK)                                  { goto done; }
-   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
-      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                            { goto done; }
-   }
-   /* T2 = T1 * T2 */
-   if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK)                                    { goto done; }
-   if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)                 { goto done; }
-   /* T1 = 2T2 */
-   if ((err = mp_add(t2, t2, t1)) != CRYPT_OK)                                    { goto done; }
-   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
-      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                            { goto done; }
-   }
-   /* T1 = T1 + T2 */
-   if ((err = mp_add(t1, t2, t1)) != CRYPT_OK)                                    { goto done; }
-   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
-      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                            { goto done; }
-   }
-
    /* Y = 2Y */
    if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK)                              { goto done; }
    if (mp_cmp(R->y, modulus) != LTC_MP_LT) {