diff options
Diffstat (limited to 'agent')
-rw-r--r-- | agent/Makefile.am | 2 | ||||
-rw-r--r-- | agent/agent.h | 13 | ||||
-rw-r--r-- | agent/call-tkd.c | 370 | ||||
-rw-r--r-- | agent/command.c | 80 | ||||
-rw-r--r-- | agent/divert-tkd.c | 45 | ||||
-rw-r--r-- | agent/findkey.c | 66 | ||||
-rw-r--r-- | agent/gpg-agent.c | 6 | ||||
-rw-r--r-- | agent/keyformat.txt | 12 | ||||
-rw-r--r-- | agent/pksign.c | 4 | ||||
-rw-r--r-- | agent/protect.c | 22 |
10 files changed, 586 insertions, 34 deletions
diff --git a/agent/Makefile.am b/agent/Makefile.am index 4da1ea9d8..587aa7ae8 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -56,8 +56,10 @@ gpg_agent_SOURCES = \ protect.c \ trustlist.c \ divert-scd.c \ + divert-tkd.c \ cvt-openpgp.c cvt-openpgp.h \ call-scd.c \ + call-tkd.c \ call-daemon.c \ $(tpm2_sources) \ learncard.c diff --git a/agent/agent.h b/agent/agent.h index 4e7452eee..54076223d 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -60,6 +60,7 @@ enum daemon_type { DAEMON_SCD, + DAEMON_TKD, DAEMON_TPM2D, DAEMON_MAX_TYPE }; @@ -660,6 +661,11 @@ int divert_generic_cmd (ctrl_t ctrl, gpg_error_t divert_writekey (ctrl_t ctrl, int force, const char *serialno, const char *keyref, const char *keydata, size_t keydatalen); +/*-- divert-tkd.c --*/ +int divert_tkd_pksign (ctrl_t ctrl, + const unsigned char *digest, size_t digestlen, + unsigned char **r_sig, size_t *r_siglen); +int divert_tkd_cmd (ctrl_t ctrl, const char *cmdline); /*-- call-daemon.c --*/ gpg_error_t daemon_start (enum daemon_type type, ctrl_t ctrl); @@ -730,6 +736,13 @@ void agent_card_free_keyinfo (struct card_key_info_s *l); gpg_error_t agent_card_keyinfo (ctrl_t ctrl, const char *keygrip, int cap, struct card_key_info_s **result); +/*-- call-tkd.c --*/ +int agent_tkd_pksign (ctrl_t ctrl, + const unsigned char *indata, size_t indatalen, + unsigned char **r_buf, size_t *r_buflen); +int agent_tkd_readkey (ctrl_t ctrl, const char *keygrip, + unsigned char **r_buf, size_t *r_buflen); +int agent_tkd_cmd (ctrl_t ctrl, const char *cmdline); /*-- 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 new file mode 100644 index 000000000..e0c85e9eb --- /dev/null +++ b/agent/call-tkd.c @@ -0,0 +1,370 @@ +/* call-tkd.c - fork of the tkdaemon to do TK operations + * Copyright (C) 2001, 2002, 2005, 2007, 2010, + * 2011 Free Software Foundation, Inc. + * Copyright (C) 2013 Werner Koch + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> + +#include "agent.h" +#include <assuan.h> +#include "../common/strlist.h" +#include "../common/sexp-parse.h" +#include "../common/i18n.h" + +static int +start_tkd (ctrl_t ctrl) +{ + return daemon_start (DAEMON_TKD, ctrl); +} + +static int +unlock_tkd (ctrl_t ctrl, gpg_error_t err) +{ + return daemon_unlock (DAEMON_TKD, ctrl, err); +} + +static assuan_context_t +daemon_ctx (ctrl_t ctrl) +{ + return daemon_type_ctx (DAEMON_TKD, ctrl); +} + +struct inq_parm_s { + assuan_context_t ctx; + gpg_error_t (*getpin_cb)(ctrl_t, const char *, char **); + ctrl_t ctrl; + /* The next fields are used by inq_keydata. */ + const unsigned char *keydata; + size_t keydatalen; + /* following only used by inq_extra */ + const unsigned char *extra; + size_t extralen; + char *pin; +}; + +static gpg_error_t +inq_needpin (void *opaque, const char *line) +{ + struct inq_parm_s *parm = opaque; + char *pin = NULL; + gpg_error_t rc; + const char *s; + + if ((s = has_leading_keyword (line, "NEEDPIN"))) + { + rc = parm->getpin_cb (parm->ctrl, s, &pin); + if (!rc) + rc = assuan_send_data (parm->ctx, pin, strlen(pin)); + parm->pin = pin; + } + else + { + log_error ("unsupported inquiry '%s'\n", line); + rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE); + } + + return rc; +} + +static gpg_error_t +inq_extra (void *opaque, const char *line) +{ + struct inq_parm_s *parm = opaque; + + if (has_leading_keyword (line, "EXTRA")) + return assuan_send_data (parm->ctx, parm->extra, parm->extralen); + else + return inq_needpin (opaque, line); +} + +static gpg_error_t +pin_cb (ctrl_t ctrl, const char *prompt, char **passphrase) +{ + char hexgrip[2*KEYGRIP_LEN + 1]; + + bin2hex (ctrl->keygrip, KEYGRIP_LEN, hexgrip); + *passphrase = agent_get_cache (ctrl, hexgrip, CACHE_MODE_USER); + if (*passphrase) + return 0; + return agent_get_passphrase (ctrl, passphrase, + _("Please enter your passphrase, so that the " + "secret key can be unlocked for this session"), + prompt, NULL, 0, + 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; + struct inq_parm_s inqparm; + + *r_buf = NULL; + if (r_buflen) + *r_buflen = 0; + + rc = start_tkd (ctrl); + if (rc) + return rc; + + init_membuf (&data, 1024); + + inqparm.ctx = daemon_ctx (ctrl); + inqparm.getpin_cb = pin_cb; + inqparm.ctrl = ctrl; + inqparm.pin = NULL; + + snprintf (line, DIM(line), "READKEY %s", keygrip); + rc = assuan_transact (daemon_ctx (ctrl), line, + put_membuf_cb, &data, + inq_needpin, &inqparm, + 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); +} + + +/* Helper returning a command option to describe the used hash + algorithm. See scd/command.c:cmd_pksign. */ +static const char * +hash_algo_option (int algo) +{ + switch (algo) + { + case GCRY_MD_MD5 : return "--hash=md5"; + case GCRY_MD_RMD160: return "--hash=rmd160"; + case GCRY_MD_SHA1 : return "--hash=sha1"; + case GCRY_MD_SHA224: return "--hash=sha224"; + case GCRY_MD_SHA256: return "--hash=sha256"; + case GCRY_MD_SHA384: return "--hash=sha384"; + case GCRY_MD_SHA512: return "--hash=sha512"; + default: return ""; + } +} + + +int +agent_tkd_pksign (ctrl_t ctrl, const unsigned char *digest, size_t digestlen, + unsigned char **r_sig, size_t *r_siglen) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + membuf_t data; + struct inq_parm_s inqparm; + char hexgrip[2*KEYGRIP_LEN + 1]; + + rc = start_tkd (ctrl); + if (rc) + return rc; + + init_membuf (&data, 1024); + + inqparm.ctx = daemon_ctx (ctrl); + inqparm.getpin_cb = pin_cb; + inqparm.pin = NULL; + inqparm.ctrl = ctrl; + inqparm.extra = digest; + inqparm.extralen = digestlen; + + bin2hex (ctrl->keygrip, KEYGRIP_LEN, hexgrip); + snprintf (line, sizeof(line), "PKSIGN %s %s", + hash_algo_option (ctrl->digest.algo), hexgrip); + + rc = assuan_transact (daemon_ctx (ctrl), line, + put_membuf_cb, &data, + inq_extra, &inqparm, + NULL, NULL); + if (!rc) + { + bin2hex (ctrl->keygrip, KEYGRIP_LEN, hexgrip); + agent_put_cache (ctrl, hexgrip, CACHE_MODE_USER, inqparm.pin, 0); + } + + xfree (inqparm.pin); + + if (rc) + { + size_t len; + xfree (get_membuf (&data, &len)); + return unlock_tkd (ctrl, rc); + } + + *r_sig = get_membuf (&data, r_siglen); + + return unlock_tkd (ctrl, 0); +} + +/* This handler is a helper for pincache_put_cb but may also be called + * directly for that status code with ARGS being the arguments after + * the status keyword (and with white space removed). */ +static gpg_error_t +handle_pincache_put (const char *args) +{ + gpg_error_t err; + const char *s, *key, *pin; + char *keybuf = NULL; + size_t keylen; + + key = s = args; + while (*s && !spacep (s)) + s++; + keylen = s - key; + if (keylen < 3) + { + /* At least we need 2 slashes and slot number. */ + log_error ("%s: ignoring invalid key\n", __func__); + err = 0; + goto leave; + } + + keybuf = xtrymalloc (keylen+1); + if (!keybuf) + { + err = gpg_error_from_syserror (); + goto leave; + } + memcpy (keybuf, key, keylen); + keybuf[keylen] = 0; + key = keybuf; + + while (spacep (s)) + s++; + pin = s; + if (!*pin) + { + /* No value - flush the cache. The cache module knows aboput + * the structure of the key to flush only parts. */ + log_debug ("%s: flushing cache '%s'\n", __func__, key); + agent_put_cache (NULL, key, CACHE_MODE_PIN, NULL, -1); + err = 0; + goto leave; + } + + log_debug ("%s: caching '%s'->'%s'\n", __func__, key, pin); + agent_put_cache (NULL, key, CACHE_MODE_PIN, pin, -1); + err = 0; + + leave: + xfree (keybuf); + return err; +} + +static gpg_error_t +pass_status_thru (void *opaque, const char *line) +{ + gpg_error_t err = 0; + assuan_context_t ctx = opaque; + char keyword[200]; + int i; + + if (line[0] == '#' && (!line[1] || spacep (line+1))) + { + /* We are called in convey comments mode. Now, if we see a + comment marker as keyword we forward the line verbatim to the + the caller. This way the comment lines from scdaemon won't + appear as status lines with keyword '#'. */ + assuan_write_line (ctx, line); + } + else + { + for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++) + keyword[i] = *line; + keyword[i] = 0; + + /* Truncate any remaining keyword stuff. */ + for (; *line && !spacep (line); line++) + ; + while (spacep (line)) + line++; + + /* We do not want to pass PINCACHE_PUT through. */ + if (!strcmp (keyword, "PINCACHE_PUT")) + err = handle_pincache_put (line); + else + assuan_write_status (ctx, keyword, line); + } + return err; +} + +static gpg_error_t +pass_data_thru (void *opaque, const void *buffer, size_t length) +{ + assuan_context_t ctx = opaque; + + assuan_send_data (ctx, buffer, length); + return 0; +} + +int +agent_tkd_cmd (ctrl_t ctrl, const char *cmdline) +{ + int rc; + struct inq_parm_s inqparm; + int saveflag; + + rc = start_tkd (ctrl); + if (rc) + return rc; + + inqparm.ctx = daemon_ctx (ctrl); + inqparm.getpin_cb = pin_cb; + inqparm.pin = NULL; + + saveflag = assuan_get_flag (daemon_ctx (ctrl), ASSUAN_CONVEY_COMMENTS); + assuan_set_flag (daemon_ctx (ctrl), ASSUAN_CONVEY_COMMENTS, 1); + rc = assuan_transact (daemon_ctx (ctrl), cmdline, + pass_data_thru, daemon_ctx (ctrl), + inq_needpin, &inqparm, + pass_status_thru, daemon_ctx (ctrl)); + + assuan_set_flag (daemon_ctx (ctrl), ASSUAN_CONVEY_COMMENTS, saveflag); + + return unlock_tkd (ctrl, rc); +} diff --git a/agent/command.c b/agent/command.c index 2e996d096..9351ef615 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1297,6 +1297,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."; @@ -1309,13 +1310,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); @@ -1367,6 +1369,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); @@ -2648,6 +2678,53 @@ cmd_scd (assuan_context_t ctx, char *line) } +static const char hlp_tkd[] = + "TKD <commands to pass to the tkdaemon>\n" + " \n" + "This is a general quote command to redirect everything to the\n" + "TKdaemon."; +static gpg_error_t +cmd_tkd (assuan_context_t ctx, char *line) +{ + int rc; +#ifdef BUILD_WITH_TKDAEMON + ctrl_t ctrl = assuan_get_pointer (ctx); + + if (ctrl->restricted) + { + const char *argv[5]; + int argc; + char *l; + + l = xtrystrdup (line); + if (!l) + return gpg_error_from_syserror (); + + argc = split_fields (l, argv, DIM (argv)); + + /* These commands are allowed. */ + if ((argc >= 1 && !strcmp (argv[0], "SLOTLIST")) + || (argc == 2 + && !strcmp (argv[0], "GETINFO") + && !strcmp (argv[1], "version")) + || (argc == 2 + && !strcmp (argv[0], "KEYINFO") + && !strcmp (argv[1], "--list=encr"))) + xfree (l); + else + { + xfree (l); + return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); + } + } + + rc = divert_tkd_cmd (ctrl, line); +#else + (void)ctx; (void)line; + rc = gpg_error (GPG_ERR_NOT_SUPPORTED); +#endif + return rc; +} static const char hlp_keywrap_key[] = "KEYWRAP_KEY [--clear] <mode>\n" @@ -4198,6 +4275,7 @@ register_commands (assuan_context_t ctx) { "INPUT", NULL }, { "OUTPUT", NULL }, { "SCD", cmd_scd, hlp_scd }, + { "TKD", cmd_tkd, hlp_tkd }, { "KEYWRAP_KEY", cmd_keywrap_key, hlp_keywrap_key }, { "IMPORT_KEY", cmd_import_key, hlp_import_key }, { "EXPORT_KEY", cmd_export_key, hlp_export_key }, diff --git a/agent/divert-tkd.c b/agent/divert-tkd.c new file mode 100644 index 000000000..3fd1872f1 --- /dev/null +++ b/agent/divert-tkd.c @@ -0,0 +1,45 @@ +/* divert-tkd.c - divert operations to the tkdaemon + * Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "agent.h" +#include "../common/i18n.h" +#include "../common/sexp-parse.h" + +int +divert_tkd_pksign (ctrl_t ctrl, const unsigned char *digest, size_t digestlen, + unsigned char **r_sig, size_t *r_siglen) +{ + return agent_tkd_pksign (ctrl, digest, digestlen, r_sig, r_siglen); +} + +int +divert_tkd_cmd (ctrl_t ctrl, const char *cmdline) +{ + return agent_tkd_cmd (ctrl, cmdline); +} diff --git a/agent/findkey.c b/agent/findkey.c index 098d5224f..3544764d0 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -1309,24 +1309,36 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce, err = agent_get_shadow_info_type (buf, &s, &shadow_type); if (!err) { - n = gcry_sexp_canon_len (s, 0, NULL,NULL); - log_assert (n); - *shadow_info = xtrymalloc (n); - if (!*shadow_info) + if (!s) { - err = out_of_core (); - goto shadow_error; + *shadow_info = xstrdup ("tkd"); + if (!*shadow_info) + { + err = out_of_core (); + goto shadow_error; + } } else { - memcpy (*shadow_info, s, n); - /* - * When it's a key on card (not on tpm2), maks sure - * it's available. - */ - if (strcmp (shadow_type, "t1-v1") == 0 && !grip) - err = prompt_for_card (ctrl, ctrl->keygrip, - keymeta, *shadow_info); + n = gcry_sexp_canon_len (s, 0, NULL,NULL); + log_assert (n); + *shadow_info = xtrymalloc (n); + if (!*shadow_info) + { + err = out_of_core (); + goto shadow_error; + } + else + { + memcpy (*shadow_info, s, n); + /* + * When it's a key on card (not on tpm2), make sure + * it's available. + */ + if (strcmp (shadow_type, "t1-v1") == 0 && !grip) + err = prompt_for_card (ctrl, ctrl->keygrip, + keymeta, *shadow_info); + } } } else @@ -1801,16 +1813,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/gpg-agent.c b/agent/gpg-agent.c index 1db422737..11815b4b5 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -104,6 +104,7 @@ enum cmd_and_opt_values oLCmessages, oXauthority, oScdaemonProgram, + oTkdaemonProgram, oTpm2daemonProgram, oDefCacheTTL, oDefCacheTTLSSH, @@ -207,6 +208,8 @@ static gpgrt_opt_t opts[] = { /* */ N_("do not use the SCdaemon") ), ARGPARSE_s_s (oScdaemonProgram, "scdaemon-program", /* */ N_("|PGM|use PGM as the SCdaemon program") ), + ARGPARSE_s_s (oTkdaemonProgram, "tkdaemon-program", + /* */ N_("|PGM|use PGM as the TKdaemon program") ), ARGPARSE_s_s (oTpm2daemonProgram, "tpm2daemon-program", /* */ N_("|PGM|use PGM as the tpm2daemon program") ), ARGPARSE_s_n (oDisableCheckOwnSocket, "disable-check-own-socket", "@"), @@ -942,6 +945,9 @@ parse_rereadable_options (gpgrt_argparse_t *pargs, int reread) case oScdaemonProgram: opt.daemon_program[DAEMON_SCD] = pargs->r.ret_str; break; + case oTkdaemonProgram: + opt.daemon_program[DAEMON_TKD] = pargs->r.ret_str; + break; case oDisableScdaemon: opt.disable_daemon[DAEMON_SCD] = 1; break; case oDisableCheckOwnSocket: disable_check_own_socket = 1; break; 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/pksign.c b/agent/pksign.c index dfed0e398..1ee278aac 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -392,7 +392,9 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce, } { - if (agent_is_tpm2_key (s_skey)) + if (!strcmp (shadow_info, "tkd")) + err = divert_tkd_pksign (ctrl, data, datalen, &buf, &len); + else if (agent_is_tpm2_key (s_skey)) err = divert_tpm2_pksign (ctrl, data, datalen, ctrl->digest.algo, diff --git a/agent/protect.c b/agent/protect.c index 7197cf7e6..a40be0f9a 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -1477,10 +1477,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); @@ -1536,7 +1541,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)); @@ -1550,7 +1556,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 @@ -1620,6 +1629,11 @@ agent_get_shadow_info_type (const unsigned char *shadowkey, if (shadow_info) *shadow_info = s; } + else if (smatch(&s, n, "tkd-v1")) + { + if (shadow_info) + *shadow_info = NULL; + } else return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); s = saved_s; |