mpi: Improve support for non-Weierstrass support.
authorWerner Koch <wk@gnupg.org>
Sat, 7 Sep 2013 08:06:46 +0000 (10:06 +0200)
committerWerner Koch <wk@gnupg.org>
Sat, 7 Sep 2013 08:16:45 +0000 (10:16 +0200)
* mpi/ec.c (ec_p_init): Add args MODEL and P.  Change all callers.
(_gcry_mpi_ec_p_internal_new): Ditto.
(_gcry_mpi_ec_p_new): Ditto.
* cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Return
GPG_ERR_UNKNOWN_CURVE instead of invalid value.  Init curve model.
* cipher/ecc.c (ecc_verify, ecc_encrypt_raw): Ditto.
* cipher/pubkey.c (sexp_data_to_mpi): Fix EDDSA flag error checking.
--

(fixes commit c26be7a337d0bf98193bc58e043209e46d0769bb)

cipher/ecc-curves.c
cipher/ecc-misc.c
cipher/ecc.c
cipher/pubkey.c
mpi/ec.c
src/mpi.h

index e956dad..89a4d87 100644 (file)
@@ -312,29 +312,30 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
           break;
     }
   if (!domain_parms[idx].desc)
-    return GPG_ERR_INV_VALUE;
+    return GPG_ERR_UNKNOWN_CURVE;
 
   /* In fips mode we only support NIST curves.  Note that it is
      possible to bypass this check by specifying the curve parameters
      directly.  */
   if (fips_mode () && !domain_parms[idx].fips )
-
     return GPG_ERR_NOT_SUPPORTED;
 
   switch (domain_parms[idx].model)
     {
     case MPI_EC_WEIERSTRASS:
-      break;
     case MPI_EC_TWISTEDEDWARDS:
+      break;
     case MPI_EC_MONTGOMERY:
       return GPG_ERR_NOT_SUPPORTED;
     default:
       return GPG_ERR_BUG;
     }
 
+
   if (r_nbits)
     *r_nbits = domain_parms[idx].nbits;
 
+  curve->model = domain_parms[idx].model;
   curve->p = scanval (domain_parms[idx].p);
   curve->a = scanval (domain_parms[idx].a);
   curve->b = scanval (domain_parms[idx].b);
@@ -547,6 +548,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
 {
   gpg_err_code_t errc;
   gcry_ctx_t ctx = NULL;
+  enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
   gcry_mpi_t p = NULL;
   gcry_mpi_t a = NULL;
   gcry_mpi_t b = NULL;
@@ -626,6 +628,8 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
           goto leave;
         }
 
+      model = E->model;
+
       if (!p)
         {
           p = E->p;
@@ -657,7 +661,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
       gcry_free (E);
     }
 
