pubkey: Move sexp parsing of remaining fucntions to the modules.
authorWerner Koch <wk@gnupg.org>
Fri, 11 Oct 2013 20:37:41 +0000 (22:37 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 11 Oct 2013 20:37:58 +0000 (22:37 +0200)
* cipher/pubkey.c (release_mpi_array): Remove.
(pubkey_check_secret_key): Remove.
(sexp_elements_extract): Remove.
(sexp_elements_extract_ecc): Remove.
(sexp_to_key): Remove.
(get_hash_algo): Remove.
(gcry_pk_testkey): Revamp.
(gcry_pk_get_curve): Revamp.
* cipher/rsa.c (rsa_check_secret_key): Revamp.
* cipher/elgamal.c (elg_check_secret_key): Revamp.
* cipher/dsa.c (dsa_check_secret_key): Revamp.
* cipher/ecc.c (ecc_check_secret_key): Revamp.
* cipher/ecc-curves.c: Include cipher.h and pubkey-internal.h
(_gcry_ecc_get_curve): Revamp.

* cipher/pubkey-util.c (_gcry_pk_util_extract_mpis): Set passed and
used parameters on error to NULL.
--

That is the final part of the changes modulo introduced regressions.
pubkey.c is now actually maintainable code.

Signed-off-by: Werner Koch <wk@gnupg.org>
cipher/dsa.c
cipher/ecc-common.h
cipher/ecc-curves.c
cipher/ecc.c
cipher/elgamal.c
cipher/pubkey-util.c
cipher/pubkey.c
cipher/rsa.c
src/cipher-proto.h

index 3dfef07..f86ff15 100644 (file)
@@ -928,27 +928,29 @@ dsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 
 
 static gcry_err_code_t
-dsa_check_secret_key (int algo, gcry_mpi_t *skey)
+dsa_check_secret_key (gcry_sexp_t keyparms)
 {
-  gcry_err_code_t err = GPG_ERR_NO_ERROR;
-  DSA_secret_key sk;
+  gcry_err_code_t rc;
+  DSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL};
 
-  (void)algo;
+  rc = _gcry_pk_util_extract_mpis (keyparms, "pqgyx",
+                                   &sk.p, &sk.q, &sk.g, &sk.y, &sk.x,
+                                   NULL);
+  if (rc)
+    goto leave;
 
-  if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]) || (! skey[4]))
-    err = GPG_ERR_BAD_MPI;
-  else
-    {
-      sk.p = skey[0];
-      sk.q = skey[1];
-      sk.g = skey[2];
-      sk.y = skey[3];
-      sk.x = skey[4];
-      if (! check_secret_key (&sk))
-       err = GPG_ERR_BAD_SECKEY;
-    }
+  if (!check_secret_key (&sk))
+    rc = GPG_ERR_BAD_SECKEY;
 
-  return err;
+ leave:
+  gcry_mpi_release (sk.p);
+  gcry_mpi_release (sk.q);
+  gcry_mpi_release (sk.g);
+  gcry_mpi_release (sk.y);
+  gcry_mpi_release (sk.x);
+  if (DBG_CIPHER)
+    log_debug ("dsa_testkey    => %s\n", gpg_strerror (rc));
+  return rc;
 }
 
 
@@ -976,7 +978,7 @@ dsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   rc = _gcry_pk_util_extract_mpis (keyparms, "pqgyx",
                                    &sk.p, &sk.q, &sk.g, &sk.y, &sk.x, NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_mpidump ("dsa_sign      p", sk.p);
@@ -1053,7 +1055,7 @@ dsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   rc = _gcry_pk_util_extract_mpis (s_keyparms, "pqgy",
                                    &pk.p, &pk.q, &pk.g, &pk.y, NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_mpidump ("dsa_verify    p", pk.p);
index cdb1362..0be1f2c 100644 (file)
@@ -68,7 +68,7 @@ gpg_err_code_t _gcry_ecc_fill_in_curve (unsigned int nbits,
                                         elliptic_curve_t *curve,
                                         unsigned int *r_nbits);
 
-const char *_gcry_ecc_get_curve (gcry_mpi_t *pkey,
+const char *_gcry_ecc_get_curve (gcry_sexp_t keyparms,
                                  int iterator,
                                  unsigned int *r_nbits);
 gcry_err_code_t _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey);
index 971dd32..53433a2 100644 (file)
 
 #include "g10lib.h"
 #include "mpi.h"
+#include "cipher.h"
 #include "context.h"
 #include "ec-context.h"
+#include "pubkey-internal.h"
 #include "ecc-common.h"
 
 
@@ -405,18 +407,20 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
 /* Return the name matching the parameters in PKEY.  This works only
    with curves described by the Weierstrass equation. */
 const char *
-_gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
+_gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
 {
-  gpg_err_code_t err;
+  const char *result = NULL;
   elliptic_curve_t E;
+  gcry_mpi_t mpi_g = NULL;
+  gcry_mpi_t tmp = NULL;
   int idx;
-  gcry_mpi_t tmp;
-  const char *result = NULL;
+
+  memset (&E, 0, sizeof E);
 
   if (r_nbits)
     *r_nbits = 0;
 
-  if (!pkey)
+  if (!keyparms)
     {
       idx = iterator;
       if (idx >= 0 && idx < DIM (domain_parms))
@@ -428,23 +432,20 @@ _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
       return result;
     }
 
-  if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
-    return NULL;
 
-  E.model = MPI_EC_WEIERSTRASS;
-  E.dialect = ECC_DIALECT_STANDARD;
-  E.name = NULL;
-  E.p = pkey[0];
-  E.a = pkey[1];
-  E.b = pkey[2];
-  _gcry_mpi_point_init (&E.G);
-  err = _gcry_ecc_os2ec (&E.G, pkey[3]);
-  if (err)
+  /*
+   * Extract the curve parameters..
+   */
+  if (_gcry_pk_util_extract_mpis (keyparms, "-pabgn",
+                                  &E.p, &E.a, &E.b, &mpi_g, &E.n,
+                                  NULL))
+    goto leave;
+  if (mpi_g)
     {
-      _gcry_mpi_point_free_parts (&E.G);
-      return NULL;
+      _gcry_mpi_point_init (&E.G);
+      if (_gcry_ecc_os2ec (&E.G, mpi_g))
+        goto leave;
     }
-  E.n = pkey[4];
 
   for (idx = 0; domain_parms[idx].desc; idx++)
     {
@@ -471,22 +472,26 @@ _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
                           tmp = scanval (domain_parms[idx].g_y);
                           if (!mpi_cmp (tmp, E.G.y))
                             {
-                              mpi_free (tmp);
                               result = domain_parms[idx].desc;
                               if (r_nbits)
                                 *r_nbits = domain_parms[idx].nbits;
-                              break;
+                              goto leave;
                             }
                         }
                     }
                 }
             }
         }
-      mpi_free (tmp);
     }
 
+ leave:
+  gcry_mpi_release (tmp);
+  gcry_mpi_release (E.p);
+  gcry_mpi_release (E.a);
+  gcry_mpi_release (E.b);
+  gcry_mpi_release (mpi_g);
   _gcry_mpi_point_free_parts (&E.G);
-
+  gcry_mpi_release (E.n);
   return result;
 }
 
index 17724e8..bd4d253 100644 (file)
@@ -1397,66 +1397,106 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 
 
 static gcry_err_code_t
-ecc_check_secret_key (int algo, gcry_mpi_t *skey)
+ecc_check_secret_key (gcry_sexp_t keyparms)
 {
-  gpg_err_code_t err;
+  gcry_err_code_t rc;
+  gcry_sexp_t l1 = NULL;
+  char *curvename = NULL;
+  gcry_mpi_t mpi_g = NULL;
+  gcry_mpi_t mpi_q = NULL;
   ECC_secret_key sk;
 
-  (void)algo;
-
-  /* FIXME:  This check looks a bit fishy:  Now long is the array?  */
-  if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
-      || !skey[6])
-    return GPG_ERR_BAD_MPI;
+  memset (&sk, 0, sizeof sk);
 
-  sk.E.model = MPI_EC_WEIERSTRASS;
-  sk.E.p = skey[0];
-  sk.E.a = skey[1];
-  sk.E.b = skey[2];
-  point_init (&sk.E.G);
-  err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
-  if (err)
+  /*
+   * Extract the key.
+   */
+  rc = _gcry_pk_util_extract_mpis (keyparms, "-p?a?b?g?n?/q?+d",
+                                   &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
+                                   &mpi_q, &sk.d, NULL);
+  if (rc)
+    goto leave;
+  if (mpi_g)
+    {
+      point_init (&sk.E.G);
+      rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
+      if (rc)
+        goto leave;
+    }
+  /* Add missing parameters using the optional curve parameter.  */
+  gcry_sexp_release (l1);
+  l1 = gcry_sexp_find_token (keyparms, "curve", 5);
+  if (l1)
     {
-      point_free (&sk.E.G);
-      return err;
+      curvename = gcry_sexp_nth_string (l1, 1);
+      if (curvename)
+        {
+          rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
+          if (rc)
+            return rc;
+        }
     }
