speedo: Improve speedo Makefile.
[gnupg.git] / g10 / pkglue.c
index 836c2c3..684ce8a 100644 (file)
@@ -1,5 +1,6 @@
 /* pkglue.c - public key operations glue code
- *     Copyright (C) 2000, 2003, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2000, 2003, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2014 Werner Koch
  *
  * This file is part of GnuPG.
  *
 /* FIXME: Better chnage the fucntion name because mpi_ is used by
    gcrypt macros.  */
 gcry_mpi_t
-mpi_from_sexp (gcry_sexp_t sexp, const char * item)
+get_mpi_from_sexp (gcry_sexp_t sexp, const char *item, int mpifmt)
 {
   gcry_sexp_t list;
   gcry_mpi_t data;
 
   list = gcry_sexp_find_token (sexp, item, 0);
   assert (list);
-  data = gcry_sexp_nth_mpi (list, 1, 0);
+  data = gcry_sexp_nth_mpi (list, 1, mpifmt);
   assert (data);
   gcry_sexp_release (list);
   return data;
@@ -53,31 +54,31 @@ mpi_from_sexp (gcry_sexp_t sexp, const char * item)
  * change the internal design to directly fit to libgcrypt.
  */
 int
-pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
+pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
+           gcry_mpi_t *data, gcry_mpi_t *pkey)
 {
   gcry_sexp_t s_sig, s_hash, s_pkey;
   int rc;
-  const int pkalgo = map_pk_openpgp_to_gcry (algo);
 
   /* Make a sexp from pkey.  */
-  if (pkalgo == GCRY_PK_DSA)
+  if (pkalgo == PUBKEY_ALGO_DSA)
     {
       rc = gcry_sexp_build (&s_pkey, NULL,
                            "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
                            pkey[0], pkey[1], pkey[2], pkey[3]);
     }
-  else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
+  else if (pkalgo == PUBKEY_ALGO_ELGAMAL_E || pkalgo == PUBKEY_ALGO_ELGAMAL)
     {
       rc = gcry_sexp_build (&s_pkey, NULL,
                            "(public-key(elg(p%m)(g%m)(y%m)))",
                            pkey[0], pkey[1], pkey[2]);
     }
-  else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S)
+  else if (pkalgo == PUBKEY_ALGO_RSA || pkalgo == PUBKEY_ALGO_RSA_S)
     {
       rc = gcry_sexp_build (&s_pkey, NULL,
                            "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
     }
-  else if (pkalgo == GCRY_PK_ECDSA) /* Same as GCRY_PK_ECDH */
+  else if (pkalgo == PUBKEY_ALGO_ECDSA)
     {
       char *curve = openpgp_oid_to_str (pkey[0]);
       if (!curve)
@@ -90,6 +91,20 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
           xfree (curve);
         }
     }
+  else if (pkalgo == PUBKEY_ALGO_EDDSA)
+    {
+      char *curve = openpgp_oid_to_str (pkey[0]);
+      if (!curve)
+        rc = gpg_error_from_syserror ();
+      else
+        {
+          rc = gcry_sexp_build (&s_pkey, NULL,
+                                "(public-key(ecc(curve %s)"
+                                "(flags eddsa)(q%m)))",
+                                curve, pkey[1]);
+          xfree (curve);
+        }
+    }
   else
     return GPG_ERR_PUBKEY_ALGO;
 
@@ -97,12 +112,22 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
     BUG ();  /* gcry_sexp_build should never fail.  */
 
   /* Put hash into a S-Exp s_hash. */
-  if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
-    BUG (); /* gcry_sexp_build should never fail.  */
+  if (pkalgo == PUBKEY_ALGO_EDDSA)
+    {
+      if (gcry_sexp_build (&s_hash, NULL,
+                           "(data(flags eddsa)(hash-algo sha512)(value %m))",
+                           hash))
+        BUG (); /* gcry_sexp_build should never fail.  */
+    }
+  else
+    {
+      if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
+        BUG (); /* gcry_sexp_build should never fail.  */
+    }
 
   /* Put data into a S-Exp s_sig. */
   s_sig = NULL;
