aboutsummaryrefslogtreecommitdiffstats
path: root/g10/encrypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/encrypt.c')
-rw-r--r--g10/encrypt.c80
1 files changed, 67 insertions, 13 deletions
diff --git a/g10/encrypt.c b/g10/encrypt.c
index ea0ea1b2b..eaca0a51a 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -43,8 +43,10 @@
static int encrypt_simple( const char *filename, int mode, int use_seskey );
-static int write_pubkey_enc_from_list (ctrl_t ctrl,
- PK_LIST pk_list, DEK *dek, iobuf_t out);
+static int write_pubkey_enc_from_list (ctrl_t ctrl, pk_list_t pk_list,
+ DEK *dek, iobuf_t out,
+ struct pubkey_enc_info_item *restrct);
+
/* Helper for show the "encrypted for USER" during encryption.
@@ -933,7 +935,7 @@ encrypt_crypt (ctrl_t ctrl, gnupg_fd_t filefd, const char *filename,
if (DBG_CRYPTO)
log_printhex (cfx.dek->key, cfx.dek->keylen, "DEK is: ");
- rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out);
+ rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out, NULL);
if (rc)
goto leave;
@@ -1090,12 +1092,35 @@ reencrypt_to_new_recipients (ctrl_t ctrl, int armor, const char *filename,
gpg_error_t err;
int save_no_encrypt_to;
pk_list_t newpk_list = NULL;
+ struct pubkey_enc_info_item *restrict_pk_list = NULL;
+ struct pubkey_enc_info_item *pkei; /* Iterator */
iobuf_t outfp = NULL;
armor_filter_context_t *outafx = NULL;
PACKET pkt;
struct pubkey_enc_list *el;
unsigned int count;
+ /* Unless we want to clear the recipients, record the pubkey encrypt
+ * infos so hat we can avoid to double encrypt to the same
+ * recipient. We can't do that for wildcards, though. */
+ if (!ctrl->clear_recipients)
+ {
+ for (el = pkenc_list; el; el = el->next, count++)
+ {
+ if (el->u_sym)
+ continue;
+ if (!el->u.pub.keyid[0] && !el->u.pub.keyid[1])
+ continue; /* Wildcard encrypt - no useful info. */
+ pkei = xcalloc (1, sizeof *pkei);
+ pkei->keyid[0] = el->u.pub.keyid[0];
+ pkei->keyid[1] = el->u.pub.keyid[1];
+ pkei->version = el->u.pub.version;
+ pkei->pubkey_algo = el->u.pub.pubkey_algo;
+ pkei->next = restrict_pk_list;
+ restrict_pk_list = pkei;
+ }
+ }
+
/* Get the keys for all additional recipients but do not encrypt to
* the encrypt-to keys. */
save_no_encrypt_to = opt.no_encrypt_to;
@@ -1117,19 +1142,20 @@ reencrypt_to_new_recipients (ctrl_t ctrl, int armor, const char *filename,
}
/* Write the new recipients first. */
- err = write_pubkey_enc_from_list (ctrl, newpk_list, dek, outfp);
+ err = write_pubkey_enc_from_list (ctrl, newpk_list, dek, outfp,
+ restrict_pk_list);
if (err)
goto leave;
/* Write the old recipients in --add-recipients mode. */
for (count=0, el = pkenc_list; el; el = el->next, count++)
- if (!ctrl->clear_recipients)
+ if (!ctrl->clear_recipients && !el->u_sym)
{
if (opt.verbose)
- show_encrypted_for_user_info (ctrl, 0, &el->d, dek);
+ show_encrypted_for_user_info (ctrl, 0, &el->u.pub, dek);
init_packet (&pkt);
pkt.pkttype = PKT_PUBKEY_ENC;
- pkt.pkt.pubkey_enc = &el->d;
+ pkt.pkt.pubkey_enc = &el->u.pub;
err = build_packet (outfp, &pkt);
if (err)
log_error ("build_packet(pubkey_enc) failed: %s\n",
@@ -1157,6 +1183,12 @@ reencrypt_to_new_recipients (ctrl_t ctrl, int armor, const char *filename,
iobuf_close (outfp);
release_armor_context (outafx);
release_pk_list (newpk_list);
+ while (restrict_pk_list)
+ {
+ pkei = restrict_pk_list->next;
+ xfree (restrict_pk_list);
+ restrict_pk_list = pkei;
+ }
return err;
}
@@ -1198,7 +1230,7 @@ encrypt_filter (void *opaque, int control,
log_printhex (efx->cfx.dek->key, efx->cfx.dek->keylen, "DEK is: ");
rc = write_pubkey_enc_from_list (efx->ctrl,
- efx->pk_list, efx->cfx.dek, a);
+ efx->pk_list, efx->cfx.dek, a, NULL);
if (rc)
return rc;
@@ -1288,11 +1320,19 @@ write_pubkey_enc (ctrl_t ctrl,
/*
- * Write pubkey-enc packets from the list of PKs to OUT.
+ * Write pubkey-enc packets from the list of PKs PKLIST to OUT. DEK
+ * has the session key. If a packet with the same key is also found
+ * in RESTRICT_PK_LIST, it is not written.
*/
static int
-write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out)
+write_pubkey_enc_from_list (ctrl_t ctrl, pk_list_t pk_list, DEK *dek,
+ iobuf_t out,
+ struct pubkey_enc_info_item *restrict_pk_list)
{
+ PKT_public_key *pk;
+ struct pubkey_enc_info_item *pkei;
+ int throw_keyid, rc;
+
if (opt.throw_keyids && (PGP7 || PGP8))
{
log_info(_("option '%s' may not be used in %s mode\n"),
@@ -1303,9 +1343,23 @@ write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out)
for ( ; pk_list; pk_list = pk_list->next )
{
- PKT_public_key *pk = pk_list->pk;
- int throw_keyid = (opt.throw_keyids || (pk_list->flags&1));
- int rc = write_pubkey_enc (ctrl, pk, throw_keyid, dek, out);
+ pk = pk_list->pk;
+ for (pkei = restrict_pk_list; pkei; pkei = pkei->next)
+ if (pk->keyid[0] == pkei->keyid[0]
+ && pk->keyid[1] == pkei->keyid[1]
+ && pk->version == pkei->version
+ && pk->pubkey_algo == pkei->pubkey_algo)
+ break;
+ if (pkei)
+ {
+ if (opt.verbose)
+ log_info (_("already encrypted to %08lX\n"),
+ (ulong) keyid_from_pk (pk, NULL));
+ continue;
+ }
+
+ throw_keyid = (opt.throw_keyids || (pk_list->flags&1));
+ rc = write_pubkey_enc (ctrl, pk, throw_keyid, dek, out);
if (rc)
return rc;
}