[PATCH 3/8] g10: add new match_curve_skey_pk() function

Daniel Kahn Gillmor dkg at fifthhorseman.net
Sat May 21 01:41:06 CEST 2016


* g10/export.c (match_curve_skey_pk): new function, testing whether an
  OpenPGP public key and an S-expression use the same curve.
---
 g10/export.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/g10/export.c b/g10/export.c
index 5120e33..d931507 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -390,6 +390,71 @@ exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
   return result;
 }
 
+/* return an error if the key represented by the S-expression s_key
+   and the OpenPGP key represented by pk do not use the same curve. */
+static gpg_error_t
+match_curve_skey_pk (gcry_sexp_t s_key, PKT_public_key *pk)
+{
+  gcry_sexp_t curve = NULL, flags = NULL;
+  char *curve_str = NULL, *flag;
+  const char *oidstr = NULL;
+  gcry_mpi_t curve_as_mpi = NULL;
+  gpg_error_t err;
+  int is_eddsa = 0, idx = 0;
+
+  if (!(pk->pubkey_algo==PUBKEY_ALGO_ECDH ||
+        pk->pubkey_algo==PUBKEY_ALGO_ECDSA ||
+        pk->pubkey_algo==PUBKEY_ALGO_EDDSA))
+    return gpg_error (GPG_ERR_PUBKEY_ALGO);
+
+  curve = gcry_sexp_find_token (s_key, "curve", 0);
+  if (!curve)
+    {
+      log_error ("no reported curve\n");
+      err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
+    }
+  curve_str = gcry_sexp_nth_string (curve, 1);
+  gcry_sexp_release (curve); curve = NULL;
+  if (!curve_str)
+    {
+      log_error ("no curve name\n");
+      return gpg_error (GPG_ERR_UNKNOWN_CURVE);
+    }
+  oidstr = openpgp_curve_to_oid (curve_str, NULL);
+  if (!oidstr)
+    {
+      log_error ("no OID known for curve '%s'\n", curve_str);
+      gcry_free (curve_str);
+      return gpg_error (GPG_ERR_UNKNOWN_CURVE);
+    }
+  gcry_free (curve_str);
+  err = openpgp_oid_from_str (oidstr, &curve_as_mpi);
+  if (err)
+    return err;
+  if (gcry_mpi_cmp(pk->pkey[0], curve_as_mpi))
+    {
+      log_error ("curves do not match\n");
+      err = gpg_error (GPG_ERR_INV_CURVE);
+    }
+  gcry_mpi_release (curve_as_mpi);
+  flags = gcry_sexp_find_token (s_key, "flags", 0);
+  if (flags)
+    for (idx = 1; idx < gcry_sexp_length (flags); idx++)
+      {
+        flag = gcry_sexp_nth_string (flags, idx);
+        if (flag && (strcmp ("eddsa", flag) == 0))
+          is_eddsa = 1;
+        gcry_free (flag);
+      }
+  if (is_eddsa !=
+      (pk->pubkey_algo==PUBKEY_ALGO_EDDSA))
+    {
+      log_error ("disagreement about EdDSA\n");
+      err = gpg_error (GPG_ERR_INV_CURVE);
+    }
+
+  return err;
+}
 
 /* Return a canonicalized public key algoithms.  This is used to
    compare different flavors of algorithms (e.g. ELG and ELG_E are
-- 
2.8.1




More information about the Gnupg-devel mailing list