diff options
-rw-r--r-- | common/openpgpdefs.h | 1 | ||||
-rw-r--r-- | doc/gpg.texi | 10 | ||||
-rw-r--r-- | g10/gpg.c | 7 | ||||
-rw-r--r-- | g10/options.h | 1 | ||||
-rw-r--r-- | g10/parse-packet.c | 29 | ||||
-rw-r--r-- | g10/sign.c | 108 |
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 @@ -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; |