diff options
author | Werner Koch <[email protected]> | 2014-09-17 13:12:08 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2014-09-17 13:12:08 +0000 |
commit | 457bce5cd39146df047e4740162125c32c738789 (patch) | |
tree | 915fe264027c168e0c0610c983ef9d72c6e90a72 /agent/findkey.c | |
parent | gpg: Use algorithm id 22 for EdDSA. (diff) | |
download | gnupg-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.c | 42 |
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); } |