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/cache.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/cache.c')
-rw-r--r-- | agent/cache.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/agent/cache.c b/agent/cache.c index d4deaeb8c..49402e434 100644 --- a/agent/cache.c +++ b/agent/cache.c @@ -65,6 +65,9 @@ struct cache_item_s { /* The cache himself. */ static ITEM thecache; +/* NULL or the last cache key stored by agent_store_cache_hit. */ +static char *last_stored_cache_key; + /* This function must be called once to initialize this module. It has to be done before a second thread is spawned. */ @@ -388,12 +391,24 @@ agent_get_cache (const char *key, cache_mode_t cache_mode) ITEM r; char *value = NULL; int res; + int last_stored = 0; if (cache_mode == CACHE_MODE_IGNORE) return NULL; + if (!key) + { + key = last_stored_cache_key; + if (!key) + return NULL; + last_stored = 1; + } + + if (DBG_CACHE) - log_debug ("agent_get_cache '%s' (mode %d) ...\n", key, cache_mode); + log_debug ("agent_get_cache '%s' (mode %d)%s ...\n", + key, cache_mode, + last_stored? " (stored cache key)":""); housekeeping (); for (r=thecache; r; r = r->next) @@ -404,6 +419,7 @@ agent_get_cache (const char *key, cache_mode_t cache_mode) || r->cache_mode == cache_mode) && !strcmp (r->key, key)) { + /* Note: To avoid races KEY may not be accessed anymore below. */ r->accessed = gnupg_get_time (); if (DBG_CACHE) log_debug ("... hit\n"); @@ -442,3 +458,14 @@ agent_get_cache (const char *key, cache_mode_t cache_mode) return NULL; } + + +/* Store the key for the last successful cache hit. That value is + used by agent_get_cache if the requested KEY is given as NULL. + NULL may be used to remove that key. */ +void +agent_store_cache_hit (const char *key) +{ + xfree (last_stored_cache_key); + last_stored_cache_key = key? xtrystrdup (key) : NULL; +} |