From c03a3eb01d2d26bd69e6d7c7d2a5f72229e189e0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 11 Jun 2018 11:48:14 +0900 Subject: [PATCH] g10: Enumerated keys for decryption should be unique. * g10/getkey.c (enum_secret_keys): Collecting keys in the context, check duplicate to make sure returning only unique keys. * g10/pubkey-enc.c (get_session_key): Now, it's the responsibility of enum_secret_keys to free keys. -- Signed-off-by: NIIBE Yutaka --- g10/getkey.c | 25 +++++++++++++++++++++++++ g10/pubkey-enc.c | 2 -- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/g10/getkey.c b/g10/getkey.c index b111376c9..670dc1dc2 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -3950,6 +3950,7 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk) kbnode_t keyblock; kbnode_t node; getkey_ctx_t ctx; + pubkey_t results; } *c = *context; if (!c) @@ -3964,6 +3965,7 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk) if (!sk) { /* Free the context. */ + pubkeys_free (c->results); release_kbnode (c->keyblock); getkey_end (ctrl, c->ctx); xfree (c); @@ -4066,8 +4068,31 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk) if (c->node->pkt->pkttype == PKT_PUBLIC_KEY || c->node->pkt->pkttype == PKT_PUBLIC_SUBKEY) { + pubkey_t r; + + /* Skip this candidate if it's already enumerated. */ + for (r = c->results; r; r = r->next) + if (!cmp_public_keys (r->pk, c->node->pkt->pkt.public_key)) + break; + if (r) + continue; + copy_public_key (sk, c->node->pkt->pkt.public_key); c->node = c->node->next; + + r = xtrycalloc (1, sizeof (*r)); + if (!r) + { + err = gpg_error_from_syserror (); + free_public_key (sk); + return err; + } + + r->pk = sk; + r->keyblock = NULL; + r->next = c->results; + c->results = r; + return 0; /* Found. */ } } diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 8540e03c9..32b1ed08b 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -87,7 +87,6 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek) { struct pubkey_enc_list *k; - free_public_key (sk); sk = xmalloc_clear (sizeof *sk); rc = enum_secret_keys (ctrl, &enum_context, sk); if (rc) @@ -156,7 +155,6 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek) } } enum_secret_keys (ctrl, &enum_context, NULL); /* free context */ - free_public_key (sk); if (DBG_CLOCK) log_clock ("get_session_key leave");