-  errc = _gcry_mpi_ec_p_new (&ctx, p, a);
+  errc = _gcry_mpi_ec_p_new (&ctx, model, p, a, b);
   if (!errc)
     {
       mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
@@ -719,7 +723,7 @@ _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
 
   g_x = mpi_new (0);
   g_y = mpi_new (0);
-  ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (0, E.p, E.a, NULL);
   if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
     log_fatal ("ecc get param: Failed to get affine coordinates\n");
   _gcry_mpi_ec_free (ctx);
index 5c86121..6c34902 100644 (file)
@@ -53,6 +53,7 @@ _gcry_ecc_curve_copy (elliptic_curve_t E)
 {
   elliptic_curve_t R;
 
+  R.model = E.model;
   R.p = mpi_copy (E.p);
   R.a = mpi_copy (E.a);
   R.b = mpi_copy (E.b);
index 0cb279f..9d318cc 100644 (file)
@@ -174,10 +174,11 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
 
   /* Compute Q.  */
   point_init (&Q);
-  ctx = _gcry_mpi_ec_p_internal_new (E.p, E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (E.model, E.p, E.a, E.b);
   _gcry_mpi_ec_mul_point (&Q, sk->d, &E.G, ctx);
 
   /* Copy the stuff to the key structures. */
+  sk->E.model = E.model;
   sk->E.p = mpi_copy (E.p);
   sk->E.a = mpi_copy (E.a);
   sk->E.b = mpi_copy (E.b);
@@ -343,7 +344,7 @@ check_secret_key (ECC_secret_key * sk)
       goto leave;
     }
 
-  ctx = _gcry_mpi_ec_p_internal_new (sk->E.p, sk->E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.p, sk->E.a, sk->E.b);
 
   _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
   if (mpi_cmp_ui (Q.z, 0))
@@ -457,7 +458,8 @@ sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s,
   mpi_set_ui (s, 0);
   mpi_set_ui (r, 0);
 
-  ctx = _gcry_mpi_ec_p_internal_new (skey->E.p, skey->E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (skey->E.model,
+                                     skey->E.p, skey->E.a, skey->E.b);
 
   while (!mpi_cmp_ui (s, 0)) /* s == 0 */
     {
@@ -556,7 +558,8 @@ verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey,
   point_init (&Q1);
   point_init (&Q2);
 
-  ctx = _gcry_mpi_ec_p_internal_new (pkey->E.p, pkey->E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model,
+                                     pkey->E.p, pkey->E.a, pkey->E.b);
 
   /* h  = s^(-1) (mod n) */
   mpi_invm (h, s, pkey->E.n);
@@ -786,6 +789,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey)
       || !skey[6])
     return GPG_ERR_BAD_MPI;
 
+  sk.E.model = MPI_EC_WEIERSTRASS;
   sk.E.p = skey[0];
   sk.E.a = skey[1];
   sk.E.b = skey[2];
@@ -833,6 +837,9 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
       || !skey[6] )
     return GPG_ERR_BAD_MPI;
 
+  sk.E.model = ((flags & PUBKEY_FLAG_EDDSA)
+                ? MPI_EC_TWISTEDEDWARDS
+                : MPI_EC_WEIERSTRASS);
   sk.E.p = skey[0];
   sk.E.a = skey[1];
   sk.E.b = skey[2];
@@ -880,6 +887,9 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
       || !pkey[3] || !pkey[4] || !pkey[5] )
     return GPG_ERR_BAD_MPI;
 
+  pk.E.model = ((flags & PUBKEY_FLAG_EDDSA)
+                ? MPI_EC_TWISTEDEDWARDS
+                : MPI_EC_WEIERSTRASS);
   pk.E.p = pkey[0];
   pk.E.a = pkey[1];
   pk.E.b = pkey[2];
@@ -976,6 +986,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
       || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5])
     return GPG_ERR_BAD_MPI;
 
+  pk.E.model = MPI_EC_WEIERSTRASS;
   pk.E.p = pkey[0];
   pk.E.a = pkey[1];
   pk.E.b = pkey[2];
@@ -996,7 +1007,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k,
       return err;
     }
 
-  ctx = _gcry_mpi_ec_p_internal_new (pk.E.p, pk.E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.p, pk.E.a, pk.E.b);
 
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
   {
@@ -1084,7 +1095,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
       return err;
     }
 
-
+  sk.E.model = MPI_EC_WEIERSTRASS;
   sk.E.p = skey[0];
   sk.E.a = skey[1];
   sk.E.b = skey[2];
@@ -1108,7 +1119,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
     }
   sk.d = skey[6];
 
-  ctx = _gcry_mpi_ec_p_internal_new (sk.E.p, sk.E.a);
+  ctx = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.p, sk.E.a, sk.E.b);
 
   /* R = dkG */
   point_init (&R);
index fb8de14..141d656 100644 (file)
@@ -2588,7 +2588,7 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
       void *value;
       size_t valuelen;
 
