scd:piv: Add feature to read Yubikey attestation certificates.
authorWerner Koch <wk@gnupg.org>
Fri, 1 Mar 2019 13:04:29 +0000 (14:04 +0100)
committerWerner Koch <wk@gnupg.org>
Fri, 1 Mar 2019 13:04:29 +0000 (14:04 +0100)
* scd/app-piv.c (do_readcert): Add hack to read Yubikey attestaions.
--

Use
  gpg-card 'readcert PIV.ATST.9A >x.crt'
to store the attestation certificate for 9A into X.CRT.

Signed-off-by: Werner Koch <wk@gnupg.org>
scd/app-piv.c

index 2cbc6e1..d55d71f 100644 (file)
@@ -182,6 +182,9 @@ static struct data_object_s data_objects[] = {
    * "97" Secondary Finger OCC
    * "98" Pairing Code
    * "9B" PIV Card Application Administration Key
+   *
+   * Yubikey specific data objects:
+   * "F9" Attestation key (preloaded can be replaced)
    */
 };
 
@@ -1044,7 +1047,6 @@ set_adm_key (app_t app, const unsigned char *value, size_t valuelen)
    return err;
 }
 
-
 /* Handle the SETATTR operation. All arguments are already basically
  * checked. */
 static gpg_error_t
@@ -1167,7 +1169,7 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
  * given tag and returns it in a freshly allocated buffer stored at
  * R_CERT and the length of the certificate stored at R_CERTLEN.  If
  * on success a non-zero value is stored at R_MECHANISM, the returned
- * data is not certificate but a public key (in the format used by the
+ * data is not certificate but a public key (in the format used by the
  * container '7f49'.  */
 static gpg_error_t
 readcert_by_tag (app_t app, unsigned int tag,
@@ -1396,6 +1398,30 @@ do_readcert (app_t app, const char *certid,
   *r_cert = NULL;
   *r_certlen = 0;
 
+  /* Hack to read a Yubikey attestation certificate.  */
+  if (app->app_local->flags.yubikey
+      && strlen (certid) == 11
+      && !ascii_strncasecmp (certid, "PIV.ATST.", 9)
+      && hexdigitp (certid+9) && hexdigitp (certid+10))
+    {
+      unsigned char apdu[4];
+      unsigned char *result;
+      size_t resultlen;
+
+      apdu[0] = 0;
+      apdu[1] = 0xf9;  /* Yubikey: Get attestation cert.  */
+      apdu[2] = xtoi_2 (certid+9);
+      apdu[3] = 0;
+      err = iso7816_apdu_direct (app->slot, apdu, 4, 1,
+                                 NULL, &result, &resultlen);
+      if (!err)
+        {
+          *r_cert = result;
+          *r_certlen = resultlen;
+        }
+      return err;
+    }
+
   dobj = find_dobj_by_keyref (app, certid);
   if (!dobj)
     return gpg_error (GPG_ERR_INV_ID);