From 08ef809c5eb0cd9df7737f83de0f8ffc925fc980 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 9 Mar 2023 14:38:19 +0900 Subject: [PATCH] agent: Add divert to tkdaemon. Signed-off-by: NIIBE Yutaka --- agent/Makefile.am | 2 + agent/agent.h | 13 ++++ agent/call-tkd.c | 181 +++++++++++++++++++++++++++++++++++++++++++++ agent/divert-tkd.c | 41 ++++++++++ 4 files changed, 237 insertions(+) create mode 100644 agent/call-tkd.c create mode 100644 agent/divert-tkd.c 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 303f92e50..eeb970b7b 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 }; @@ -667,6 +668,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 *grip, + const unsigned char *digest, size_t digestlen, int algo, + unsigned char **r_sig, size_t *r_siglen); /*-- call-daemon.c --*/ gpg_error_t daemon_start (enum daemon_type type, ctrl_t ctrl); @@ -737,6 +743,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 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); /*-- 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..00c84c704 --- /dev/null +++ b/agent/call-tkd.c @@ -0,0 +1,181 @@ +/* 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 . + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agent.h" +#include +#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_keydata (void *opaque, const char *line) +{ + struct inq_parm_s *parm = opaque; + + if (has_leading_keyword (line, "KEYDATA")) + return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen); + else + return inq_needpin (opaque, line); +} + +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_keydata (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); +} + +int +agent_tkd_pksign (ctrl_t ctrl, const char *keygrip, + 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.ctrl = ctrl; + // inqparm.keydata = shadow_info; + // inqparm.keydatalen = gcry_sexp_canon_len (shadow_info, 0, NULL, NULL); + inqparm.extra = digest; + inqparm.extralen = digestlen; + inqparm.pin = NULL; + + snprintf(line, sizeof(line), "PKSIGN"); + + 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); +} diff --git a/agent/divert-tkd.c b/agent/divert-tkd.c new file mode 100644 index 000000000..b5e07bdf2 --- /dev/null +++ b/agent/divert-tkd.c @@ -0,0 +1,41 @@ +/* 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agent.h" +#include "../common/i18n.h" +#include "../common/sexp-parse.h" + +int +divert_tkd_pksign (ctrl_t ctrl, const unsigned char *grip, + const unsigned char *digest, size_t digestlen, int algo, + unsigned char **r_sig, size_t *r_siglen) +{ + (void)algo; + return agent_tkd_pksign(ctrl, grip, digest, digestlen, r_sig, r_siglen); +}