-      if (lvalue)
+      if (!lvalue)
         {
           rc = GPG_ERR_INV_OBJ;
           goto leave;
index 7da2e3b..049afa9 100644 (file)
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -386,14 +386,18 @@ ec_get_two_inv_p (mpi_ec_t ec)
    field GF(p).  P is the prime specifying this field, A is the first
    coefficient.  CTX is expected to be zeroized.  */
 static void
-ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a)
+ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
+           gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
 {
   int i;
 
   /* Fixme: Do we want to check some constraints? e.g.  a < p  */
 
+  ctx->model = model;
   ctx->p = mpi_copy (p);
   ctx->a = mpi_copy (a);
+  if (b && model == MPI_EC_TWISTEDEDWARDS)
+    ctx->b = mpi_copy (b);
 
   ec_get_reset (ctx);
 
@@ -461,41 +465,35 @@ ec_deinit (void *opaque)
 
 /* This function returns a new context for elliptic curve based on the
    field GF(p).  P is the prime specifying this field, A is the first
-   coefficient.  This function is only used within Libgcrypt and not
+   coefficient, B is the second coefficient, and MODEL is the model
+   for the curve.  This function is only used within Libgcrypt and not
    part of the public API.
 
    This context needs to be released using _gcry_mpi_ec_free.  */
 mpi_ec_t
-_gcry_mpi_ec_p_internal_new (gcry_mpi_t p, gcry_mpi_t a)
+_gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
+                             gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
 {
   mpi_ec_t ctx;
 
   ctx = gcry_xcalloc (1, sizeof *ctx);
-  ec_p_init (ctx, p, a);
+  ec_p_init (ctx, model, p, a, b);
 
   return ctx;
 }
 
 
-void
-_gcry_mpi_ec_free (mpi_ec_t ctx)
-{
-  if (ctx)
-    {
-      ec_deinit (ctx);
-      gcry_free (ctx);
-    }
-}
+/* This is a variant of _gcry_mpi_ec_p_internal_new which returns an
+   public contect and does some error checking on the supplied
+   arguments.  On success the new context is stored at R_CTX and 0 is
+   returned; on error NULL is stored at R_CTX and an error code is
+   returned.
 
-
-/* This function returns a new context for elliptic curve operations
-   based on the field GF(p).  P is the prime specifying this field, A
-   is the first coefficient.  On success the new context is stored at
-   R_CTX and 0 is returned; on error NULL is stored at R_CTX and an
-   error code is returned.  The context needs to be released using
-   gcry_ctx_release.  This is an internal fucntions.  */
+   The context needs to be released using gcry_ctx_release.  */
 gpg_err_code_t
-_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
+_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
+                    enum gcry_mpi_ec_models model,
+                    gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
 {
   gcry_ctx_t ctx;
   mpi_ec_t ec;
@@ -508,12 +506,24 @@ _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
   if (!ctx)
     return gpg_err_code_from_syserror ();
   ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
-  ec_p_init (ec, p, a);
+  ec_p_init (ec, model, p, a, b);
 
   *r_ctx = ctx;
   return 0;
 }
 
+
+void
+_gcry_mpi_ec_free (mpi_ec_t ctx)
+{
+  if (ctx)
+    {
+      ec_deinit (ctx);
+      gcry_free (ctx);
+    }
+}
+
+
 gcry_mpi_t
 _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy)
 {
@@ -772,6 +782,9 @@ dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
 static void
 dup_point_montgomery (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
 {
+  (void)result;
+  (void)point;
+  (void)ctx;
   log_fatal ("%s: %s not yet supported\n",
              "_gcry_mpi_ec_dup_point", "Montgomery");
 }
@@ -953,6 +966,10 @@ add_points_montgomery (mpi_point_t result,
                        mpi_point_t p1, mpi_point_t p2,
                        mpi_ec_t ctx)
 {
+  (void)result;
+  (void)p1;
+  (void)p2;
+  (void)ctx;
   log_fatal ("%s: %s not yet supported\n",
              "_gcry_mpi_ec_add_points", "Montgomery");
 }
index 09ba717..6406112 100644 (file)
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -291,8 +291,13 @@ enum gcry_mpi_ec_models
 struct mpi_ec_ctx_s;
 typedef struct mpi_ec_ctx_s *mpi_ec_t;
 
-mpi_ec_t _gcry_mpi_ec_p_internal_new (gcry_mpi_t p, gcry_mpi_t a);
+mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
+                                      gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b);
+gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
+                                   enum gcry_mpi_ec_models model,
+                                   gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b);
 void _gcry_mpi_ec_free (mpi_ec_t ctx);
+
 int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
                              mpi_ec_t ctx);
 void _gcry_mpi_ec_dup_point (mpi_point_t result,
@@ -303,11 +308,10 @@ void _gcry_mpi_ec_add_points (mpi_point_t result,
 void _gcry_mpi_ec_mul_point (mpi_point_t result,
                              gcry_mpi_t scalar, mpi_point_t point,
                              mpi_ec_t ctx);
+int  _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx);
 
 gcry_mpi_t _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx);
 
-gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
-                                   gcry_mpi_t p, gcry_mpi_t a);
 gpg_err_code_t _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
                                  gcry_sexp_t keyparam, const char *curvename);
 gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy);