[PATCH] agent: Support of ECC key generation by scd

Arnaud Fontaine arnaud.fontaine at ssi.gouv.fr
Fri Oct 14 14:23:39 CEST 2016


* g10/call-agent.c: Retrieving data sent by scdaemon when an ECC key
has been generated.
* g10/call-agent.h: Change in agent info structure to hold information
related to an ECC key generated by scdaemon.
* g10/keygen.c: Support of ECC key generation by scd
---
 g10/call-agent.c | 26 ++++++++++++++++++++++--
 g10/call-agent.h | 14 +++++++++++--
 g10/keygen.c     | 61
+++++++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 90 insertions(+), 11 deletions(-)

diff --git a/g10/call-agent.c b/g10/call-agent.c
index 0fb392c..988c763 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -1049,13 +1049,35 @@ scd_genkey_cb (void *opaque, const char *line)
             }
           else
             rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
+
           if (rc)
             log_error ("error parsing received key data: %s\n",
                        gpg_strerror (rc));
           else if (*name == 'n' && spacep (name+1))
-            parm->cgk->n = a;
+            {
+              parm->cgk->algo = PUBKEY_ALGO_RSA;
+              parm->cgk->rsa.n = a;
+            }
           else if (*name == 'e' && spacep (name+1))
-            parm->cgk->e = a;
+            {
+              parm->cgk->algo = PUBKEY_ALGO_RSA;
+              parm->cgk->rsa.e = a;
+            }
+          else if (*name == 'q' && spacep (name+1))
+            {
+              parm->cgk->algo = PUBKEY_ALGO_ECDSA;
+              parm->cgk->ecc.q = a;
+            }
+          else if (*name == 'c' && spacep (name+1))
+            {
+              parm->cgk->algo = PUBKEY_ALGO_ECDSA;
+              parm->cgk->ecc.curve_oid = a;
+            }
+          else if (*name == 'f' && spacep (name+1))
+            {
+              parm->cgk->algo = PUBKEY_ALGO_ECDH;
+              parm->cgk->ecc.kdf = a;
+            }
           else
             {
               log_info ("unknown parameter name in received key data\n");
diff --git a/g10/call-agent.h b/g10/call-agent.h
index d85a6fd..6440be6 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -72,8 +72,18 @@ struct agent_card_genkey_s {
   char fprvalid;
   char fpr[20];
   u32  created_at;
-  gcry_mpi_t n;
-  gcry_mpi_t e;
+  int algo;
+  union {
+    struct {
+      gcry_mpi_t n;
+      gcry_mpi_t e;
+    } rsa;
+    struct {
+      gcry_mpi_t curve_oid;
+      gcry_mpi_t kdf; /* if algo is ECDH only */
+      gcry_mpi_t q;
+    } ecc;
+  };
 };
  diff --git a/g10/keygen.c b/g10/keygen.c
index 9cf314d..0b07677 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -4901,12 +4901,29 @@ gen_card_key (int algo, int keyno, int
is_primary, kbnode_t pub_root,
    *       rc = agent_scd_genkey (&info, keyno, 1);
    *   }
   */
-  if (!err && (!info.n || !info.e))
+  if (!err && (info.algo == PUBKEY_ALGO_RSA) && (!info.rsa.n ||
!info.rsa.e))
     {
       log_error ("communication error with SCD\n");
-      gcry_mpi_release (info.n);
-      gcry_mpi_release (info.e);
-      err =  gpg_error (GPG_ERR_GENERAL);
+      gcry_mpi_release (info.rsa.n);
+      gcry_mpi_release (info.rsa.e);
+      err = gpg_error (GPG_ERR_GENERAL);
+    }
+  if (!err && (info.algo == PUBKEY_ALGO_ECDSA)
+           && (!info.ecc.curve_oid || !info.ecc.q))
+    {
+      log_error ("communication error with SCD\n");
+      gcry_mpi_release (info.ecc.curve_oid);
+      gcry_mpi_release (info.ecc.q);
+      err = gpg_error (GPG_ERR_GENERAL);
+    }
+  if (!err && (info.algo == PUBKEY_ALGO_ECDH)
+           && (!info.ecc.curve_oid || !info.ecc.kdf || !info.ecc.q))
+    {
+      log_error ("communication error with SCD\n");
+      gcry_mpi_release (info.ecc.curve_oid);
+      gcry_mpi_release (info.ecc.kdf);
+      gcry_mpi_release (info.ecc.q);
+      err = gpg_error (GPG_ERR_GENERAL);
     }
   if (err)
     {
@@ -4937,9 +4954,39 @@ gen_card_key (int algo, int keyno, int
is_primary, kbnode_t pub_root,
   pk->version = 4;
   if (expireval)
     pk->expiredate = pk->timestamp + expireval;
-  pk->pubkey_algo = algo;
-  pk->pkey[0] = info.n;
-  pk->pkey[1] = info.e;
+  pk->pubkey_algo = info.algo;
+  if (info.algo == PUBKEY_ALGO_RSA)
+    {
+      pk->pkey[0] = info.rsa.n;
+      pk->pkey[1] = info.rsa.e;
+    }
+  if (info.algo == PUBKEY_ALGO_ECDH || info.algo == PUBKEY_ALGO_ECDSA)
+    {
+      unsigned char *buf = NULL;
+      size_t buflen = 0;
+
+      err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buf, &buflen,
info.ecc.curve_oid);
+      if (err)
+        {
+          log_error("Failed to convert EC curve OID");
+          return err;
+        }
+      pk->pkey[0] = gcry_mpi_set_opaque_copy (NULL, buf, buflen * 8);
+      pk->pkey[1] = info.ecc.q;
+      xfree (buf);
+
+      if (info.algo == PUBKEY_ALGO_ECDH)
+        {
+          err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buf, &buflen,
info.ecc.kdf);
+          if (err)
+            {
+              log_error("Failed to convert ECDH KDF parameters");
+              return err;
+            }
+          pk->pkey[2] = gcry_mpi_set_opaque_copy (NULL, buf, buflen * 8);
+          xfree (buf);
+        }
+    }
    pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
   pkt->pkt.public_key = pk;
-- 
2.9.3




More information about the Gnupg-devel mailing list