aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2002-02-01 11:39:06 +0000
committerWerner Koch <[email protected]>2002-02-01 11:39:06 +0000
commit30f1b027c012f8022c67185832fa1aada26c396a (patch)
treec2a8b3c3e993dbb47643ea9c220277a23b857bea
parentAdded a few more error codes (diff)
downloadgnupg-30f1b027c012f8022c67185832fa1aada26c396a.tar.gz
gnupg-30f1b027c012f8022c67185832fa1aada26c396a.zip
* cache.c: Add a few debug outputs.
* protect.c (agent_private_key_type): New. * agent.h: Add PRIVATE_KEY_ enums. * findkey.c (agent_key_from_file): Use it to decide whether we have to unprotect a key. (unprotect): Cache the passphrase. * findkey.c (agent_key_from_file,agent_key_available): The key files do now require a ".key" suffix to make a script's life easier. * genkey.c (store_key): Ditto.
-rw-r--r--agent/ChangeLog15
-rw-r--r--agent/agent.h8
-rw-r--r--agent/cache.c15
-rw-r--r--agent/findkey.c65
-rw-r--r--agent/genkey.c4
-rw-r--r--agent/protect.c27
6 files changed, 118 insertions, 16 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 21f496628..83ac2b33c 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,18 @@
+2002-02-01 Werner Koch <[email protected]>
+
+ * cache.c: Add a few debug outputs.
+
+ * protect.c (agent_private_key_type): New.
+ * agent.h: Add PRIVATE_KEY_ enums.
+ * findkey.c (agent_key_from_file): Use it to decide whether we
+ have to unprotect a key.
+ (unprotect): Cache the passphrase.
+
+ * findkey.c (agent_key_from_file,agent_key_available): The key
+ files do now require a ".key" suffix to make a script's life
+ easier.
+ * genkey.c (store_key): Ditto.
+
2002-01-31 Werner Koch <[email protected]>
* genkey.c (store_key): Protect the key.
diff --git a/agent/agent.h b/agent/agent.h
index 955dd1ce2..0b88d9a2c 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -83,6 +83,13 @@ struct pin_entry_info_s {
};
+enum {
+ PRIVATE_KEY_UNKNOWN = 0,
+ PRIVATE_KEY_CLEAR = 1,
+ PRIVATE_KEY_PROTECTED = 2,
+ PRIVATE_KEY_SHADOWED = 3
+};
+
/*-- gpg-agent.c --*/
void agent_exit (int rc); /* also implemented in other tools */
@@ -125,6 +132,7 @@ int agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned char **result, size_t *resultlen);
int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
unsigned char **result, size_t *resultlen);
+int agent_private_key_type (const unsigned char *privatekey);
/*-- trustlist.c --*/
diff --git a/agent/cache.c b/agent/cache.c
index aa7a21b16..480eb277c 100644
--- a/agent/cache.c
+++ b/agent/cache.c
@@ -89,6 +89,9 @@ housekeeping (void)
{
if (r->pw && r->accessed + r->ttl < current)
{
+ if (DBG_CACHE)
+ log_debug (" expired `%s' (%ds after last access)\n",
+ r->key, r->ttl);
release_data (r->pw);
r->pw = NULL;
r->accessed = current;
@@ -101,6 +104,8 @@ housekeeping (void)
{
if (r->pw && r->created + 60*60 < current)
{
+ if (DBG_CACHE)
+ log_debug (" expired `%s' (1h after creation)\n", r->key);
release_data (r->pw);
r->pw = NULL;
r->accessed = current;
@@ -114,6 +119,8 @@ housekeeping (void)
if (!r->pw && r->accessed + 60*30 < current)
{
ITEM r2 = r->next;
+ if (DBG_CACHE)
+ log_debug (" removed `%s' (slot not used for 30m)\n", r->key);
xfree (r);
if (!rprev)
thecache = r2;
@@ -140,6 +147,8 @@ agent_put_cache (const char *key, const char *data, int ttl)
{
ITEM r;
+ if (DBG_CACHE)
+ log_debug ("agent_put_cache `%s'\n", key);
housekeeping ();
if (ttl < 1)
@@ -198,6 +207,8 @@ agent_get_cache (const char *key)
ITEM r;
int count = 0;
+ if (DBG_CACHE)
+ log_debug ("agent_get_cache `%s'...\n", key);
housekeeping ();
/* FIXME: Returning pointers is not thread safe - add a referencense
@@ -209,9 +220,13 @@ agent_get_cache (const char *key)
/* put_cache does only put strings into the cache, so we
don't need the lengths */
r->accessed = time (NULL);
+ if (DBG_CACHE)
+ log_debug ("... hit\n");
return r->pw->data;
}
}
+ if (DBG_CACHE)
+ log_debug ("... miss\n");
return NULL;
}
diff --git a/agent/findkey.c b/agent/findkey.c
index 097903340..250852c23 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -31,16 +31,36 @@
#include "agent.h"
static int
-unprotect (unsigned char **keybuf)
+unprotect (unsigned char **keybuf, const unsigned char *grip)
{
struct pin_entry_info_s *pi;
- int rc;
+ int rc, i;
unsigned char *result;
size_t resultlen;
int tries = 0;
+ char hexgrip[40+1];
+
+ for (i=0; i < 20; i++)
+ sprintf (hexgrip+2*i, "%02X", grip[i]);
+ hexgrip[40] = 0;
- /* fixme: check whether the key needs unprotection */
-
+ /* first try to get it from the cache - if there is none or we can't
+ unprotect it, we fall back to ask the user */
+ {
+ const char *pw = agent_get_cache (hexgrip);
+ if (pw)
+ {
+ rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
+ if (!rc)
+ {
+ xfree (*keybuf);
+ *keybuf = result;
+ return 0;
+ }
+ rc = 0;
+ }
+ }
+
pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
pi->max_length = 100;
pi->min_digits = 0; /* we want a real passphrase */
@@ -55,6 +75,7 @@ unprotect (unsigned char **keybuf)
rc = agent_unprotect (*keybuf, pi->pin, &result, &resultlen);
if (!rc)
{
+ agent_put_cache (hexgrip, pi->pin, 0);
xfree (*keybuf);
*keybuf = result;
xfree (pi);
@@ -82,13 +103,13 @@ agent_key_from_file (const unsigned char *grip)
unsigned char *buf;
size_t len, buflen, erroff;
GCRY_SEXP s_skey;
- char hexgrip[41];
+ char hexgrip[40+4+1];
for (i=0; i < 20; i++)
sprintf (hexgrip+2*i, "%02X", grip[i]);
- hexgrip[40] = 0;
+ strcpy (hexgrip+40, ".key");
- fname = make_filename (opt.homedir, "private-keys-v1.d", hexgrip, NULL );
+ fname = make_filename (opt.homedir, "private-keys-v1.d", hexgrip, NULL);
fp = fopen (fname, "rb");
if (!fp)
{
@@ -138,16 +159,32 @@ agent_key_from_file (const unsigned char *grip)
assert (len);
gcry_sexp_release (s_skey);
- rc = unprotect (&buf);
+ switch (agent_private_key_type (buf))
+ {
+ case PRIVATE_KEY_CLEAR:
+ break; /* no unprotection needed */
+ case PRIVATE_KEY_PROTECTED:
+ rc = unprotect (&buf, grip);
+ if (rc)
+ log_error ("failed to unprotect the secret key: %s\n",
+ gnupg_strerror (rc));
+ break;
+ case PRIVATE_KEY_SHADOWED:
+ log_error ("shadowed private keys are not yet supported\n");
+ rc = GNUPG_Not_Implemented;
+ break;
+ default:
+ log_error ("invalid private key format\n");
+ rc = GNUPG_Bad_Secret_Key;
+ break;
+ }
if (rc)
{
- log_error ("failed to unprotect the secret key: %s\n",
- gcry_strerror (rc));
xfree (buf);
return NULL;
}
- /* arggg FIXME: does scna support secure memory? */
+ /* arggg FIXME: does scan support secure memory? */
rc = gcry_sexp_sscan (&s_skey, &erroff,
buf, gcry_sexp_canon_len (buf, 0, NULL, NULL));
xfree (buf);
@@ -168,13 +205,13 @@ agent_key_available (const unsigned char *grip)
{
int i;
char *fname;
- char hexgrip[41];
+ char hexgrip[40+4+1];
for (i=0; i < 20; i++)
sprintf (hexgrip+2*i, "%02X", grip[i]);
- hexgrip[40] = 0;
+ strcpy (hexgrip+40, ".key");
- fname = make_filename (opt.homedir, "private-keys-v1.d", hexgrip, NULL );
+ fname = make_filename (opt.homedir, "private-keys-v1.d", hexgrip, NULL);
i = !access (fname, R_OK)? 0 : -1;
xfree (fname);
return i;
diff --git a/agent/genkey.c b/agent/genkey.c
index 2119bbb44..1aca33b83 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -40,7 +40,7 @@ store_key (GCRY_SEXP private, const char *passphrase)
char *buf;
size_t len;
unsigned char grip[20];
- char hexgrip[41];
+ char hexgrip[40+4+1];
if ( !gcry_pk_get_keygrip (private, grip) )
{
@@ -49,7 +49,7 @@ store_key (GCRY_SEXP private, const char *passphrase)
}
for (i=0; i < 20; i++)
sprintf (hexgrip+2*i, "%02X", grip[i]);
- hexgrip[40] = 0;
+ strcpy (hexgrip+40, ".key");
fname = make_filename (opt.homedir, "private-keys-v1.d", hexgrip, NULL);
if (!access (fname, F_OK))
diff --git a/agent/protect.c b/agent/protect.c
index 6b95dabfa..115a94563 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -776,6 +776,33 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
return 0;
}
+/* Check the type of the private key, this is one of the constants:
+ PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
+ value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
+ PRIVATE_KEY_PROTECTED for an protected private key or
+ PRIVATE_KEY_SHADOWED for a sub key where the secret parts are store
+ elsewhere. */
+int
+agent_private_key_type (const unsigned char *privatekey)
+{
+ const unsigned char *s;
+ size_t n;
+
+ s = privatekey;
+ if (*s != '(')
+ return PRIVATE_KEY_UNKNOWN;
+ s++;
+ n = snext (&s);
+ if (!n)
+ return PRIVATE_KEY_UNKNOWN;
+ if (smatch (&s, n, "protected-private-key"))
+ return PRIVATE_KEY_PROTECTED;
+ if (smatch (&s, n, "shadowed-private-key"))
+ return PRIVATE_KEY_SHADOWED;
+ if (smatch (&s, n, "private-key"))
+ return PRIVATE_KEY_CLEAR;
+ return PRIVATE_KEY_UNKNOWN;
+}