aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--agent/agent.h3
-rw-r--r--agent/command-ssh.c32
-rw-r--r--agent/command.c69
-rw-r--r--agent/findkey.c36
-rw-r--r--agent/learncard.c30
5 files changed, 100 insertions, 70 deletions
diff --git a/agent/agent.h b/agent/agent.h
index fe5ffba12..a3ec45724 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -490,6 +490,9 @@ gpg_error_t s2k_hash_passphrase (const char *passphrase, int hashalgo,
const unsigned char *s2ksalt,
unsigned int s2kcount,
unsigned char *key, size_t keylen);
+gpg_error_t agent_write_shadow_key (const unsigned char *grip,
+ const char *serialno, const char *keyid,
+ const unsigned char *pkbuf, int force);
/*-- trustlist.c --*/
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 083b8d890..7bcda504c 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -2474,39 +2474,9 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
if ( agent_key_available (grip) )
{
/* (Shadow)-key is not available in our key storage. */
- unsigned char *shadow_info;
- unsigned char *tmp;
-
- shadow_info = make_shadow_info (serialno, authkeyid);
- if (!shadow_info)
- {
- err = gpg_error_from_syserror ();
- xfree (pkbuf);
- gcry_sexp_release (s_pk);
- xfree (serialno);
- xfree (authkeyid);
- return err;
- }
- err = agent_shadow_key (pkbuf, shadow_info, &tmp);
- xfree (shadow_info);
- if (err)
- {
- log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err));
- xfree (pkbuf);
- gcry_sexp_release (s_pk);
- xfree (serialno);
- xfree (authkeyid);
- return err;
- }
- xfree (pkbuf);
- pkbuf = tmp;
- pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
- assert (pkbuflen);
-
- err = agent_write_private_key (grip, pkbuf, pkbuflen, 0);
+ err = agent_write_shadow_key (grip, serialno, authkeyid, pkbuf, 0);
if (err)
{
- log_error (_("error writing key: %s\n"), gpg_strerror (err));
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
diff --git a/agent/command.c b/agent/command.c
index 1ecdf20cd..a291d5b68 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -988,8 +988,10 @@ cmd_genkey (assuan_context_t ctx, char *line)
static const char hlp_readkey[] =
"READKEY <hexstring_with_keygrip>\n"
+ " --card <keyid>\n"
"\n"
- "Return the public key for the given keygrip.";
+ "Return the public key for the given keygrip or keyid.\n"
+ "With --card, private key file with card information will be created.";
static gpg_error_t
cmd_readkey (assuan_context_t ctx, char *line)
{
@@ -997,10 +999,57 @@ cmd_readkey (assuan_context_t ctx, char *line)
int rc;
unsigned char grip[20];
gcry_sexp_t s_pkey = NULL;
+ unsigned char *pkbuf = NULL;
+ size_t pkbuflen;
if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
+ if (has_option_name (line, "--card"))
+ {
+ const char *keyid;
+ char *serialno = NULL;
+
+ keyid = skip_options (line);
+
+ rc = agent_card_getattr (ctrl, "SERIALNO", &serialno);
+ if (rc)
+ {
+ log_error (_("error getting serial number of card: %s\n"),
+ gpg_strerror (rc));
+ goto leave;
+ }
+
+ pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
+ rc = agent_card_readkey (ctrl, keyid, &pkbuf);
+ if (rc)
+ goto leave;
+ rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)pkbuf, pkbuflen);
+ if (rc)
+ goto leave;
+
+ if (!gcry_pk_get_keygrip (s_pkey, grip))
+ {
+ rc = gcry_pk_testkey (s_pkey);
+ if (rc == 0)
+ rc = gpg_error (GPG_ERR_INTERNAL);
+
+ goto leave;
+ }
+
+ rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0);
+ if (rc)
+ goto leave;
+
+ rc = assuan_send_data (ctx, pkbuf, pkbuflen);
+
+ leave:
+ xfree (serialno);
+ xfree (pkbuf);
+ gcry_sexp_release (s_pkey);
+ return leave_cmd (ctx, rc);
+ }
+
rc = parse_keygrip (ctx, line, grip);
if (rc)
return rc; /* Return immediately as this is already an Assuan error code.*/
@@ -1008,20 +1057,16 @@ cmd_readkey (assuan_context_t ctx, char *line)
rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
if (!rc)
{
- size_t len;
- unsigned char *buf;
-
- len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = xtrymalloc (len);
- if (!buf)
+ pkbuflen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
+ assert (pkbuflen);
+ pkbuf = xtrymalloc (pkbuflen);
+ if (!pkbuf)
rc = gpg_error_from_syserror ();
else
{
- len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
- rc = assuan_send_data (ctx, buf, len);
- xfree (buf);
+ gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, pkbuf, pkbuflen);
+ rc = assuan_send_data (ctx, pkbuf, pkbuflen);
+ xfree (pkbuf);
}
gcry_sexp_release (s_pkey);
}
diff --git a/agent/findkey.c b/agent/findkey.c
index c5ab0e905..23e94f0dd 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -1492,3 +1492,39 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
gcry_sexp_release (s_skey);
return err;
}
+
+
+/* Write an S-expression formatted shadow key to our key storage.
+ Shadow key is created by an S-expression public key in PKBUF and
+ card's SERIALNO and the IDSTRING. With FORCE passed as true an
+ existing key with the given GRIP will get overwritten. */
+gpg_error_t
+agent_write_shadow_key (const unsigned char *grip,
+ const char *serialno, const char *keyid,
+ const unsigned char *pkbuf, int force)
+{
+ gpg_error_t err;
+ unsigned char *shadow_info;
+ unsigned char *shdkey;
+ size_t len;
+
+ shadow_info = make_shadow_info (serialno, keyid);
+ if (!shadow_info)
+ return gpg_error_from_syserror ();
+
+ err = agent_shadow_key (pkbuf, shadow_info, &shdkey);
+ xfree (shadow_info);
+ if (err)
+ {
+ log_error ("shadowing the key failed: %s\n", gpg_strerror (err));
+ return err;
+ }
+
+ len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
+ err = agent_write_private_key (grip, shdkey, len, force);
+ xfree (shdkey);
+ if (err)
+ log_error ("error writing key: %s\n", gpg_strerror (err));
+
+ return err;
+}
diff --git a/agent/learncard.c b/agent/learncard.c
index e9304fb8b..103a82163 100644
--- a/agent/learncard.c
+++ b/agent/learncard.c
@@ -381,8 +381,7 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
for (item = parm.info; item; item = item->next)
{
- unsigned char *pubkey, *shdkey;
- size_t n;
+ unsigned char *pubkey;
if (opt.verbose)
log_info (" id: %s (grip=%s)\n", item->id, item->hexgrip);
@@ -410,33 +409,10 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
goto leave;
}
- {
- unsigned char *shadow_info = make_shadow_info (serialno, item->id);
- if (!shadow_info)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- xfree (pubkey);
- goto leave;
- }
- rc = agent_shadow_key (pubkey, shadow_info, &shdkey);
- xfree (shadow_info);
- }
+ rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, force);
xfree (pubkey);
if (rc)
- {
- log_error ("shadowing the key failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- n = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
- assert (n);
-
- rc = agent_write_private_key (grip, shdkey, n, force);
- xfree (shdkey);
- if (rc)
- {
- log_error ("error writing key: %s\n", gpg_strerror (rc));
- goto leave;
- }
+ goto leave;
if (opt.verbose)
log_info (" id: %s - shadow key created\n", item->id);