Problems with Elliptic Curve Key Importing

James Bottomley James.Bottomley at HansenPartnership.com
Sat Jul 22 14:24:03 CEST 2023


There are times when you need to import external keys into gpg so you
can attach them to your public key.  The most common case is ssh
authentication keys.  The traditional way to do this is with the pkcs12
importer and then use the addkey expert command to bind it to your
public key.  However, this seems to fail when you try to import an
Elliptic Curve key.  The reason seems to be that gnupg doesn't have a
single type for EC keys, it has multiple types:

PUBKEY_ALGO_ECDH, PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_EDDSA

whereas libgcrypt has a single key type: GCRY_PK_ECC

What happens is that gnupg maps GCRY_PK_ECC to PUBKEY_ALGO_ECDH, which
means an imported EC ssh key can only be used for encryption (not
authentication or signing).  There is special code in the card handling
to fix this (g10/keygen.c for the cardkey case), but it doesn't work
for the type 13 keygrip case.  There also seems to be special code in
ask_algo() for this, but it doesn't work because current is zero for
keys added by grip.  The way I solved this to import my key is
attached, but I'm not sure it's the right solution.

James

---

From: James Bottomley <James.Bottomley at HansenPartnership.com>
Subject: [PATCH] g10: allow ECC added keys for authentication and signing

Signed-off-by: James Bottomley <James.Bottomley at HansenPartnership.com>
---
 common/sexputil.c | 18 ++++++++++++++++--
 g10/keygen.c      |  9 ++++++++-
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/common/sexputil.c b/common/sexputil.c
index c7471be85..ecee217db 100644
--- a/common/sexputil.c
+++ b/common/sexputil.c
@@ -1048,12 +1048,26 @@ int
 get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen)
 {
   gcry_sexp_t sexp;
-  int algo;
+  enum gcry_pk_algos algo;
+  char *algostr;
 
   if (gcry_sexp_sscan (&sexp, NULL, keydata, keydatalen))
     return 0;
 
-  algo = get_pk_algo_from_key (sexp);
+  algostr = pubkey_algo_string (sexp, &algo);
+  if (algo == GCRY_PK_ECC)
+    {
+      if (!strcmp (algostr, "ed25519"))
+	algo = PUBKEY_ALGO_EDDSA;
+      else if (!strcmp (algostr, "ed448"))
+	algo = PUBKEY_ALGO_EDDSA;
+      else if (!strcmp (algostr, "cv25519"))
+	algo = PUBKEY_ALGO_ECDH;
+      else if (!strcmp (algostr, "cv448"))
+	algo = PUBKEY_ALGO_ECDH;
+      /* cannot determine other ECC keys without knowing usage */
+    }
+  xfree (algostr);
   gcry_sexp_release (sexp);
   return algo;
 }
diff --git a/g10/keygen.c b/g10/keygen.c
index 1605bff89..145218b62 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -2257,7 +2257,14 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
           xfree (keygrip);
           keygrip = answer;
           answer = NULL;
-          *r_usage = ask_key_flags (algo, addmode, 0);
+	  if (algo == GCRY_PK_ECC)
+	    {
+	      *r_usage = ask_key_flags (algo, addmode, ~0);
+	      if (*r_usage & (PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH))
+		algo = PUBKEY_ALGO_ECDSA;
+	    }
+	  else
+	    *r_usage = ask_key_flags (algo, addmode, 0);
           break;
 	}
       else if ((algo == 14 || !strcmp (answer, "cardkey")) && r_keygrip)
-- 
2.35.3





More information about the Gnupg-devel mailing list