-  sk.E.n = skey[4];
-  point_init (&sk.Q);
-  err = _gcry_ecc_os2ec (&sk.Q, skey[5]);
-  if (err)
+  /* Guess required fields if a curve parameter has not been given.
+     FIXME: This is a crude hacks.  We need to fix that.  */
+  if (!curvename)
     {
-      point_free (&sk.E.G);
-      point_free (&sk.Q);
-      return err;
+      sk.E.model = MPI_EC_WEIERSTRASS;
+      sk.E.dialect = ECC_DIALECT_STANDARD;
+    }
+  if (DBG_CIPHER)
+    {
+      log_debug ("ecc_testkey inf: %s/%s\n",
+                 _gcry_ecc_model2str (sk.E.model),
+                 _gcry_ecc_dialect2str (sk.E.dialect));
+      if (sk.E.name)
+        log_debug  ("ecc_testkey nam: %s\n", sk.E.name);
+      log_printmpi ("ecc_testkey   p", sk.E.p);
+      log_printmpi ("ecc_testkey   a", sk.E.a);
+      log_printmpi ("ecc_testkey   b", sk.E.b);
+      log_printpnt ("ecc_testkey g",   &sk.E.G, NULL);
+      log_printmpi ("ecc_testkey   n", sk.E.n);
+      log_printmpi ("ecc_testkey   q", mpi_q);
+      if (!fips_mode ())
+        log_printmpi ("ecc_testkey   d", sk.d);
+    }
+  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.d)
+    {
+      rc = GPG_ERR_NO_OBJ;
+      goto leave;
     }
 
-  {
-    const unsigned char *buf;
-    unsigned int n;
-
-    gcry_assert (mpi_is_opaque (skey[6]));
+  if (mpi_q)
+    {
+      point_init (&sk.Q);
+      rc = _gcry_ecc_os2ec (&sk.Q, mpi_q);
+      if (rc)
+        goto leave;
+    }
+  else
+    {
+      /* The current test requires Q.  */
+      rc = GPG_ERR_NO_OBJ;
+      goto leave;
+    }
 
-    buf = gcry_mpi_get_opaque (skey[6], &n);
-    if (!buf)
-      err = GPG_ERR_INV_OBJ;
-    else
-      {
-        n = (n + 7)/8;
-        sk.d = NULL;
-        err = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL);
-        if (!err)
-          {
-            if (check_secret_key (&sk))
-              err = GPG_ERR_BAD_SECKEY;
-            gcry_mpi_release (sk.d);
-            sk.d = NULL;
-          }
-      }
-  }
+  if (check_secret_key (&sk))
+    rc = GPG_ERR_BAD_SECKEY;
 
+ leave:
+  gcry_mpi_release (sk.E.p);
+  gcry_mpi_release (sk.E.a);
+  gcry_mpi_release (sk.E.b);
+  gcry_mpi_release (mpi_g);
   point_free (&sk.E.G);
+  gcry_mpi_release (sk.E.n);
+  gcry_mpi_release (mpi_q);
   point_free (&sk.Q);
-  return err;
+  gcry_mpi_release (sk.d);
+  gcry_free (curvename);
+  gcry_sexp_release (l1);
+  if (DBG_CIPHER)
+    log_debug ("ecc_testkey   => %s\n", gpg_strerror (rc));
+  return rc;
 }
 
 
index 7fedc7b..691e122 100644 (file)
@@ -730,27 +730,28 @@ elg_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 
 
 static gcry_err_code_t
-elg_check_secret_key (int algo, gcry_mpi_t *skey)
+elg_check_secret_key (gcry_sexp_t keyparms)
 {
-  gcry_err_code_t err = GPG_ERR_NO_ERROR;
-  ELG_secret_key sk;
-
-  (void)algo;
+  gcry_err_code_t rc;
+  ELG_secret_key sk = {NULL, NULL, NULL, NULL};
 
-  if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]))
-    err = GPG_ERR_BAD_MPI;
-  else
-    {
-      sk.p = skey[0];
-      sk.g = skey[1];
-      sk.y = skey[2];
-      sk.x = skey[3];
+  rc = _gcry_pk_util_extract_mpis (keyparms, "pgyx",
+                                   &sk.p, &sk.g, &sk.y, &sk.x,
+                                   NULL);
+  if (rc)
+    goto leave;
 
-      if (! check_secret_key (&sk))
-       err = GPG_ERR_BAD_SECKEY;
-    }
+  if (!check_secret_key (&sk))
+    rc = GPG_ERR_BAD_SECKEY;
 
