From 955baf04364721457cd99aad21942523cd50498c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 20 Jun 2016 23:58:16 +0200 Subject: [PATCH] gpg: Add experimental support for an issuer fpr. * 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 --- common/openpgpdefs.h | 1 + g10/build-packet.c | 49 +++++++++++++++++++++++++++++++------------- g10/gpgv.c | 11 ++++++++++ g10/mainproc.c | 33 +++++++++++++++++------------ g10/packet.h | 2 +- g10/parse-packet.c | 18 ++++++++++++++++ g10/sign.c | 6 +++--- g10/test-stubs.c | 11 ++++++++++ 8 files changed, 100 insertions(+), 31 deletions(-) diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h index f8b86e1bd..2c0ace2a5 100644 --- a/common/openpgpdefs.h +++ b/common/openpgpdefs.h @@ -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 } diff --git a/g10/build-packet.c b/g10/build-packet.c index 2745734b4..21cd004a8 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -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; diff --git a/g10/gpgv.c b/g10/gpgv.c index 2aed10c2a..9ccc0da99 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -364,6 +364,17 @@ keyserver_import_keyid (u32 *keyid, void *dummy) return -1; } +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) { diff --git a/g10/mainproc.c b/g10/mainproc.c index 453d1b07b..bd738abaa 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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. */ diff --git a/g10/packet.h b/g10/packet.h index 8fb6fc48f..0ff28c82b 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -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, diff --git a/g10/parse-packet.c b/g10/parse-packet.c index e02238bfd..1c1b389d8 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -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: diff --git a/g10/sign.c b/g10/sign.c index a4974be85..3a96f0f1f 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -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); diff --git a/g10/test-stubs.c b/g10/test-stubs.c index 42c91f869..f4d952665 100644 --- a/g10/test-stubs.c +++ b/g10/test-stubs.c @@ -176,6 +176,17 @@ keyserver_import_keyid (u32 *keyid, void *dummy) return -1; } +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) {