summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/openpgpdefs.h1
-rw-r--r--doc/gpg.texi10
-rw-r--r--g10/gpg.c7
-rw-r--r--g10/options.h1
-rw-r--r--g10/parse-packet.c29
-rw-r--r--g10/sign.c108
6 files changed, 145 insertions, 11 deletions
diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h
index 2962fe2d4..5ab45debd 100644
--- a/common/openpgpdefs.h
+++ b/common/openpgpdefs.h
@@ -120,6 +120,7 @@ typedef enum
SIGSUBPKT_PREF_AEAD = 34, /* Preferred AEAD algorithms. */
SIGSUBPKT_ATTST_SIGS = 37, /* Attested Certifications. */
+ SIGSUBPKT_KEY_BLOCK = 38, /* Entire key used. */
SIGSUBPKT_FLAG_CRITICAL = 128
}
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 2cb20f4c7..105aaf9df 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -2700,6 +2700,16 @@ As of now this is only done if the signing key has been specified with
information can be helpful for verifier to locate the key; see option
@option{--auto-key-retrieve}.
+@item --include-key-block
+@opindex include-key-block
+This option is used to embed the actual signing key into a data
+signature. The embedded key is stripped down to a single user id and
+includes only the signing subkey used to create the signature as well
+as as valid encryption subkeys. All other info is removed from the
+key to keep it and thus the signature small. This option is the
+OpenPGP counterpart to the @command{gpgsm} option
+@option{--include-certs}.
+
@item --personal-cipher-preferences @var{string}
@opindex personal-cipher-preferences
Set the list of personal cipher preferences to @var{string}. Use
diff --git a/g10/gpg.c b/g10/gpg.c
index bf7421577..05289880a 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -433,6 +433,7 @@ enum cmd_and_opt_values
oNoSymkeyCache,
oUseOnlyOpenPGPCard,
oFullTimestrings,
+ oIncludeKeyBlock,
oNoop
};
@@ -748,7 +749,9 @@ static gpgrt_opt_t opts[] = {
N_("|N|set compress level to N (0 disables)")),
ARGPARSE_s_i (oCompressLevel, "compress-level", "@"),
ARGPARSE_s_i (oBZ2CompressLevel, "bzip2-compress-level", "@"),
-
+ ARGPARSE_s_n (oDisableSignerUID, "disable-signer-uid", "@"),
+ ARGPARSE_s_n (oIncludeKeyBlock, "include-key-block",
+ N_("include the public key in the signature")),
ARGPARSE_header ("ImportExport",
N_("Options controlling key import and export")),
@@ -826,7 +829,6 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"),
ARGPARSE_s_s (oOverrideSessionKey, "override-session-key", "@"),
ARGPARSE_s_i (oOverrideSessionKeyFD, "override-session-key-fd", "@"),
- ARGPARSE_s_n (oDisableSignerUID, "disable-signer-uid", "@"),
ARGPARSE_header ("Security", N_("Options controlling the security")),
@@ -3032,6 +3034,7 @@ main (int argc, char **argv)
case oForceAEAD: opt.force_aead = 1; 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;
diff --git a/g10/options.h b/g10/options.h
index 4f190a1bc..d05164eac 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -241,6 +241,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 "-". */
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 7c330ee43..d554bf5fe 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -1615,6 +1615,23 @@ dump_sig_subpkt (int hashed, int type, int critical,
}
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)
@@ -1692,6 +1709,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;
}
@@ -1760,6 +1783,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;
}
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;