-  return err;
+ leave:
+  gcry_mpi_release (sk.p);
+  gcry_mpi_release (sk.g);
+  gcry_mpi_release (sk.y);
+  gcry_mpi_release (sk.x);
+  if (DBG_CIPHER)
+    log_debug ("elg_testkey    => %s\n", gpg_strerror (rc));
+  return rc;
 }
 
 
@@ -782,7 +783,7 @@ elg_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   /* Extract the key.  */
   rc = _gcry_pk_util_extract_mpis (keyparms, "pgy", &pk.p, &pk.g, &pk.y, NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_mpidump ("elg_encrypt  p", pk.p);
@@ -849,7 +850,7 @@ elg_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
                                    &sk.p, &sk.g, &sk.y, &sk.x,
                                    NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_printmpi ("elg_decrypt    p", sk.p);
@@ -942,7 +943,7 @@ elg_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   rc = _gcry_pk_util_extract_mpis (keyparms, "pgyx",
                                    &sk.p, &sk.g, &sk.y, &sk.x, NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_mpidump ("elg_sign      p", sk.p);
@@ -1020,7 +1021,7 @@ elg_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   rc = _gcry_pk_util_extract_mpis (s_keyparms, "pgy",
                                    &pk.p, &pk.g, &pk.y, NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_mpidump ("elg_verify    p", pk.p);
index 9a94fe2..2838802 100644 (file)
@@ -213,7 +213,7 @@ _gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
  * parameter "E" again as an unsigned MPI into MPI_E.
  *
  * The function returns NULL on success.  On error an error code is
- * returned and and the passed MPIs have no defined value.
+ * returned and the passed MPIs are either unchanged or set to NULL.
  */
 gpg_err_code_t
 _gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
@@ -275,7 +275,10 @@ _gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
           else if (!l1)
             {
               while (idx--)
-                gcry_mpi_release (*array[idx]);
+                {
+                  gcry_mpi_release (*array[idx]);
+                  *array[idx] = NULL;
+                }
               return GPG_ERR_NO_OBJ;  /* List element not found.  */
             }
           else
@@ -288,7 +291,10 @@ _gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
               if (!*array[idx])
                 {
                   while (idx--)
-                    gcry_mpi_release (*array[idx]);
+                    {
+                      gcry_mpi_release (*array[idx]);
+                      *array[idx] = NULL;
+                    }
                   return GPG_ERR_INV_OBJ;  /* Conversion failed.  */
                 }
             }
index d7a474d..c1d8bbc 100644 (file)
@@ -183,20 +183,6 @@ disable_pubkey_algo (int algo)
 
 
 \f
-/* Free the MPIs stored in the NULL terminated ARRAY of MPIs and set
-   the slots to NULL.  */
-static void
-release_mpi_array (gcry_mpi_t *array)
-{
-  for (; *array; array++)
-    {
-      mpi_free(*array);
-      *array = NULL;
-    }
-}
-
-
-\f
 /*
  * Map a string to the pubkey algo
  */
@@ -303,396 +289,7 @@ pubkey_get_nenc (int algo)
 }
 
 
-static gcry_err_code_t
-pubkey_check_secret_key (int algo, gcry_mpi_t *skey)
-{
-  gcry_err_code_t rc;
-  gcry_pk_spec_t *spec = spec_from_algo (algo);
-
-  if (spec && spec->check_secret_key)
-    rc = spec->check_secret_key (algo, skey);
-  else if (spec)
-    rc = GPG_ERR_NOT_IMPLEMENTED;
-  else
-    rc = GPG_ERR_PUBKEY_ALGO;
-
-  return rc;
-}
-
-
-/* Internal function.   */
-static gcry_err_code_t
-sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
-                      gcry_mpi_t *elements, const char *algo_name, int opaque)
-{
-  gcry_err_code_t err = 0;
-  int i, idx;
-  const char *name;
-  gcry_sexp_t list;
-
-  for (name = element_names, idx = 0; *name && !err; name++, idx++)
-    {
-      list = gcry_sexp_find_token (key_sexp, name, 1);
-      if (!list)
-       elements[idx] = NULL;
-      else if (opaque)
-        {
-         elements[idx] = _gcry_sexp_nth_opaque_mpi (list, 1);
-         gcry_sexp_release (list);
-         if (!elements[idx])
-           err = GPG_ERR_INV_OBJ;
-        }
-      else
-       {
-         elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
-         gcry_sexp_release (list);
-         if (!elements[idx])
-           err = GPG_ERR_INV_OBJ;
-       }
-    }
-
-  if (!err)
-    {
-      /* Check that all elements are available.  */
-      for (name = element_names, i = 0; *name; name++, i++)
-        if (!elements[i])
-          break;
-      if (*name)
-        {
-          err = GPG_ERR_NO_OBJ;
-          /* Some are missing.  Before bailing out we test for
-             optional parameters.  */
-          if (algo_name && !strcmp (algo_name, "RSA")
-              && !strcmp (element_names, "nedpqu") )
-            {
-              /* This is RSA.  Test whether we got N, E and D and that
-                 the optional P, Q and U are all missing.  */
-              if (elements[0] && elements[1] && elements[2]
-                  && !elements[3] && !elements[4] && !elements[5])
-                err = 0;
-            }
-        }
-    }
-
-
-  if (err)
-    {
-      for (i = 0; i < idx; i++)
-        if (elements[i])
-          mpi_free (elements[i]);
-    }
-  return err;
-}
-
-
-/* Internal function used for ecc.  Note, that this function makes use
-   of its intimate knowledge about the ECC parameters from ecc.c. */
-static gcry_err_code_t
-sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
-                           gcry_mpi_t *elements, gcry_pk_spec_t *spec,
-                           int want_private)
-
-{
-  gcry_err_code_t err = 0;
-  int idx;
-  const char *name;
-  gcry_sexp_t list;
-
-  /* Clear the array for easier error cleanup. */
-  for (name = element_names, idx = 0; *name; name++, idx++)
-    elements[idx] = NULL;
-  gcry_assert (idx >= 5); /* We know that ECC has at least 5 elements
-                             (params only) or 6 (full public key).  */
-  if (idx == 5)
-    elements[5] = NULL;   /* Extra clear for the params only case.  */
-
-
-  /* Init the array with the available curve parameters. */
-  for (name = element_names, idx = 0; *name && !err; name++, idx++)
-    {
-      list = gcry_sexp_find_token (key_sexp, name, 1);
-      if (!list)
-       elements[idx] = NULL;
-      else
-       {
-          switch (idx)
-            {
-            case 5: /* The public and */
-            case 6: /* the secret key must to be passed opaque.  */
-              elements[idx] = _gcry_sexp_nth_opaque_mpi (list, 1);
-              break;
-            default:
-              elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_STD);
-              break;
-            }
-         gcry_sexp_release (list);
-         if (!elements[idx])
-            {
-              err = GPG_ERR_INV_OBJ;
-              goto leave;
-            }
-       }
-    }
-
-  /* Check whether a curve parameter has been given and then fill any
-     missing elements.  */
-  list = gcry_sexp_find_token (key_sexp, "curve", 5);
-  if (list)
-    {
-      if (spec->get_param)
-        {
-          char *curve;
-          gcry_mpi_t params[6];
-
-          for (idx = 0; idx < DIM(params); idx++)
-            params[idx] = NULL;
-
-          curve = _gcry_sexp_nth_string (list, 1);
-          gcry_sexp_release (list);
-          if (!curve)
-            {
-              /* No curve name given (or out of core). */
-              err = GPG_ERR_INV_OBJ;
-              goto leave;
-            }
-          err = spec->get_param (curve, params);
-          gcry_free (curve);
-          if (err)
-            goto leave;
-
-          for (idx = 0; idx < DIM(params); idx++)
-            {
-              if (!elements[idx])
-                elements[idx] = params[idx];
-              else
-                mpi_free (params[idx]);
-            }
-        }
-      else
-        {
-          gcry_sexp_release (list);
-          err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
-          goto leave;
-        }
-    }
-
-  /* Check that all parameters are known.  */
-  for (name = element_names, idx = 0; *name; name++, idx++)
-    if (!elements[idx])
-      {
-        if (want_private && *name == 'q')
-          ; /* Q is optional.  */
-        else
-          {
-            err = GPG_ERR_NO_OBJ;
-            goto leave;
-          }
-      }
-
- leave:
-  if (err)
-    {
-      for (name = element_names, idx = 0; *name; name++, idx++)
-        if (elements[idx])
-          mpi_free (elements[idx]);
-    }
-  return err;
-}
-
-
-
-/****************
- * Convert a S-Exp with either a private or a public key to our
- * internal format. Currently we do only support the following
- * algorithms:
- *    dsa
- *    rsa
- *    openpgp-dsa
- *    openpgp-rsa
- *    openpgp-elg
- *    openpgp-elg-sig
- *    ecdsa
- *    ecdh
- * Provide a SE with the first element be either "private-key" or
- * or "public-key". It is followed by a list with its first element
- * be one of the above algorithm identifiers and the remaning
- * elements are pairs with parameter-id and value.
- * NOTE: we look through the list to find a list beginning with
- * "private-key" or "public-key" - the first one found is used.
- *
- * If OVERRIDE_ELEMS is not NULL those elems override the parameter
- * specification taken from the module.  This ise used by
- * gcry_pk_get_curve.
- *
- * Returns: A pointer to an allocated array of MPIs if the return value is
- *         zero; the caller has to release this array.
- *
- * Example of a DSA public key:
- *  (private-key
- *    (dsa
- *     (p <mpi>)
- *     (g <mpi>)
- *     (y <mpi>)
- *     (x <mpi>)
- *    )
- *  )
- * The <mpi> are expected to be in GCRYMPI_FMT_USG
- */
-static gcry_err_code_t
-sexp_to_key (gcry_sexp_t sexp, int want_private, int use,
-             const char *override_elems,
-             gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, int *r_is_ecc)
-{
-  gcry_err_code_t err = 0;
-  gcry_sexp_t list, l2;
-  char *name;
-  const char *elems;
-  gcry_mpi_t *array;
-  gcry_pk_spec_t *spec;
-  int is_ecc;
-
-  /* Check that the first element is valid.  If we are looking for a
-     public key but a private key was supplied, we allow the use of
-     the private key anyway.  The rationale for this is that the
-     private key is a superset of the public key. */
-  list = gcry_sexp_find_token (sexp,
-                               want_private? "private-key":"public-key", 0);
-  if (!list && !want_private)
-    list = gcry_sexp_find_token (sexp, "private-key", 0);
-  if (!list)
-    return GPG_ERR_INV_OBJ; /* Does not contain a key object.  */
-
-  l2 = gcry_sexp_cadr( list );
-  gcry_sexp_release ( list );
-  list = l2;
-  name = _gcry_sexp_nth_string (list, 0);
-  if (!name)
-    {
-      gcry_sexp_release ( list );
-      return GPG_ERR_INV_OBJ;      /* Invalid structure of object. */
-    }
-
-  /* Fixme: We should make sure that an ECC key is always named "ecc"
-     and not "ecdsa".  "ecdsa" should be used for the signature
-     itself.  We need a function to test whether an algorithm given
-     with a key is compatible with an application of the key (signing,
-     encryption).  For RSA this is easy, but ECC is the first
-     algorithm which has many flavours.
-
-     We use an ugly hack here to decide whether to use ecdsa or ecdh.
-  */
-  if (!strcmp (name, "ecc"))
-    is_ecc = 2;
-  else if (!strcmp (name, "ecdsa") || !strcmp (name, "ecdh"))
-    is_ecc = 1;
-  else
-    is_ecc = 0;
-
-  if (is_ecc == 2 && (use & GCRY_PK_USAGE_SIGN))
-    spec = spec_from_name ("ecdsa");
-  else if (is_ecc == 2 && (use & GCRY_PK_USAGE_ENCR))
-    spec = spec_from_name ("ecdh");
-  else
-    spec = spec_from_name (name);
-
-  gcry_free (name);
-
-  if (!spec)
-    {
-      gcry_sexp_release (list);
-      return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
-    }
-
-  if (override_elems)
-    elems = override_elems;
-  else if (want_private)
-    elems = spec->elements_skey;
-  else
-    elems = spec->elements_pkey;
-  array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
-  if (!array)
-    err = gpg_err_code_from_syserror ();
-  if (!err)
-    {
-      if (is_ecc)
-        err = sexp_elements_extract_ecc (list, elems, array, spec,
-                                         want_private);
-      else
-        err = sexp_elements_extract (list, elems, array, spec->name, 0);
-    }
-
-  gcry_sexp_release (list);
-
-  if (err)
-    {
-      gcry_free (array);
-    }
-  else
-    {
-      *retarray = array;
-      *r_spec = spec;
-      if (r_is_ecc)
-        *r_is_ecc = is_ecc;
-    }
-
-  return err;
-}
-
-
-
-/* FIXME: This is a duplicate.  */
-static inline int
-get_hash_algo (const char *s, size_t n)
-{
-  static const struct { const char *name; int algo; } hashnames[] = {
-    { "sha1",   GCRY_MD_SHA1 },
-    { "md5",    GCRY_MD_MD5 },
-    { "sha256", GCRY_MD_SHA256 },
-    { "ripemd160", GCRY_MD_RMD160 },
-    { "rmd160", GCRY_MD_RMD160 },
-    { "sha384", GCRY_MD_SHA384 },
-    { "sha512", GCRY_MD_SHA512 },
-    { "sha224", GCRY_MD_SHA224 },
-    { "md2",    GCRY_MD_MD2 },
-    { "md4",    GCRY_MD_MD4 },
-    { "tiger",  GCRY_MD_TIGER },
-    { "haval",  GCRY_MD_HAVAL },
-    { NULL, 0 }
-  };
-  int algo;
-  int i;
-
-  for (i=0; hashnames[i].name; i++)
-    {
-      if ( strlen (hashnames[i].name) == n
-          && !memcmp (hashnames[i].name, s, n))
-       break;
-    }
-  if (hashnames[i].name)
-    algo = hashnames[i].algo;
-  else
-    {
-      /* In case of not listed or dynamically allocated hash
-        algorithm we fall back to this somewhat slower
-        method.  Further, it also allows to use OIDs as
-        algorithm names. */
-      char *tmpname;
-
-      tmpname = gcry_malloc (n+1);
-      if (!tmpname)
-       algo = 0;  /* Out of core - silently give up.  */
-      else
-       {
-         memcpy (tmpname, s, n);
-         tmpname[n] = 0;
-         algo = gcry_md_map_name (tmpname);
-         gcry_free (tmpname);
-       }
-    }
-  return algo;
-}
-
-
+\f
 /*
    Do a PK encrypt operation
 
@@ -881,22 +478,25 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
 
    Returns: 0 or an errorcode.
 
-   s_key = <key-as-defined-in-sexp_to_key> */
+   NOTE: We currently support only secret key checking. */
 gcry_error_t
 gcry_pk_testkey (gcry_sexp_t s_key)
 {
-  gcry_pk_spec_t *spec = NULL;
-  gcry_mpi_t *key = NULL;
   gcry_err_code_t rc;
+  gcry_pk_spec_t *spec;
+  gcry_sexp_t keyparms;
 
-  /* Note we currently support only secret key checking. */
-  rc = sexp_to_key (s_key, 1, 0, NULL, &key, &spec, NULL);
-  if (!rc)
-    {
-      rc = pubkey_check_secret_key (spec->algo, key);
-      release_mpi_array (key);
-      gcry_free (key);
-    }
+  rc = spec_from_sexp (s_key, 1, &spec, &keyparms);
+  if (rc)
+    goto leave;
+
+  if (spec->check_secret_key)
+    rc = spec->check_secret_key (keyparms);
+  else
+    rc = GPG_ERR_NOT_IMPLEMENTED;
+
+ leave:
+  gcry_sexp_release (keyparms);
   return gcry_error (rc);
 }
 
