mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
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 <wk@gnupg.org>
This commit is contained in:
parent
57b8ed61ab
commit
ce5a7fb72b
4 changed files with 150 additions and 114 deletions
111
agent/call-scd.c
111
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)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue