aboutsummaryrefslogtreecommitdiffstats
path: root/g10/sign.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-03-13 12:28:35 +0000
committerWerner Koch <[email protected]>2020-03-13 12:34:49 +0000
commit865d485180240369a20d3be14d0c6499783df2b5 (patch)
treea5f3a95e9d714517dabbc66987ee1f01cb65d55f /g10/sign.c
parentgpg: Add property "fpr" for use by --export-filter. (diff)
downloadgnupg-865d485180240369a20d3be14d0c6499783df2b5.tar.gz
gnupg-865d485180240369a20d3be14d0c6499783df2b5.zip
gpg: New option --include-key-block.
* common/openpgpdefs.h (SIGSUBPKT_KEY_BLOCK): New. * g10/gpg.c (oIncludeKeyBlock): New. (opts): New option --include-key-block. (main): Implement. * g10/options.h (opt): New flag include_key_block. * g10/parse-packet.c (dump_sig_subpkt): Support SIGSUBPKT_KEY_BLOCK. (parse_one_sig_subpkt): Ditto. (can_handle_critical): Ditto. * g10/sign.c (mk_sig_subpkt_key_block): New. (write_signature_packets): Call it for data signatures. -- This patch adds support for a to be proposed OpenPGP ferature: Introduce the Key Block subpacket to align OpenPGP with CMS. This new subpacket may be used similar to the CertificateSet of CMS (RFC-5652) and thus allows to start encrypted communication after having received a signed message. In practice a stripped down version of the key should be including having only the key material and the self-signatures which are really useful and shall be used by the recipient to reply encrypted. #### Key Block (1 octet with value 0, N octets of key data) This subpacket MAY be used to convey key data along with a signature of class 0x00, 0x01, or 0x02. It MUST contain the key used to create the signature; either as the primary key or as a subkey. The key SHOULD contain a primary or subkey capable of encryption and the entire key must be a valid OpenPGP key including at least one User ID packet and the corresponding self-signatures. Implementations MUST ignore this subpacket if the first octet does not have a value of zero or if the key data does not represent a valid transferable public key. GnuPG-bug-id: 4856 Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'g10/sign.c')
-rw-r--r--g10/sign.c108
1 files changed, 99 insertions, 9 deletions
diff --git a/g10/sign.c b/g10/sign.c
index f0d622b31..90466e9bc 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -202,6 +202,91 @@ mk_notation_policy_etc (ctrl_t ctrl, PKT_signature *sig,
}
+
+/*
+ * Put the Key Block subpakcet into SIG for key PKSK. Returns an
+ * error code on failure.
+ */
+static gpg_error_t
+mk_sig_subpkt_key_block (ctrl_t ctrl, PKT_signature *sig, PKT_public_key *pksk)
+{
+ gpg_error_t err;
+ char *mbox;
+ char *filterexp = NULL;
+ int save_opt_armor = opt.armor;
+ int save_opt_verbose = opt.verbose;
+ char hexfpr[2*MAX_FINGERPRINT_LEN + 1];
+ void *data = NULL;
+ size_t datalen;
+ kbnode_t keyblock = NULL;
+
+ push_export_filters ();
+ opt.armor = 0;
+
+ hexfingerprint (pksk, hexfpr, sizeof hexfpr);
+
+ /* Get the user id so that we know which one to insert into the
+ * key. */
+ if (pksk->user_id
+ && (mbox = mailbox_from_userid (pksk->user_id->name, 0)))
+ {
+ if (DBG_LOOKUP)
+ log_debug ("including key with UID '%s' (specified)\n", mbox);
+ filterexp = xasprintf ("keep-uid= -- mbox = %s", mbox);
+ xfree (mbox);
+ }
+ else if (opt.sender_list)
+ {
+ /* If --sender was given we use the first one from that list. */
+ if (DBG_LOOKUP)
+ log_debug ("including key with UID '%s' (--sender)\n",
+ opt.sender_list->d);
+ filterexp = xasprintf ("keep-uid= -- mbox = %s", opt.sender_list->d);
+ }
+ else /* Use the primary user id. */
+ {
+ if (DBG_LOOKUP)
+ log_debug ("including key with primary UID\n");
+ filterexp = xstrdup ("keep-uid= primary -t");
+ }
+
+ if (DBG_LOOKUP)
+ log_debug ("export filter expression: %s\n", filterexp);
+ err = parse_and_set_export_filter (filterexp);
+ if (err)
+ goto leave;
+ xfree (filterexp);
+ filterexp = xasprintf ("drop-subkey= fpr <> %s && usage !~ e", hexfpr);
+ if (DBG_LOOKUP)
+ log_debug ("export filter expression: %s\n", filterexp);
+ err = parse_and_set_export_filter (filterexp);
+ if (err)
+ goto leave;
+
+
+ opt.verbose = 0;
+ err = export_pubkey_buffer (ctrl, hexfpr, EXPORT_MINIMAL|EXPORT_CLEAN,
+ "", 1, /* Prefix with the reserved byte. */
+ NULL, &keyblock, &data, &datalen);
+ opt.verbose = save_opt_verbose;
+ if (err)
+ {
+ log_error ("failed to get to be included key: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ build_sig_subpkt (sig, SIGSUBPKT_KEY_BLOCK, data, datalen);
+
+ leave:
+ xfree (data);
+ release_kbnode (keyblock);
+ xfree (filterexp);
+ opt.armor = save_opt_armor;
+ pop_export_filters ();
+ return err;
+}
+
+
/*
* Helper to hash a user ID packet.
*/
@@ -835,7 +920,7 @@ write_signature_packets (ctrl_t ctrl,
PKT_public_key *pk;
PKT_signature *sig;
gcry_md_hd_t md;
- int rc;
+ gpg_error_t err;
pk = sk_rover->pk;
@@ -865,12 +950,17 @@ write_signature_packets (ctrl_t ctrl,
build_sig_subpkt_from_sig (sig, pk);
mk_notation_policy_etc (ctrl, sig, NULL, pk);
+ if (opt.flags.include_key_block && IS_SIG (sig))
+ err = mk_sig_subpkt_key_block (ctrl, sig, pk);
+ else
+ err = 0;
hash_sigversion_to_magic (md, sig, extrahash);
gcry_md_final (md);
- rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce, 0);
+ if (!err)
+ err = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce, 0);
gcry_md_close (md);
- if (!rc)
+ if (!err)
{
/* Write the packet. */
PACKET pkt;
@@ -878,19 +968,19 @@ write_signature_packets (ctrl_t ctrl,
init_packet (&pkt);
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
- rc = build_packet (out, &pkt);
- if (!rc && is_status_enabled())
+ err = build_packet (out, &pkt);
+ if (!err && is_status_enabled())
print_status_sig_created (pk, sig, status_letter);
free_packet (&pkt, NULL);
- if (rc)
+ if (err)
log_error ("build signature packet failed: %s\n",
- gpg_strerror (rc));
+ gpg_strerror (err));
}
else
free_seckey_enc (sig);
- if (rc)
- return rc;
+ if (err)
+ return err;
}
return 0;