1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-06-12 18:11:03 +02:00

agent: Call TKDaemon READKEY command.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2023-03-10 15:39:14 +09:00
parent 08ef809c5e
commit d0855b1204
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
6 changed files with 116 additions and 21 deletions

View File

@ -748,8 +748,8 @@ int agent_tkd_pksign (ctrl_t ctrl,
const char *keygrip, const char *keygrip,
const unsigned char *indata, size_t indatalen, const unsigned char *indata, size_t indatalen,
unsigned char **r_buf, size_t *r_buflen); unsigned char **r_buf, size_t *r_buflen);
int agent_tkd_readkey (ctrl_t ctrl, const char *id, int agent_tkd_readkey (ctrl_t ctrl, const char *keygrip,
unsigned char **r_buf, char **r_keyref); unsigned char **r_buf, size_t *r_buflen);
/*-- learncard.c --*/ /*-- learncard.c --*/
int agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force); int agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force);

View File

@ -128,6 +128,52 @@ pin_cb (ctrl_t ctrl, const char *prompt, char **passphrase)
hexgrip, CACHE_MODE_USER, NULL); hexgrip, CACHE_MODE_USER, NULL);
} }
/* Read a key with KEYGRIP and return it in a malloced buffer pointed
* to by R_BUF as a valid S-expression. If R_BUFLEN is not NULL the
* length is stored there. */
int
agent_tkd_readkey (ctrl_t ctrl, const char *keygrip,
unsigned char **r_buf, size_t *r_buflen)
{
int rc;
char line[ASSUAN_LINELENGTH];
membuf_t data;
size_t buflen;
*r_buf = NULL;
if (r_buflen)
*r_buflen = 0;
rc = start_tkd (ctrl);
if (rc)
return rc;
init_membuf (&data, 1024);
snprintf (line, DIM(line), "READKEY %s", keygrip);
rc = assuan_transact (daemon_ctx (ctrl), line,
put_membuf_cb, &data,
NULL, NULL, NULL, NULL);
if (rc)
{
xfree (get_membuf (&data, &buflen));
return unlock_tkd (ctrl, rc);
}
*r_buf = get_membuf (&data, &buflen);
if (!*r_buf)
return unlock_tkd (ctrl, gpg_error (GPG_ERR_ENOMEM));
if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
{
xfree (*r_buf); *r_buf = NULL;
return unlock_tkd (ctrl, gpg_error (GPG_ERR_INV_VALUE));
}
if (r_buflen)
*r_buflen = buflen;
return unlock_tkd (ctrl, 0);
}
int int
agent_tkd_pksign (ctrl_t ctrl, const char *keygrip, agent_tkd_pksign (ctrl_t ctrl, const char *keygrip,
const unsigned char *digest, size_t digestlen, const unsigned char *digest, size_t digestlen,
@ -154,7 +200,7 @@ agent_tkd_pksign (ctrl_t ctrl, const char *keygrip,
inqparm.extralen = digestlen; inqparm.extralen = digestlen;
inqparm.pin = NULL; inqparm.pin = NULL;
snprintf(line, sizeof(line), "PKSIGN"); snprintf (line, sizeof(line), "PKSIGN %s", keygrip);
rc = assuan_transact (daemon_ctx (ctrl), line, rc = assuan_transact (daemon_ctx (ctrl), line,
put_membuf_cb, &data, put_membuf_cb, &data,

View File

@ -1303,6 +1303,7 @@ cmd_keyattr (assuan_context_t ctx, char *line)
static const char hlp_readkey[] = static const char hlp_readkey[] =
"READKEY [--no-data] [--format=ssh] <hexstring_with_keygrip>\n" "READKEY [--no-data] [--format=ssh] <hexstring_with_keygrip>\n"
" --card <keyid>\n" " --card <keyid>\n"
" --token <hexstring_with_keygrip>\n"
"\n" "\n"
"Return the public key for the given keygrip or keyid.\n" "Return the public key for the given keygrip or keyid.\n"
"With --card, private key file with card information will be created."; "With --card, private key file with card information will be created.";
@ -1315,13 +1316,14 @@ cmd_readkey (assuan_context_t ctx, char *line)
gcry_sexp_t s_pkey = NULL; gcry_sexp_t s_pkey = NULL;
unsigned char *pkbuf = NULL; unsigned char *pkbuf = NULL;
size_t pkbuflen; size_t pkbuflen;
int opt_card, opt_no_data, opt_format_ssh; int opt_card, opt_token, opt_no_data, opt_format_ssh;
if (ctrl->restricted) if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
opt_no_data = has_option (line, "--no-data"); opt_no_data = has_option (line, "--no-data");
opt_card = has_option (line, "--card"); opt_card = has_option (line, "--card");
opt_token = has_option (line, "--token");
opt_format_ssh = has_option (line, "--format=ssh"); opt_format_ssh = has_option (line, "--format=ssh");
line = skip_options (line); line = skip_options (line);
@ -1373,6 +1375,34 @@ cmd_readkey (assuan_context_t ctx, char *line)
xfree (serialno); xfree (serialno);
xfree (keyidbuf); xfree (keyidbuf);
} }
else if (opt_token)
{
const char *keygrip = line;
rc = agent_tkd_readkey (ctrl, keygrip, &pkbuf, &pkbuflen);
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;
}
if (agent_key_available (grip))
{
/* (Shadow)-key is not available in our key storage. */
rc = agent_write_shadow_key (grip, NULL, NULL, pkbuf, 0);
if (rc)
goto leave;
}
}
else else
{ {
rc = parse_keygrip (ctx, line, grip); rc = parse_keygrip (ctx, line, grip);

View File

@ -1821,16 +1821,22 @@ agent_write_shadow_key (const unsigned char *grip,
unsigned char *shdkey; unsigned char *shdkey;
size_t len; size_t len;
/* Just in case some caller did not parse the stuff correctly, skip if (serialno == NULL && keyid == NULL)
* leading spaces. */ /* It's a token, identified by the keygrip. */
while (spacep (serialno)) shadow_info = NULL;
serialno++; else
while (spacep (keyid)) {
keyid++; /* Just in case some caller did not parse the stuff correctly, skip
* leading spaces. */
while (spacep (serialno))
serialno++;
while (spacep (keyid))
keyid++;
shadow_info = make_shadow_info (serialno, keyid); shadow_info = make_shadow_info (serialno, keyid);
if (!shadow_info) if (!shadow_info)
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
}
err = agent_shadow_key (pkbuf, shadow_info, &shdkey); err = agent_shadow_key (pkbuf, shadow_info, &shdkey);
xfree (shadow_info); xfree (shadow_info);

View File

@ -342,9 +342,11 @@ to keys stored on a token:
(comment whatever) (comment whatever)
) )
The currently used protocols are "t1-v1" (token info version 1) and The currently used protocols are "t1-v1" (token info version 1),
"tpm2-v1" (TPM format key information). The second list with the "tpm2-v1" (TPM format key information), and "tkd-v1" (token daemon
information has this layout for "t1-v1": info version 1).
The second list with the information has this layout for "t1-v1":
(card_serial_number id_string_of_key fixed_pin_length) (card_serial_number id_string_of_key fixed_pin_length)
@ -353,13 +355,15 @@ the PIN; a value of 0 indicates that this information is not
available. The rationale for this field is that some pinpad equipped available. The rationale for this field is that some pinpad equipped
readers don't allow passing a variable length PIN. readers don't allow passing a variable length PIN.
This is the (info) layout for "tpm2-v1": For "tpm2-v1", the layout of the (info) is:
(parent tpm_private_string tpm_public_string) (parent tpm_private_string tpm_public_string)
Although this precise format is encapsulated inside the tpm2daemon Although this precise format is encapsulated inside the tpm2daemon
itself and nothing in gpg ever uses this. itself and nothing in gpg ever uses this.
For "tkd-v1", the layout of the (info) part is nothing.
More items may be added to the list. More items may be added to the list.
** OpenPGP Private Key Transfer Format ** OpenPGP Private Key Transfer Format

View File

@ -1545,10 +1545,15 @@ agent_shadow_key_type (const unsigned char *pubkey,
int depth = 0; int depth = 0;
char *p; char *p;
size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL); size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL); size_t shadow_info_len;
if (!pubkey_len || !shadow_info_len) if (!pubkey_len)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (shadow_info)
shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
else
shadow_info_len = 0;
s = pubkey; s = pubkey;
if (*s != '(') if (*s != '(')
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
@ -1604,7 +1609,8 @@ agent_shadow_key_type (const unsigned char *pubkey,
memcpy (p, pubkey+14, point - (pubkey+14)); memcpy (p, pubkey+14, point - (pubkey+14));
p += point - (pubkey+14); p += point - (pubkey+14);
p += sprintf (p, "(8:shadowed%d:%s", (int)strlen(type), type); p += sprintf (p, "(8:shadowed%d:%s", (int)strlen(type), type);
memcpy (p, shadow_info, shadow_info_len); if (shadow_info_len)
memcpy (p, shadow_info, shadow_info_len);
p += shadow_info_len; p += shadow_info_len;
*p++ = ')'; *p++ = ')';
memcpy (p, point, pubkey_len - (point - pubkey)); memcpy (p, point, pubkey_len - (point - pubkey));
@ -1618,7 +1624,10 @@ agent_shadow_key (const unsigned char *pubkey,
const unsigned char *shadow_info, const unsigned char *shadow_info,
unsigned char **result) unsigned char **result)
{ {
return agent_shadow_key_type (pubkey, shadow_info, "t1-v1", result); if (shadow_info)
return agent_shadow_key_type (pubkey, shadow_info, "t1-v1", result);
else
return agent_shadow_key_type (pubkey, NULL, "tkd-v1", result);
} }
/* Parse a canonical encoded shadowed key and return a pointer to the /* Parse a canonical encoded shadowed key and return a pointer to the