[PATCH] scd: Generation of ECC keys on-board (OpenPGP card 3)

Arnaud Fontaine arnaud.fontaine at ssi.gouv.fr
Fri Oct 14 13:46:35 CEST 2016


* scd/app-openpgp.c: Support for on-board generation of ECC keys
introduced in OpenPGP card specification 3.0.
---
 scd/app-openpgp.c | 116
+++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 88 insertions(+), 28 deletions(-)

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 563a045..775640e 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -3568,9 +3568,17 @@ do_genkey (app_t app, ctrl_t ctrl,  const char
*keynostr, unsigned int flags,
      to put a limit on the max. allowed keysize.  2048 bit will
      already lead to a 527 byte long status line and thus a 4096 bit
      key would exceed the Assuan line length limit.  */
-  keybits = app->app_local->keyattr[keyno].rsa.n_bits;
-  if (keybits > 4096)
-    return gpg_error (GPG_ERR_TOO_LARGE);
+  if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
+    {
+      keybits = app->app_local->keyattr[keyno].rsa.n_bits;
+      if (keybits > 4096)
+        return gpg_error (GPG_ERR_TOO_LARGE);
+    }
+  else
+    {
+      keybits = 600; /* arbitrary value, but large enough for curves
+                        supported in 3.0 */
+    }
    /* Prepare for key generation by verifying the Admin PIN.  */
   rc = verify_chv3 (app, pincb, pincb_arg);
@@ -3625,38 +3633,90 @@ do_genkey (app_t app, ctrl_t ctrl,  const char
*keynostr, unsigned int flags,
       goto leave;
     }
 -  m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
-  if (!m)
+  created_at = createtime? createtime : gnupg_get_time ();
+  sprintf (numbuf, "%lu", (unsigned long)created_at);
+  send_status_info (ctrl, "KEY-CREATED-AT",
+                    numbuf, (size_t)strlen(numbuf), NULL, 0);
+
+  if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
     {
-      rc = gpg_error (GPG_ERR_CARD);
-      log_error (_("response does not contain the RSA modulus\n"));
-      goto leave;
+      m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
+      if (!m)
+        {
+          rc = gpg_error (GPG_ERR_CARD);
+          log_error (_("response does not contain the RSA modulus\n"));
+          goto leave;
+        }
+      /* log_printhex ("RSA n:", m, mlen); */
+      send_key_data (ctrl, "n", m, mlen);
+
+      e = find_tlv (keydata, keydatalen, 0x0082, &elen);
+      if (!e)
+        {
+          rc = gpg_error (GPG_ERR_CARD);
+          log_error (_("response does not contain the RSA public
exponent\n"));
+          goto leave;
+        }
+       /* log_printhex ("RSA e:", e, elen); */
+       send_key_data (ctrl, "e", e, elen);
+
+       for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
+        ;
+       for (; elen && !*e; elen--, e++) /* strip leading zeroes */
+        ;
+
+      rc = store_fpr (app, keyno, (u32)created_at, fprbuf, PUBKEY_ALGO_RSA,
+                      m, mlen, e, elen);
     }
-  /* log_printhex ("RSA n:", m, mlen); */
-  send_key_data (ctrl, "n", m, mlen);
 -  e = find_tlv (keydata, keydatalen, 0x0082, &elen);
-  if (!e)
+  if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
     {
-      rc = gpg_error (GPG_ERR_CARD);
-      log_error (_("response does not contain the RSA public exponent\n"));
-      goto leave;
-    }
-  /* log_printhex ("RSA e:", e, elen); */
-  send_key_data (ctrl, "e", e, elen);
+      gcry_mpi_t oid;
+      int n;
 -  created_at = createtime? createtime : gnupg_get_time ();
-  sprintf (numbuf, "%lu", (unsigned long)created_at);
-  send_status_info (ctrl, "KEY-CREATED-AT",
-                    numbuf, (size_t)strlen(numbuf), NULL, 0);
+      m = find_tlv (keydata, keydatalen, 0x0086, &mlen);
+      if (!m)
+        {
+          rc = gpg_error (GPG_ERR_CARD);
+          log_error (_("response does not contain the EC public key\n"));
+          goto leave;
+        }
 -  for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
-    ;
-  for (; elen && !*e; elen--, e++) /* strip leading zeroes */
-    ;
+      rc = openpgp_oid_from_str
(app->app_local->keyattr[keyno].ecc.oid, &oid);
+      if (rc)
+        goto leave;
+
+      e = gcry_mpi_get_opaque (oid, &n);
+      elen = (n+7)/8;
+
+      send_key_data (ctrl, "q", m, mlen);
+
+      for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
+        ;
+
+      send_key_data(ctrl, "c", e, elen);
+
+      if (keyno == 1)
+        {
+          send_key_data(ctrl, "f", "\x03\x01\x08\x07", (size_t)4);
+
+          rc = store_fpr (app, keyno, (u32)created_at, fprbuf,
+                          PUBKEY_ALGO_ECDH,
+                          e, elen,
+                          m, mlen,
+                          "\x03\x01\x08\x07", (size_t)4); /* KDF for
ECDH : 03 01 hash_alg sym_alg */
+                                                          /* hash_alg :
8 = SHA256, 9 = SHA384, 10 = SHA512 */
+                                                          /* sym_alg :
7 = AES, 8 = AES192, 9 = AES256 */
+        }
+      else
+        {
+          rc = store_fpr (app, keyno, (u32)created_at, fprbuf,
+                          PUBKEY_ALGO_ECDSA,
+                          e, elen,
+                          m, mlen);
+        }
+    }
 -  rc = store_fpr (app, keyno, (u32)created_at, fprbuf, PUBKEY_ALGO_RSA,
-                  m, mlen, e, elen);
   if (rc)
     goto leave;
   send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);
-- 
2.9.3




More information about the Gnupg-devel mailing list