aboutsummaryrefslogtreecommitdiffstats
path: root/agent/cache.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/cache.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/cache.c')
-rw-r--r--agent/cache.c29
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;
+}