gpg: Add experimental support for an issuer fpr.
authorWerner Koch <wk@gnupg.org>
Mon, 20 Jun 2016 21:58:16 +0000 (23:58 +0200)
committerWerner Koch <wk@gnupg.org>
Mon, 20 Jun 2016 21:59:18 +0000 (23:59 +0200)
* common/openpgpdefs.h (SIGSUBPKT_ISSUER_FPR): New.
* g10/build-packet.c (build_sig_subpkt_from_sig): Add arg PKSK and
insert the issuer fpr if needed.
* g10/sign.c (write_signature_packets): Pass signing key.
(make_keysig_packet): Ditto.
(update_keysig_packet): Ditto.
* g10/parse-packet.c (dump_sig_subpkt): Print issuer fpr.
(parse_one_sig_subpkt): Detect issuer fpr.
(can_handle_critical): Add issuer fpr.
* g10/mainproc.c (check_sig_and_print): Try to get key via fingerprint.
* g10/gpgv.c (keyserver_import_fprint): New stub.
* g10/test-stubs.c (keyserver_import_fprint): New stub.
--

This support is enabled with the --rfc4880bis option and intended to
test to recently proposed issuer fpr.

Signed-off-by: Werner Koch <wk@gnupg.org>
common/openpgpdefs.h
g10/build-packet.c
g10/gpgv.c
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/sign.c
g10/test-stubs.c

index f8b86e1..2c0ace2 100644 (file)
@@ -115,6 +115,7 @@ typedef enum
     SIGSUBPKT_FEATURES      = 30, /* Feature flags. */
 
     SIGSUBPKT_SIGNATURE     = 32, /* Embedded signature. */
+    SIGSUBPKT_ISSUER_FPR    = 33, /* EXPERIMENTAL: Issuer fingerprint. */
 
     SIGSUBPKT_FLAG_CRITICAL = 128
   }
index 2745734..21cd004 100644 (file)
@@ -972,28 +972,49 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
        sig->unhashed = newarea;
 }
 
-/****************
+/*
  * Put all the required stuff from SIG into subpackets of sig.
+ * PKSK is the signing key.
  * Hmmm, should we delete those subpackets which are in a wrong area?
  */
 void
-build_sig_subpkt_from_sig( PKT_signature *sig )
+build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk)
 {
     u32  u;
-    byte buf[8];
+    byte buf[1+MAX_FINGERPRINT_LEN];
+    size_t fprlen;
 
-    u = sig->keyid[0];
-    buf[0] = (u >> 24) & 0xff;
-    buf[1] = (u >> 16) & 0xff;
-    buf[2] = (u >>  8) & 0xff;
-    buf[3] = u & 0xff;
-    u = sig->keyid[1];
-    buf[4] = (u >> 24) & 0xff;
-    buf[5] = (u >> 16) & 0xff;
-    buf[6] = (u >>  8) & 0xff;
-    buf[7] = u & 0xff;
-    build_sig_subpkt( sig, SIGSUBPKT_ISSUER, buf, 8 );
+    /* For v4 keys we need to write the ISSUER subpacket.  We do not
+     * want that for a future v5 format.  */
+    if (pksk->version < 5)
+      {
+        u = sig->keyid[0];
+        buf[0] = (u >> 24) & 0xff;
+        buf[1] = (u >> 16) & 0xff;
+        buf[2] = (u >>  8) & 0xff;
+        buf[3] = u & 0xff;
+        u = sig->keyid[1];
+        buf[4] = (u >> 24) & 0xff;
+        buf[5] = (u >> 16) & 0xff;
+        buf[6] = (u >>  8) & 0xff;
+        buf[7] = u & 0xff;
+        build_sig_subpkt (sig, SIGSUBPKT_ISSUER, buf, 8);
+      }
+
+    /* For a future v5 keys we write the ISSUER_FPR subpacket.  We
+     * also write that for a v4 key is experimental support for
+     * RFC4880bis is requested.  */
+    if (pksk->version > 4 || opt.flags.rfc4880bis)
+      {
+        fingerprint_from_pk (pksk, buf+1, &fprlen);
+        if (fprlen == 20)
+          {
+            buf[0] = pksk->version;
+            build_sig_subpkt (sig, SIGSUBPKT_ISSUER_FPR, buf, 21);
+          }
+      }
 
+    /* Write the timestamp.  */
     u = sig->timestamp;
     buf[0] = (u >> 24) & 0xff;
     buf[1] = (u >> 16) & 0xff;
index 2aed10c..9ccc0da 100644 (file)
@@ -365,6 +365,17 @@ keyserver_import_keyid (u32 *keyid, void *dummy)
 }
 
 int
+keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
+                        struct keyserver_spec *keyserver)
+{
+  (void)ctrl;
+  (void)fprint;
+  (void)fprint_len;
+  (void)keyserver;
+  return -1;
+}
+
+int
 keyserver_import_cert (const char *name)
 {
   (void)name;
index 453d1b0..bd738ab 100644 (file)
@@ -1805,19 +1805,26 @@ check_sig_and_print (CTX c, kbnode_t node)
    * favor this over the WKD method (to be tried next), because an
    * arbitrary keyserver is less subject to web bug like
    * monitoring.  */
-  /* if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY */
-  /*     && signature_hash_full_fingerprint (sig) */
-  /*     && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) */
-  /*     && keyserver_any_configured (c->ctrl)) */
-  /*   { */
-  /*     int res; */
-
-  /*     glo_ctrl.in_auto_key_retrieve++; */
-  /*     res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver ); */
-  /*     glo_ctrl.in_auto_key_retrieve--; */
-  /*     if (!res) */
-  /*       rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey ); */
-  /*   } */
+  if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
+      && opt.flags.rfc4880bis
+      && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
+      && keyserver_any_configured (c->ctrl))
+    {
+      int res;
+      const byte *p;
+      size_t n;
+
+      p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_ISSUER_FPR, &n);
+      if (p && n == 21 && p[0] == 4)
+        {
+          /* v4 packet with a SHA-1 fingerprint.  */
+          glo_ctrl.in_auto_key_retrieve++;
+          res = keyserver_import_fprint (c->ctrl, p+1, n-1, opt.keyserver);
+          glo_ctrl.in_auto_key_retrieve--;
+          if (!res)
+            rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey );
+        }
+    }
 
   /* If the above methods didn't work, our next try is to retrieve the
    * key from the WKD. */
index 8fb6fc4..0ff28c8 100644 (file)
@@ -764,7 +764,7 @@ gpg_error_t gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a);
 u32 calc_packet_length( PACKET *pkt );
 void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
                        const byte *buffer, size_t buflen );
-void build_sig_subpkt_from_sig( PKT_signature *sig );
+void build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk);
 int  delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type );
 void build_attribute_subpkt(PKT_user_id *uid,byte type,
                            const void *buf,u32 buflen,
index e02238b..1c1b389 100644 (file)
@@ -1335,6 +1335,19 @@ dump_sig_subpkt (int hashed, int type, int critical,
                     (ulong) buf32_to_u32 (buffer),
                     (ulong) buf32_to_u32 (buffer + 4));
       break;
+    case SIGSUBPKT_ISSUER_FPR:
+      if (length >= 21)
+        {
+          char *tmp;
+          es_fprintf (listfp, "issuer fpr v%d ", buffer[0]);
+          tmp = bin2hex (buffer+1, length-1, NULL);
+          if (tmp)
+            {
+              es_fputs (tmp, listfp);
+              xfree (tmp);
+            }
+        }
+      break;
     case SIGSUBPKT_NOTATION:
       {
        es_fputs ("notation: ", listfp);
@@ -1485,6 +1498,10 @@ parse_one_sig_subpkt (const byte * buffer, size_t n, int type)
       if (n < 8)
        break;
       return 0;
+    case SIGSUBPKT_ISSUER_FPR: /* issuer key ID */
+      if (n < 21)
+       break;
+      return 0;
     case SIGSUBPKT_NOTATION:
       /* minimum length needed, and the subpacket must be well-formed
          where the name length and value length all fit inside the
@@ -1543,6 +1560,7 @@ can_handle_critical (const byte * buffer, size_t n, int type)
     case SIGSUBPKT_REVOCABLE:
     case SIGSUBPKT_REV_KEY:
     case SIGSUBPKT_ISSUER:     /* issuer key ID */
+    case SIGSUBPKT_ISSUER_FPR: /* issuer fingerprint */
     case SIGSUBPKT_PREF_SYM:
     case SIGSUBPKT_PREF_HASH:
     case SIGSUBPKT_PREF_COMPR:
index a4974be..3a96f0f 100644 (file)
@@ -690,7 +690,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
 
       if (sig->version >= 4)
         {
-          build_sig_subpkt_from_sig (sig);
+          build_sig_subpkt_from_sig (sig, pk);
           mk_notation_policy_etc (sig, NULL, pk);
         }
 
@@ -1456,7 +1456,7 @@ make_keysig_packet (PKT_signature **ret_sig, PKT_public_key *pk,
       sig->expiredate=sig->timestamp+duration;
     sig->sig_class = sigclass;
 
-    build_sig_subpkt_from_sig( sig );
+    build_sig_subpkt_from_sig (sig, pksk);
     mk_notation_policy_etc (sig, pk, pksk);
 
     /* Crucial that the call to mksubpkt comes LAST before the calls
@@ -1559,7 +1559,7 @@ update_keysig_packet( PKT_signature **ret_sig,
        automagically lower any sig expiration dates to correctly
        correspond to the differences in the timestamps (i.e. the
        duration will shrink).  */
-    build_sig_subpkt_from_sig( sig );
+    build_sig_subpkt_from_sig (sig, pksk);
 
     if (mksubpkt)
       rc = (*mksubpkt)(sig, opaque);
index 42c91f8..f4d9526 100644 (file)
@@ -177,6 +177,17 @@ keyserver_import_keyid (u32 *keyid, void *dummy)
 }
 
 int
+keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
+                        struct keyserver_spec *keyserver)
+{
+  (void)ctrl;
+  (void)fprint;
+  (void)fprint_len;
+  (void)keyserver;
+  return -1;
+}
+
+int
 keyserver_import_cert (const char *name)
 {
   (void)name;