aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2023-03-10 06:39:14 +0000
committerNIIBE Yutaka <[email protected]>2023-03-10 06:39:14 +0000
commitd0855b120445ecb4fe0c8c0c56011b85fe9ab296 (patch)
treeec0f0331ebb6ebb780ca195b07054524d0d73727
parentagent: Add divert to tkdaemon. (diff)
downloadgnupg-d0855b120445ecb4fe0c8c0c56011b85fe9ab296.tar.gz
gnupg-d0855b120445ecb4fe0c8c0c56011b85fe9ab296.zip
agent: Call TKDaemon READKEY command.
Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--agent/agent.h4
-rw-r--r--agent/call-tkd.c48
-rw-r--r--agent/command.c32
-rw-r--r--agent/findkey.c26
-rw-r--r--agent/keyformat.txt12
-rw-r--r--agent/protect.c17
6 files changed, 117 insertions, 22 deletions
diff --git a/agent/agent.h b/agent/agent.h
index eeb970b7b..5ab710f1d 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -748,8 +748,8 @@ int agent_tkd_pksign (ctrl_t ctrl,
const char *keygrip,
const unsigned char *indata, size_t indatalen,
unsigned char **r_buf, size_t *r_buflen);
-int agent_tkd_readkey (ctrl_t ctrl, const char *id,
- unsigned char **r_buf, char **r_keyref);
+int agent_tkd_readkey (ctrl_t ctrl, const char *keygrip,
+ unsigned char **r_buf, size_t *r_buflen);
/*-- learncard.c --*/
int agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force);
diff --git a/agent/call-tkd.c b/agent/call-tkd.c
index 00c84c704..cbcfcd0dd 100644
--- a/agent/call-tkd.c
+++ b/agent/call-tkd.c
@@ -128,6 +128,52 @@ pin_cb (ctrl_t ctrl, const char *prompt, char **passphrase)
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
agent_tkd_pksign (ctrl_t ctrl, const char *keygrip,
const unsigned char *digest, size_t digestlen,
@@ -154,7 +200,7 @@ agent_tkd_pksign (ctrl_t ctrl, const char *keygrip,
inqparm.extralen = digestlen;
inqparm.pin = NULL;
- snprintf(line, sizeof(line), "PKSIGN");
+ snprintf (line, sizeof(line), "PKSIGN %s", keygrip);
rc = assuan_transact (daemon_ctx (ctrl), line,
put_membuf_cb, &data,
diff --git a/agent/command.c b/agent/command.c
index c113caba7..1dc77b43e 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -1303,6 +1303,7 @@ cmd_keyattr (assuan_context_t ctx, char *line)
static const char hlp_readkey[] =
"READKEY [--no-data] [--format=ssh] <hexstring_with_keygrip>\n"
" --card <keyid>\n"
+ " --token <hexstring_with_keygrip>\n"
"\n"
"Return the public key for the given keygrip or keyid.\n"
"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;
unsigned char *pkbuf = NULL;
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)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
opt_no_data = has_option (line, "--no-data");
opt_card = has_option (line, "--card");
+ opt_token = has_option (line, "--token");
opt_format_ssh = has_option (line, "--format=ssh");
line = skip_options (line);
@@ -1373,6 +1375,34 @@ cmd_readkey (assuan_context_t ctx, char *line)
xfree (serialno);
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
{
rc = parse_keygrip (ctx, line, grip);
diff --git a/agent/findkey.c b/agent/findkey.c
index d3a3b335c..27881f380 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -1821,16 +1821,22 @@ agent_write_shadow_key (const unsigned char *grip,
unsigned char *shdkey;
size_t len;
- /* 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);
- if (!shadow_info)
- return gpg_error_from_syserror ();
+ if (serialno == NULL && keyid == NULL)
+ /* It's a token, identified by the keygrip. */
+ shadow_info = NULL;
+ else
+ {
+ /* 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);
+ if (!shadow_info)
+ return gpg_error_from_syserror ();
+ }
err = agent_shadow_key (pkbuf, shadow_info, &shdkey);
xfree (shadow_info);
diff --git a/agent/keyformat.txt b/agent/keyformat.txt
index bbcaa7e2c..b8b814f88 100644
--- a/agent/keyformat.txt
+++ b/agent/keyformat.txt
@@ -342,9 +342,11 @@ to keys stored on a token:
(comment whatever)
)
-The currently used protocols are "t1-v1" (token info version 1) and
-"tpm2-v1" (TPM format key information). The second list with the
-information has this layout for "t1-v1":
+The currently used protocols are "t1-v1" (token info version 1),
+"tpm2-v1" (TPM format key information), and "tkd-v1" (token daemon
+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)
@@ -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
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)
Although this precise format is encapsulated inside the tpm2daemon
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.
** OpenPGP Private Key Transfer Format
diff --git a/agent/protect.c b/agent/protect.c
index 1084ee208..b92b015df 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -1545,10 +1545,15 @@ agent_shadow_key_type (const unsigned char *pubkey,
int depth = 0;
char *p;
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);
+ if (shadow_info)
+ shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
+ else
+ shadow_info_len = 0;
+
s = pubkey;
if (*s != '(')
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));
p += point - (pubkey+14);
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++ = ')';
memcpy (p, point, pubkey_len - (point - pubkey));
@@ -1618,7 +1624,10 @@ agent_shadow_key (const unsigned char *pubkey,
const unsigned char *shadow_info,
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