aboutsummaryrefslogtreecommitdiffstats
path: root/agent/call-scd.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-01-09 11:00:50 +0000
committerWerner Koch <[email protected]>2020-01-09 11:00:50 +0000
commitce5a7fb72b599de592a087867768ac1f81fd2989 (patch)
treec3d6898129d91e641966249e61edbe575416cad5 /agent/call-scd.c
parentagent: SSH: SCD KEYINFO to list available keys. (diff)
downloadgnupg-ce5a7fb72b599de592a087867768ac1f81fd2989.tar.gz
gnupg-ce5a7fb72b599de592a087867768ac1f81fd2989.zip
scd: Use a scdaemon internal key to protect the PIN cache IPC.
* agent/call-scd.c (handle_pincache_put): Do not decrypt. (handle_pincache_get): New. (inq_needpin): Call it. * scd/command.c (set_key_for_pincache): New. (pincache_put): Restructure and set key. (pincache_get): Ditto. -- This change does away with encrypting and decrypting the cached PIN in the agent. There is no need for this we can simply cache the cryptogram and let scdaemon decrypt after retrieving it from the agent. This way we do not need to share a key between gpg-agent and scdaemon and further the cached content is invalid after the scdaemon process has been replaced. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'agent/call-scd.c')
-rw-r--r--agent/call-scd.c111
1 files changed, 47 insertions, 64 deletions
diff --git a/agent/call-scd.c b/agent/call-scd.c
index d10bde835..cacf1f483 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -637,13 +637,9 @@ static gpg_error_t
handle_pincache_put (const char *args)
{
gpg_error_t err;
- const char *s, *key, *hexwrappedpin;
+ const char *s, *key, *pin;
char *keybuf = NULL;
- unsigned char *wrappedpin = NULL;
- size_t keylen, hexwrappedpinlen, wrappedpinlen;
- char *value = NULL;
- size_t valuelen;
- gcry_cipher_hd_t cipherhd = NULL;
+ size_t keylen;
key = s = args;
while (*s && !spacep (s))
@@ -657,7 +653,6 @@ handle_pincache_put (const char *args)
goto leave;
}
-
keybuf = xtrymalloc (keylen+1);
if (!keybuf)
{
@@ -670,70 +665,23 @@ handle_pincache_put (const char *args)
while (spacep (s))
s++;
- hexwrappedpin = s;
- while (*s && !spacep (s))
- s++;
- hexwrappedpinlen = s - hexwrappedpin;
- if (!hexwrappedpinlen)
+ pin = s;
+ if (!*pin)
{
- /* Flush the cache. The cache module knows aboput the structure
- * of the key to flush only parts. */
+ /* No value - flush the cache. The cache module knows aboput
+ * the structure of the key to flush only parts. */
log_debug ("%s: flushing cache '%s'\n", __func__, key);
agent_put_cache (NULL, key, CACHE_MODE_PIN, NULL, -1);
err = 0;
goto leave;
}
- if (hexwrappedpinlen < 2*24)
- {
- log_error ("%s: ignoring request with too short cryptogram\n", __func__);
- err = 0;
- goto leave;
- }
- wrappedpinlen = hexwrappedpinlen / 2;
- wrappedpin = xtrymalloc (wrappedpinlen);
- if (!wrappedpin)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
- if (hex2bin (hexwrappedpin, wrappedpin, wrappedpinlen) == -1)
- {
- log_error ("%s: invalid hex length\n", __func__);
- err = gpg_error (GPG_ERR_INV_LENGTH);
- goto leave;
- }
-
- valuelen = wrappedpinlen - 8;
- value = xtrymalloc_secure (valuelen+1);
- if (!value)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
-
- err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
- GCRY_CIPHER_MODE_AESWRAP, 0);
- if (!err)
- err = gcry_cipher_setkey (cipherhd, "1234567890123456", 16);
- if (!err)
- err = gcry_cipher_decrypt (cipherhd, value, valuelen,
- wrappedpin, wrappedpinlen);
- if (err)
- {
- log_error ("%s: error decrypting the cryptogram: %s\n",
- __func__, gpg_strerror (err));
- goto leave;
- }
-
- log_debug ("%s: caching '%s'->'%s'\n", __func__, key, value);
- agent_put_cache (NULL, key, CACHE_MODE_PIN, value, -1);
+ log_debug ("%s: caching '%s'->'%s'\n", __func__, key, pin);
+ agent_put_cache (NULL, key, CACHE_MODE_PIN, pin, -1);
+ err = 0;
leave:
xfree (keybuf);
- xfree (value);
- xfree (wrappedpin);
- gcry_cipher_close (cipherhd);
return err;
}
@@ -754,6 +702,43 @@ pincache_put_cb (void *opaque, const char *line)
}
+/* Handle a PINCACHE_GET inquiry. ARGS are the arguments of the
+ * inquiry which should be a single string with the key for the cached
+ * value. CTX is the Assuan handle. */
+static gpg_error_t
+handle_pincache_get (const char *args, assuan_context_t ctx)
+{
+ gpg_error_t err;
+ const char *key;
+ char *pin = NULL;
+
+ log_debug ("%s: enter '%s'\n", __func__, args);
+ key = args;
+ if (strlen (key) < 5)
+ {
+ /* We need at least 2 slashes, one slot number and two 1 byte strings.*/
+ err = gpg_error (GPG_ERR_INV_REQUEST);
+ log_debug ("%s: key too short\n", __func__);
+ goto leave;
+ }
+
+ pin = agent_get_cache (NULL, key, CACHE_MODE_PIN);
+ if (!pin || !*pin)
+ {
+ xfree (pin);
+ err = 0; /* Not found is indicated by sending no data back. */
+ log_debug ("%s: not cached\n", __func__);
+ goto leave;
+ }
+ log_debug ("%s: cache returned '%s'\n", __func__, pin);
+ err = assuan_send_data (ctx, pin, strlen (pin));
+
+ leave:
+ xfree (pin);
+ return err;
+}
+
+
static gpg_error_t
learn_status_cb (void *opaque, const char *line)
@@ -924,9 +909,7 @@ inq_needpin (void *opaque, const char *line)
}
else if ((s = has_leading_keyword (line, "PINCACHE_GET")))
{
- /* rc = parm->getpin_cb (parm->getpin_cb_arg, parm->getpin_cb_desc, */
- /* "", NULL, 0); */
- rc = 0;
+ rc = handle_pincache_get (s, parm->ctx);
}
else if (parm->passthru)
{