@@ -1124,13 +724,9 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
 const char *
 gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
 {
-  gcry_mpi_t *pkey = NULL;
-  gcry_sexp_t list = NULL;
-  gcry_sexp_t l2;
-  char *name = NULL;
   const char *result = NULL;
-  int want_private = 1;
-  gcry_pk_spec_t *spec = NULL;
+  gcry_pk_spec_t *spec;
+  gcry_sexp_t keyparms = NULL;
 
   if (r_nbits)
     *r_nbits = 0;
@@ -1139,50 +735,20 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
     {
       iterator = 0;
 
-      /* Check that the first element is valid. */
-      list = gcry_sexp_find_token (key, "public-key", 0);
-      if (list)
-        want_private = 0;
-      if (!list)
-        list = gcry_sexp_find_token (key, "private-key", 0);
-      if (!list)
-        return NULL; /* No public- or private-key object. */
-
-      l2 = gcry_sexp_cadr (list);
-      gcry_sexp_release (list);
-      list = l2;
-      l2 = NULL;
-
-      name = _gcry_sexp_nth_string (list, 0);
-      if (!name)
-        goto leave; /* Invalid structure of object. */
-
-      /* Get the key.  We pass the names of the parameters for
-         override_elems; this allows to call this function without the
-         actual public key parameter.  */
-      if (sexp_to_key (key, want_private, 0, "pabgn", &pkey, &spec, NULL))
-        goto leave;
+      if (spec_from_sexp (key, 0, &spec, &keyparms))
+        return NULL;
     }
   else
     {
       spec = spec_from_name ("ecc");
       if (!spec)
-        goto leave;
+        return NULL;
     }
 
-  if (!spec || !spec->get_curve)
-    goto leave;
-
-  result = spec->get_curve (pkey, iterator, r_nbits);
+  if (spec->get_curve)
+    result = spec->get_curve (keyparms, iterator, r_nbits);
 
- leave:
-  if (pkey)
-    {
-      release_mpi_array (pkey);
-      gcry_free (pkey);
-    }
-  gcry_free (name);
-  gcry_sexp_release (list);
+   gcry_sexp_release (keyparms);
   return result;
 }
 
