aboutsummaryrefslogtreecommitdiffstats
path: root/agent/findkey.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-09-17 13:12:08 +0000
committerWerner Koch <[email protected]>2014-09-17 13:12:08 +0000
commit457bce5cd39146df047e4740162125c32c738789 (patch)
tree915fe264027c168e0c0610c983ef9d72c6e90a72 /agent/findkey.c
parentgpg: Use algorithm id 22 for EdDSA. (diff)
downloadgnupg-457bce5cd39146df047e4740162125c32c738789.tar.gz
gnupg-457bce5cd39146df047e4740162125c32c738789.zip
gpg: Improve passphrase caching.
* agent/cache.c (last_stored_cache_key): New. (agent_get_cache): Allow NULL for KEY. (agent_store_cache_hit): New. * agent/findkey.c (unprotect): Call new function and try to use the last stored key. * g10/revoke.c (create_revocation): Add arg CACHE_NONCE and pass to make_keysig_packet. (gen_standard_revoke): Add arg CACHE_NONCE and pass to create_revocation. * g10/keygen.c (do_generate_keypair): Call gen_standard_revoke with cache nonce. -- This patch adds two features: 1. The key for the last passphrase successfully used for unprotecting a key is stored away. On a cache miss the stored away passphrase is tried as well. This helps for the common GPG use case of having a signing and encryption (sub)key with the same passphrase. See the code for more comments. 2. The now auto-generated revocation certificate does not anymore popup a passphrase prompt. Thus for standard key generation the passphrase needs to be given only once (well, two with the confirmation).
Diffstat (limited to 'agent/findkey.c')
-rw-r--r--agent/findkey.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/agent/findkey.c b/agent/findkey.c
index 5ff263ef4..fbe303116 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -372,6 +372,8 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
rc = agent_unprotect (ctrl, *keybuf, pw, NULL, &result, &resultlen);
if (!rc)
{
+ if (cache_mode == CACHE_MODE_NORMAL)
+ agent_store_cache_hit (hexgrip);
if (r_passphrase)
*r_passphrase = pw;
else
@@ -383,6 +385,45 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
xfree (pw);
rc = 0;
}
+ else if (cache_mode == CACHE_MODE_NORMAL)
+ {
+ /* The standard use of GPG keys is to have a signing and an
+ encryption subkey. Commonly both use the same
+ passphrase. We try to help the user to enter the
+ passphrase only once by silently trying the last
+ correctly entered passphrase. Checking one additional
+ passphrase should be acceptable; despite the S2K
+ introduced delays. The assumed workflow is:
+
+ 1. Read encrypted message in a MUA and thus enter a
+ passphrase for the encryption subkey.
+
+ 2. Reply to that mail with an encrypted and signed
+ mail, thus entering the passphrase for the signing
+ subkey.
+
+ We can often avoid the passphrase entry in the second
+ step. We do this only in normal mode, so not to
+ interfere with unrelated cache entries. */
+ pw = agent_get_cache (NULL, cache_mode);
+ if (pw)
+ {
+ rc = agent_unprotect (ctrl, *keybuf, pw, NULL,
+ &result, &resultlen);
+ if (!rc)
+ {
+ if (r_passphrase)
+ *r_passphrase = pw;
+ else
+ xfree (pw);
+ xfree (*keybuf);
+ *keybuf = result;
+ return 0;
+ }
+ xfree (pw);
+ rc = 0;
+ }
+ }
/* If the pinentry is currently in use, we wait up to 60 seconds
for it to close and check the cache again. This solves a common
@@ -460,6 +501,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
{
agent_put_cache (hexgrip, cache_mode, pi->pin,
lookup_ttl? lookup_ttl (hexgrip) : 0);
+ agent_store_cache_hit (hexgrip);
if (r_passphrase && *pi->pin)
*r_passphrase = xtrystrdup (pi->pin);
}