-  if (pkalgo == GCRY_PK_DSA)
+  if (pkalgo == PUBKEY_ALGO_DSA)
     {
       if (!data[0] || !data[1])
         rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -110,7 +135,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
         rc = gcry_sexp_build (&s_sig, NULL,
                               "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]);
     }
-  else if (pkalgo == GCRY_PK_ECDSA)
+  else if (pkalgo == PUBKEY_ALGO_ECDSA)
     {
       if (!data[0] || !data[1])
         rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -118,7 +143,15 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
         rc = gcry_sexp_build (&s_sig, NULL,
                               "(sig-val(ecdsa(r%m)(s%m)))", data[0], data[1]);
     }
-  else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
+  else if (pkalgo == PUBKEY_ALGO_EDDSA)
+    {
+      if (!data[0] || !data[1])
+        rc = gpg_error (GPG_ERR_BAD_MPI);
+      else
+        rc = gcry_sexp_build (&s_sig, NULL,
+                              "(sig-val(eddsa(r%M)(s%M)))", data[0], data[1]);
+    }
+  else if (pkalgo == PUBKEY_ALGO_ELGAMAL || pkalgo == PUBKEY_ALGO_ELGAMAL_E)
     {
       if (!data[0] || !data[1])
         rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -126,7 +159,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
         rc = gcry_sexp_build (&s_sig, NULL,
                               "(sig-val(elg(r%m)(s%m)))", data[0], data[1]);
     }
-  else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S)
+  else if (pkalgo == PUBKEY_ALGO_RSA || pkalgo == PUBKEY_ALGO_RSA_S)
     {
       if (!data[0])
         rc = gpg_error (GPG_ERR_BAD_MPI);
@@ -154,65 +187,66 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey)
  * PK is only required to compute the fingerprint for ECDH.
  */
 int
-pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
+pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data,
             PKT_public_key *pk, gcry_mpi_t *pkey)
 {
-  gcry_sexp_t s_ciph, s_data, s_pkey;
+  gcry_sexp_t s_ciph = NULL;
+  gcry_sexp_t s_data = NULL;
+  gcry_sexp_t s_pkey = NULL;
   int rc;
 
   /* Make a sexp from pkey.  */
-  if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
+  if (algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E)
     {
       rc = gcry_sexp_build (&s_pkey, NULL,
                            "(public-key(elg(p%m)(g%m)(y%m)))",
                            pkey[0], pkey[1], pkey[2]);
       /* Put DATA into a simplified S-expression.  */
-      if (rc || gcry_sexp_build (&s_data, NULL, "%m", data))
-        BUG ();
-
+      if (!rc)
+        rc = gcry_sexp_build (&s_data, NULL, "%m", data);
     }
-  else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_E)
+  else if (algo == PUBKEY_ALGO_RSA || algo == PUBKEY_ALGO_RSA_E)
     {
       rc = gcry_sexp_build (&s_pkey, NULL,
                            "(public-key(rsa(n%m)(e%m)))",
                            pkey[0], pkey[1]);
       /* Put DATA into a simplified S-expression.  */
-      if (rc || gcry_sexp_build (&s_data, NULL, "%m", data))
-        BUG ();
+      if (!rc)
+        rc = gcry_sexp_build (&s_data, NULL, "%m", data);
     }
   else if (algo == PUBKEY_ALGO_ECDH)
     {
       gcry_mpi_t k;
-      char *curve;
-      byte fp[MAX_FINGERPRINT_LEN];
-      size_t fpn;
 
       rc = pk_ecdh_generate_ephemeral_key (pkey, &k);
-      if (rc)
-        return rc;
-
-      curve = openpgp_oid_to_str (pkey[0]);
-      if (!curve)
-        rc = gpg_error_from_syserror ();
-      else
+      if (!rc)
         {
-          /* Now use the ephemeral secret to compute the shared point.  */
-          rc = gcry_sexp_build (&s_pkey, NULL,
-                                "(public-key(ecdh(curve%s)(q%m)))",
-                                curve, pkey[1]);
-          xfree (curve);
-          /* FIXME: Take care of RC.  */
-          /* Put K into a simplified S-expression.  */
-          if (rc || gcry_sexp_build (&s_data, NULL, "%m", k))
-            BUG ();
+          char *curve;
+
+          curve = openpgp_oid_to_str (pkey[0]);
+          if (!curve)
+            rc = gpg_error_from_syserror ();
+          else
+            {
+              /* Now use the ephemeral secret to compute the shared point.  */
+              rc = gcry_sexp_build (&s_pkey, NULL,
+                                    "(public-key(ecdh(curve%s)(q%m)))",
+                                    curve, pkey[1]);
+              xfree (curve);
+              /* Put K into a simplified S-expression.  */
+              if (!rc)
+                rc = gcry_sexp_build (&s_data, NULL, "%m", k);
+            }
+          gcry_mpi_release (k);
         }
     }
   else