index 428185b..fc6bbe5 100644 (file)
@@ -836,27 +836,31 @@ rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 
 
 static gcry_err_code_t
-rsa_check_secret_key (int algo, gcry_mpi_t *skey)
+rsa_check_secret_key (gcry_sexp_t keyparms)
 {
-  gcry_err_code_t err = GPG_ERR_NO_ERROR;
-  RSA_secret_key sk;
-
-  (void)algo;
+  gcry_err_code_t rc;
+  RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
 
-  sk.n = skey[0];
-  sk.e = skey[1];
-  sk.d = skey[2];
-  sk.p = skey[3];
-  sk.q = skey[4];
-  sk.u = skey[5];
+  /* To check the key we need the optional parameters. */
+  rc = _gcry_pk_util_extract_mpis (keyparms, "nedpqu",
+                                   &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
+                                   NULL);
+  if (rc)
+    goto leave;
 
-  if (!sk.p || !sk.q || !sk.u)
-    err = GPG_ERR_NO_OBJ;  /* To check the key we need the optional
-                              parameters. */
-  else if (!check_secret_key (&sk))
-    err = GPG_ERR_BAD_SECKEY;
+  if (!check_secret_key (&sk))
+    rc = GPG_ERR_BAD_SECKEY;
 
-  return err;
+ leave:
+  gcry_mpi_release (sk.n);
+  gcry_mpi_release (sk.e);
+  gcry_mpi_release (sk.d);
+  gcry_mpi_release (sk.p);
+  gcry_mpi_release (sk.q);
+  gcry_mpi_release (sk.u);
+  if (DBG_CIPHER)
+    log_debug ("rsa_testkey    => %s\n", gpg_strerror (rc));
+  return rc;
 }
 
 
