1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

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 <wk@gnupg.org>

Backported from master.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-03-13 13:28:35 +01:00
parent 2baa00ea18
commit d79ebee64e
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
6 changed files with 147 additions and 11 deletions

View file

@ -424,6 +424,7 @@ enum cmd_and_opt_values
oRequestOrigin,
oNoSymkeyCache,
oUseOnlyOpenPGPCard,
oIncludeKeyBlock,
oNoop
};
@ -888,6 +889,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oNoAutoKeyLocate, "no-auto-key-locate", "@"),
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
ARGPARSE_s_n (oNoSymkeyCache, "no-symkey-cache", "@"),
ARGPARSE_s_n (oIncludeKeyBlock, "include-key-block", "@"),
/* Options to override new security defaults. */
ARGPARSE_s_n (oAllowWeakKeySignatures, "allow-weak-key-signatures", "@"),
@ -2990,6 +2992,7 @@ main (int argc, char **argv)
case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break;
case oDisableSignerUID: opt.flags.disable_signer_uid = 1; break;
case oIncludeKeyBlock: opt.flags.include_key_block = 1; break;
case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break;
case oS2KDigest: s2k_digest_string = xstrdup(pargs.r.ret_str); break;

View file

@ -232,6 +232,7 @@ struct
unsigned int allow_weak_key_signatures:1;
unsigned int large_rsa:1;
unsigned int disable_signer_uid:1;
unsigned int include_key_block:1;
/* Flag to enable experimental features from RFC4880bis. */
unsigned int rfc4880bis:1;
/* Hack: --output is not given but OUTFILE was temporary set to "-". */

View file

@ -1548,6 +1548,24 @@ dump_sig_subpkt (int hashed, int type, int critical,
buffer[0] == 3 ? buffer[15] : buffer[2],
buffer[0] == 3 ? buffer[16] : buffer[3]);
break;
case SIGSUBPKT_KEY_BLOCK:
es_fputs ("key-block: ", listfp);
if (length && buffer[0])
p = "[unknown reserved octet]";
else if (length < 50) /* 50 is an arbitrary min. length. */
p = "[invalid subpacket]";
else
{
/* estream_t fp; */
/* fp = es_fopen ("a.key-block", "wb"); */
/* log_assert (fp); */
/* es_fwrite ( buffer+1, length-1, 1, fp); */
/* es_fclose (fp); */
es_fprintf (listfp, "[%u octets]", (unsigned int)length-1);
}
break;
default:
if (type >= 100 && type <= 110)
p = "experimental / private subpacket";
@ -1622,6 +1640,12 @@ parse_one_sig_subpkt (const byte * buffer, size_t n, int type)
if (n != 2)
break;
return 0;
case SIGSUBPKT_KEY_BLOCK:
if (n && buffer[0])
return -1; /* Unknown version - ignore. */
if (n < 50)
break; /* Definitely too short to carry a key block. */
return 0;
default:
return 0;
}
@ -1688,6 +1712,12 @@ can_handle_critical (const byte * buffer, size_t n, int type)
case SIGSUBPKT_REVOC_REASON: /* At least we know about it. */
return 1;
case SIGSUBPKT_KEY_BLOCK:
if (n && !buffer[0])
return 1;
else
return 0;
default:
return 0;
}

View file

@ -185,6 +185,91 @@ mk_notation_policy_etc (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)))
{
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.
*/
@ -737,7 +822,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;
@ -770,14 +855,18 @@ write_signature_packets (ctrl_t ctrl,
{
build_sig_subpkt_from_sig (sig, pk);
mk_notation_policy_etc (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);
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;
@ -785,19 +874,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;