-    return gpg_error (GPG_ERR_PUBKEY_ALGO);
-
+    rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
 
   /* Pass it to libgcrypt. */
-  rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
+  if (!rc)
+    rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
+
   gcry_sexp_release (s_data);
   gcry_sexp_release (s_pkey);
 
@@ -225,8 +259,8 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
       size_t fpn;
 
       /* Get the shared point and the ephemeral public key.  */
-      shared = mpi_from_sexp (s_ciph, "s");
-      public = mpi_from_sexp (s_ciph, "e");
+      shared = get_mpi_from_sexp (s_ciph, "s", GCRYMPI_FMT_USG);
+      public = get_mpi_from_sexp (s_ciph, "e", GCRYMPI_FMT_USG);
       gcry_sexp_release (s_ciph);
       s_ciph = NULL;
       if (DBG_CIPHER)
@@ -258,9 +292,9 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
   else /* Elgamal or RSA case.  */
     { /* Fixme: Add better error handling or make gnupg use
          S-expressions directly.  */
-      resarr[0] = mpi_from_sexp (s_ciph, "a");
-      if (algo != GCRY_PK_RSA && algo != GCRY_PK_RSA_E)
-        resarr[1] = mpi_from_sexp (s_ciph, "b");
+      resarr[0] = get_mpi_from_sexp (s_ciph, "a", GCRYMPI_FMT_USG);
+      if (!is_RSA (algo))
+        resarr[1] = get_mpi_from_sexp (s_ciph, "b", GCRYMPI_FMT_USG);
     }
 
   gcry_sexp_release (s_ciph);
@@ -270,33 +304,44 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
 
 /* Check whether SKEY is a suitable secret key. */
 int
-pk_check_secret_key (int algo, gcry_mpi_t *skey)
+pk_check_secret_key (pubkey_algo_t pkalgo, gcry_mpi_t *skey)
 {
   gcry_sexp_t s_skey;
   int rc;
-  const int gcry_pkalgo = map_pk_openpgp_to_gcry( algo );
 
-  if (gcry_pkalgo == GCRY_PK_DSA)
+  if (pkalgo == PUBKEY_ALGO_DSA)
     {
       rc = gcry_sexp_build (&s_skey, NULL,
                            "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
                            skey[0], skey[1], skey[2], skey[3], skey[4]);
     }
-  else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E)
+  else if (pkalgo == PUBKEY_ALGO_ELGAMAL || pkalgo == PUBKEY_ALGO_ELGAMAL_E)
     {
       rc = gcry_sexp_build (&s_skey, NULL,
                            "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
                            skey[0], skey[1], skey[2], skey[3]);
     }
-  else if (gcry_pkalgo == GCRY_PK_RSA
-           || gcry_pkalgo == GCRY_PK_RSA_S || gcry_pkalgo == GCRY_PK_RSA_E)
+  else if (is_RSA (pkalgo))
     {
       rc = gcry_sexp_build (&s_skey, NULL,
                            "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
                            skey[0], skey[1], skey[2], skey[3], skey[4],
                            skey[5]);
     }
-  else if (gcry_pkalgo == GCRY_PK_ECDSA || gcry_pkalgo == GCRY_PK_ECDH)
+  else if (pkalgo == PUBKEY_ALGO_ECDSA || pkalgo == PUBKEY_ALGO_ECDH)
+    {
+      char *curve = openpgp_oid_to_str (skey[0]);
+      if (!curve)
+        rc = gpg_error_from_syserror ();
+      else
+        {
+          rc = gcry_sexp_build (&s_skey, NULL,
+                                "(private-key(ecc(curve%s)(q%m)(d%m)))",
+                                curve, skey[1], skey[2]);
+          xfree (curve);
+        }
+    }
+  else if (pkalgo == PUBKEY_ALGO_EDDSA)
     {
       char *curve = openpgp_oid_to_str (skey[0]);
       if (!curve)
@@ -304,7 +349,8 @@ pk_check_secret_key (int algo, gcry_mpi_t *skey)
       else
         {
           rc = gcry_sexp_build (&s_skey, NULL,
-                                "(private-key(ecdsa(curve%s)(q%m)(d%m)))",
+                                "(private-key(ecc(curve %s)"
+                                "(flags eddsa)(q%m)(d%m)))",
                                 curve, skey[1], skey[2]);
           xfree (curve);
         }