@@ -887,7 +891,7 @@ rsa_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   /* Extract the key.  */
   rc = _gcry_pk_util_extract_mpis (keyparms, "ne", &pk.n, &pk.e, NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_mpidump ("rsa_encrypt    n", pk.n);
@@ -968,7 +972,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
                                    &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
                                    NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_printmpi ("rsa_decrypt    n", sk.n);
@@ -1112,7 +1116,7 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
                                    &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
                                    NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_printmpi ("rsa_sign      n", sk.n);
@@ -1205,7 +1209,7 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   /* Extract the key.  */
   rc = _gcry_pk_util_extract_mpis (keyparms, "ne", &pk.n, &pk.e, NULL);
   if (rc)
-    return rc;
+    goto leave;
   if (DBG_CIPHER)
     {
       log_printmpi ("rsa_verify    n", pk.n);
index 0dc83bd..c7ce906 100644 (file)
@@ -54,8 +54,7 @@ typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms,
                                                gcry_sexp_t *r_skey);
 
 /* Type for the pk_check_secret_key function.  */
-typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo,
-                                                      gcry_mpi_t *skey);
+typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (gcry_sexp_t keyparms);
 
 /* Type for the pk_encrypt function.  */
 typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph,
@@ -90,7 +89,7 @@ typedef gcry_err_code_t (*pk_get_param_t) (const char *name,
                                            gcry_mpi_t *pkey);
 
 /* The type used to query an ECC curve name.  */
-typedef const char *(*pk_get_curve_t)(gcry_mpi_t *pkey, int iterator,
+typedef const char *(*pk_get_curve_t)(gcry_sexp_t keyparms, int iterator,
                                       unsigned int *r_nbits);
 
 /* The type used to query ECC curve parameters by name.  */