diff options
author | Werner Koch <wk@gnupg.org> | 2021-05-19 02:32:19 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2021-05-19 02:42:35 +0200 |
commit | 40da61b89b62dcb77847dc79eb159e885f52f817 (patch) | |
tree | cc96e9d8b54046a2a541f066c9e579921f07e523 /g10/call-agent.c | |
parent | gpg: Fix sending an OpenPGP key with umlaut to an LDAP keyserver. (diff) | |
download | gnupg2-40da61b89b62dcb77847dc79eb159e885f52f817.tar.xz gnupg2-40da61b89b62dcb77847dc79eb159e885f52f817.zip |
gpg: Improve speed of secret key listing.
* agent/command.c (cmd_keyinfo): Factor some code out to ...
(get_keyinfo_on_cards): ... new.
(cmd_havekey): Add --list mode.
* g10/gpg.h (struct server_control_s): Add new caching vars.
* g10/gpg.c (gpg_deinit_default_ctrl): Release cache.
* g10/call-agent.c (agent_probe_any_secret_key): Init and try to use
the keygrip cache.
(agent_genkey): Clear the cache.
(agent_import_key): Ditto.
* g10/keylist.c (list_all, list_one): Pass ctrl to
agent_probe_any_secret_key.
* g10/getkey.c (lookup): Ditto.
--
With this change we first ask the agent for a list of all secret
keygrips and use that list instead of asking the agent for each public
key. Speeds up my "gpg -K" with a lot of secret and public keys by
more than 25%.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'g10/call-agent.c')
-rw-r--r-- | g10/call-agent.c | 104 |
1 files changed, 88 insertions, 16 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c index 83355454a..782631c0d 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -2236,13 +2236,50 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) char line[ASSUAN_LINELENGTH]; char *p; kbnode_t kbctx, node; - int nkeys; + int nkeys; /* (always zero in secret_keygrips mode) */ unsigned char grip[KEYGRIP_LEN]; + const unsigned char *s; + unsigned int n; err = start_agent (ctrl, 0); if (err) return err; + /* If we have not yet issued a "HAVEKEY --list" do that now. We use + * a more or less arbitray limit of 1000 keys. */ + if (ctrl && !ctrl->secret_keygrips && !ctrl->no_more_secret_keygrips) + { + membuf_t data; + + init_membuf (&data, 4096); + err = assuan_transact (agent_ctx, "HAVEKEY --list=1000", + put_membuf_cb, &data, + NULL, NULL, NULL, NULL); + if (err) + xfree (get_membuf (&data, NULL)); + else + { + ctrl->secret_keygrips = get_membuf (&data, + &ctrl->secret_keygrips_len); + if (!ctrl->secret_keygrips) + err = gpg_error_from_syserror (); + if ((ctrl->secret_keygrips_len % 20)) + { + err = gpg_error (GPG_ERR_INV_DATA); + xfree (ctrl->secret_keygrips); + ctrl->secret_keygrips = NULL; + } + } + if (err) + { + log_info ("problem with fast path key listing: %s - ignored\n", + gpg_strerror (err)); + err = 0; + } + /* We want to do this only once. */ + ctrl->no_more_secret_keygrips = 1; + } + err = gpg_error (GPG_ERR_NO_SECKEY); /* Just in case no key was found in KEYBLOCK. */ p = stpcpy (line, "HAVEKEY"); @@ -2252,23 +2289,42 @@ agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) || node->pkt->pkttype == PKT_SECRET_KEY || node->pkt->pkttype == PKT_SECRET_SUBKEY) { - if (nkeys && ((p - line) + 41) > (ASSUAN_LINELENGTH - 2)) + if (ctrl && ctrl->secret_keygrips) { - err = assuan_transact (agent_ctx, line, - NULL, NULL, NULL, NULL, NULL, NULL); - if (err != gpg_err_code (GPG_ERR_NO_SECKEY)) - break; /* Seckey available or unexpected error - ready. */ - p = stpcpy (line, "HAVEKEY"); - nkeys = 0; + /* We got an array with all secret keygrips. Check this. */ + err = keygrip_from_pk (node->pkt->pkt.public_key, grip); + if (err) + return err; + for (s=ctrl->secret_keygrips, n = 0; + n < ctrl->secret_keygrips_len; + s += 20, n += 20) + { + if (!memcmp (s, grip, 20)) + return 0; + } + err = gpg_error (GPG_ERR_NO_SECKEY); + /* Keep on looping over the keyblock. Never bump nkeys. */ + } + else + { + if (nkeys && ((p - line) + 41) > (ASSUAN_LINELENGTH - 2)) + { + err = assuan_transact (agent_ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); + if (err != gpg_err_code (GPG_ERR_NO_SECKEY)) + break; /* Seckey available or unexpected error - ready. */ + p = stpcpy (line, "HAVEKEY"); + nkeys = 0; + } + + err = keygrip_from_pk (node->pkt->pkt.public_key, grip); + if (err) + return err; + *p++ = ' '; + bin2hex (grip, 20, p); + p += 40; + nkeys++; } - - err = keygrip_from_pk (node->pkt->pkt.public_key, grip); - if (err) - return err; - *p++ = ' '; - bin2hex (grip, 20, p); - p += 40; - nkeys++; } if (!err && nkeys) @@ -2419,6 +2475,14 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr, char **passwd_nonce_addr, return err; dfltparm.ctx = agent_ctx; + /* Do not use our cache of secret keygrips anymore - this command + * would otherwise requiring to update that cache. */ + if (ctrl && ctrl->secret_keygrips) + { + xfree (ctrl->secret_keygrips); + ctrl->secret_keygrips = 0; + } + if (timestamp) { strcpy (timestamparg, " --timestamp="); @@ -2876,6 +2940,14 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr, return err; dfltparm.ctx = agent_ctx; + /* Do not use our cache of secret keygrips anymore - this command + * would otherwise requiring to update that cache. */ + if (ctrl && ctrl->secret_keygrips) + { + xfree (ctrl->secret_keygrips); + ctrl->secret_keygrips = 0; + } + if (timestamp) { strcpy (timestamparg, " --timestamp="); |