diff options
author | NIIBE Yutaka <[email protected]> | 2023-03-10 06:39:14 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2023-03-10 06:39:14 +0000 |
commit | d0855b120445ecb4fe0c8c0c56011b85fe9ab296 (patch) | |
tree | ec0f0331ebb6ebb780ca195b07054524d0d73727 | |
parent | agent: Add divert to tkdaemon. (diff) | |
download | gnupg-d0855b120445ecb4fe0c8c0c56011b85fe9ab296.tar.gz gnupg-d0855b120445ecb4fe0c8c0c56011b85fe9ab296.zip |
agent: Call TKDaemon READKEY command.
Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r-- | agent/agent.h | 4 | ||||
-rw-r--r-- | agent/call-tkd.c | 48 | ||||
-rw-r--r-- | agent/command.c | 32 | ||||
-rw-r--r-- | agent/findkey.c | 26 | ||||
-rw-r--r-- | agent/keyformat.txt | 12 | ||||
-rw-r--r-- | agent/protect.c | 17 |
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 |