mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
agent: Add --card option for READKEY.
* agent/findkey.c (agent_write_shadow_key): New. * agent/command-ssh.c (card_key_available): Use agent_write_shadow_key. * agent/learncard.c (agent_handle_learn): Likewise. * agent/command.c (cmd_readkey): Add --card option. -- Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
72a99f582d
commit
82cbab906a
@ -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 --*/
|
||||
|
@ -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);
|
||||
err = agent_write_shadow_key (grip, serialno, authkeyid, pkbuf, 0);
|
||||
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);
|
||||
if (err)
|
||||
{
|
||||
log_error (_("error writing key: %s\n"), gpg_strerror (err));
|
||||
xfree (pkbuf);
|
||||
gcry_sexp_release (s_pk);
|
||||
xfree (serialno);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
if (opt.verbose)
|
||||
log_info (" id: %s - shadow key created\n", item->id);
|
||||
|
Loading…
x
Reference in New Issue
Block a user