mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
agent: Add new shadow key type and functions to call tpm2daemon
* agent/call-tpm2d.c: New. * divert-tpm2.c: New. * agent/Makefile.am: Add new files. * agent/agent.h (DAEMON_TPM2D): New. Add stub fucntions. * agent/call-daemon.c (GNUPG_MODULE_NAME_TPM2DAEMON): New. * agent/command.c (do_one_keyinfo): Handle tpmv2. * agent/gpg-agent.c (oTpm2daemonProgram): New. (opts): New option --tpm2daemon-program. (parse_rereadable_options): Handle option. * agent/pkdecrypt.c (agent_pkdecrypt): Divert to tpm2d. (agent_pksign_do): Ditto. --- A new shadow key type: "tpm2-v1" is introduced signalling that the shadowed key is handled by the tpm2daemon. A function to identify this type is introduced and diversions to the tpm2daemon functions are conditioned on this function for pkign and pkdecrypt where the same diversions to scd are currently done. The (info) field of the shadowed key stores the actual TPM key. The TPM key is encrypted so only the physical TPM it was created on can read it (so no special protection is required for the info filed), but if the (info) field becomes corrupt or damaged, the key will be lost (unlike the token case, where the key is actually moved inside the token). Note, this commit adds handling for existing TPM format shadow keys, but there is still no way to create them. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Additional changes: * Add ChangeLog entries. * Some minor indentation fixes. * agent/Makefile.am (gpg_agent_SOURCES): Change to make distcheck work. * agent/agent.h [!HAVE_LIBTSS]: Do not return -EINVAL but an gpg_error_t. Mark args as unused. * agent/protect.c (agent_is_tpm2_key): Free BUF. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
62a7854816
commit
1f995b9ba4
@ -38,6 +38,12 @@ endif
|
||||
|
||||
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS)
|
||||
|
||||
if HAVE_LIBTSS
|
||||
tpm2_sources = divert-tpm2.c call-tpm2d.c
|
||||
else
|
||||
tpm2_sources =
|
||||
endif
|
||||
|
||||
gpg_agent_SOURCES = \
|
||||
gpg-agent.c agent.h \
|
||||
command.c command-ssh.c \
|
||||
@ -55,6 +61,7 @@ gpg_agent_SOURCES = \
|
||||
cvt-openpgp.c cvt-openpgp.h \
|
||||
call-scd.c \
|
||||
call-daemon.c \
|
||||
$(tpm2_sources) \
|
||||
learncard.c
|
||||
|
||||
common_libs = $(libcommon)
|
||||
|
@ -59,6 +59,7 @@
|
||||
enum daemon_type
|
||||
{
|
||||
DAEMON_SCD,
|
||||
DAEMON_TPM2D,
|
||||
DAEMON_MAX_TYPE
|
||||
};
|
||||
|
||||
@ -459,6 +460,7 @@ gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
gcry_sexp_t *result);
|
||||
int agent_pk_get_algo (gcry_sexp_t s_key);
|
||||
int agent_is_tpm2_key(gcry_sexp_t s_key);
|
||||
int agent_key_available (const unsigned char *grip);
|
||||
gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
int *r_keytype,
|
||||
@ -577,6 +579,52 @@ gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name,
|
||||
const char *fpr, int flag);
|
||||
void agent_reload_trustlist (void);
|
||||
|
||||
/*-- divert-tpm2.c --*/
|
||||
#ifdef HAVE_LIBTSS
|
||||
int divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||
size_t *r_siglen);
|
||||
int divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len, int *r_padding);
|
||||
int divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t s_skey);
|
||||
#else /*!HAVE_LIBTSS*/
|
||||
static inline int
|
||||
divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *digest,
|
||||
size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info,
|
||||
unsigned char **r_sig,
|
||||
size_t *r_siglen)
|
||||
{
|
||||
(void)ctrl; (void)desc_text; (void)digest; (void)digestlen;
|
||||
(void)algo; (void)shadow_info; (void)r_sig; (void)r_siglen;
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
static inline int
|
||||
divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len,
|
||||
int *r_padding)
|
||||
{
|
||||
(void)ctrl; (void)desc_text; (void)cipher; (void)shadow_info;
|
||||
(void)r_buf; (void)r_len; (void)r_padding;
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
static inline int
|
||||
divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t s_skey)
|
||||
{
|
||||
(void)ctrl; (void)grip; (void)s_key;
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
#endif /*!HAVE_LIBTSS*/
|
||||
|
||||
|
||||
|
||||
/*-- divert-scd.c --*/
|
||||
int divert_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
@ -606,6 +654,16 @@ void agent_daemon_check_aliveness (void);
|
||||
void agent_reset_daemon (ctrl_t ctrl);
|
||||
void agent_kill_daemon (enum daemon_type type);
|
||||
|
||||
/*-- call-tpm2d.c --*/
|
||||
int agent_tpm2d_writekey (ctrl_t ctrl, unsigned char **shadow_info,
|
||||
gcry_sexp_t s_skey);
|
||||
int agent_tpm2d_pksign (ctrl_t ctrl, const unsigned char *digest,
|
||||
size_t digestlen, const unsigned char *shadow_info,
|
||||
unsigned char **r_sig, size_t *r_siglen);
|
||||
int agent_tpm2d_pkdecrypt (ctrl_t ctrl, const unsigned char *cipher,
|
||||
size_t cipherlen, const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len);
|
||||
|
||||
/*-- call-scd.c --*/
|
||||
int agent_card_learn (ctrl_t ctrl,
|
||||
void (*kpinfo_cb)(void*, const char *),
|
||||
|
@ -45,7 +45,8 @@
|
||||
* same order as given by the daemon_type enum. */
|
||||
static const int daemon_modules[DAEMON_MAX_TYPE] =
|
||||
{
|
||||
GNUPG_MODULE_NAME_SCDAEMON
|
||||
GNUPG_MODULE_NAME_SCDAEMON,
|
||||
GNUPG_MODULE_NAME_TPM2DAEMON
|
||||
};
|
||||
|
||||
/* Definition of module local data of the CTRL structure. */
|
||||
|
248
agent/call-tpm2d.c
Normal file
248
agent/call-tpm2d.c
Normal file
@ -0,0 +1,248 @@
|
||||
#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_tpm2d (ctrl_t ctrl)
|
||||
{
|
||||
return daemon_start (DAEMON_TPM2D, ctrl);
|
||||
}
|
||||
|
||||
static int
|
||||
unlock_tpm2d (ctrl_t ctrl, gpg_error_t err)
|
||||
{
|
||||
return daemon_unlock (DAEMON_TPM2D, ctrl, err);
|
||||
}
|
||||
|
||||
static assuan_context_t
|
||||
daemon_ctx (ctrl_t ctrl)
|
||||
{
|
||||
return daemon_type_ctx (DAEMON_TPM2D, 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);
|
||||
}
|
||||
|
||||
int
|
||||
agent_tpm2d_writekey (ctrl_t ctrl, unsigned char **shadow_info,
|
||||
gcry_sexp_t s_skey)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
size_t n;
|
||||
unsigned char *kbuf;
|
||||
membuf_t data;
|
||||
struct inq_parm_s inqparm;
|
||||
size_t len;
|
||||
|
||||
rc = start_tpm2d (ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* note: returned data is TPM protected so no need for a sensitive context */
|
||||
init_membuf(&data, 4096);
|
||||
|
||||
inqparm.ctx = daemon_ctx (ctrl);
|
||||
inqparm.getpin_cb = agent_ask_new_passphrase;
|
||||
inqparm.ctrl = ctrl;
|
||||
inqparm.pin = NULL;
|
||||
|
||||
n = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
kbuf = xtrymalloc (n);
|
||||
gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, kbuf, n);
|
||||
inqparm.keydata = kbuf;
|
||||
inqparm.keydatalen = n;
|
||||
snprintf(line, sizeof(line), "IMPORT");
|
||||
|
||||
rc = assuan_transact (daemon_ctx (ctrl), line,
|
||||
put_membuf_cb, &data,
|
||||
inq_keydata, &inqparm,
|
||||
NULL, NULL);
|
||||
xfree (kbuf);
|
||||
xfree (inqparm.pin);
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
return unlock_tpm2d (ctrl, rc);
|
||||
}
|
||||
|
||||
*shadow_info = get_membuf (&data, &len);
|
||||
|
||||
return unlock_tpm2d (ctrl, 0);
|
||||
}
|
||||
|
||||
static gpg_error_t
|
||||
pin_cb (ctrl_t ctrl, const char *prompt, char **passphrase)
|
||||
{
|
||||
*passphrase = agent_get_cache (ctrl, ctrl->keygrip, 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,
|
||||
ctrl->keygrip, CACHE_MODE_USER, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
agent_tpm2d_pksign (ctrl_t ctrl, const unsigned char *digest,
|
||||
size_t digestlen, const unsigned char *shadow_info,
|
||||
unsigned char **r_sig, size_t *r_siglen)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
membuf_t data;
|
||||
struct inq_parm_s inqparm;
|
||||
|
||||
rc = start_tpm2d (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)
|
||||
agent_put_cache (ctrl, ctrl->keygrip, CACHE_MODE_USER, inqparm.pin, 0);
|
||||
|
||||
xfree (inqparm.pin);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
size_t len;
|
||||
xfree (get_membuf (&data, &len));
|
||||
return unlock_tpm2d (ctrl, rc);
|
||||
}
|
||||
|
||||
*r_sig = get_membuf (&data, r_siglen);
|
||||
|
||||
return unlock_tpm2d (ctrl, 0);
|
||||
}
|
||||
|
||||
int
|
||||
agent_tpm2d_pkdecrypt (ctrl_t ctrl, const unsigned char *cipher,
|
||||
size_t cipherlen, const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
membuf_t data;
|
||||
struct inq_parm_s inqparm;
|
||||
|
||||
rc = start_tpm2d (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 = cipher;
|
||||
inqparm.extralen = cipherlen;
|
||||
inqparm.pin = NULL;
|
||||
|
||||
snprintf(line, sizeof(line), "PKDECRYPT");
|
||||
|
||||
rc = assuan_transact (daemon_ctx (ctrl), line,
|
||||
put_membuf_cb, &data,
|
||||
inq_extra, &inqparm,
|
||||
NULL, NULL);
|
||||
if (!rc)
|
||||
agent_put_cache (ctrl, ctrl->keygrip, CACHE_MODE_USER, inqparm.pin, 0);
|
||||
|
||||
xfree (inqparm.pin);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
size_t len;
|
||||
xfree (get_membuf (&data, &len));
|
||||
return unlock_tpm2d (ctrl, rc);
|
||||
}
|
||||
|
||||
*r_buf = get_membuf (&data, r_len);
|
||||
|
||||
return unlock_tpm2d (ctrl, 0);
|
||||
}
|
@ -1314,6 +1314,11 @@ do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip, assuan_context_t ctx,
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
else if (strcmp (shadow_info_type, "tpm2-v1") == 0)
|
||||
{
|
||||
serialno = xstrdup("TPM-Protected");
|
||||
idstr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error ("unrecognised shadow key type %s\n", shadow_info_type);
|
||||
|
145
agent/divert-tpm2.c
Normal file
145
agent/divert-tpm2.c
Normal file
@ -0,0 +1,145 @@
|
||||
#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_tpm2_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||
size_t *r_siglen)
|
||||
{
|
||||
return agent_tpm2d_pksign(ctrl, digest, digestlen,
|
||||
shadow_info, r_sig, r_siglen);
|
||||
}
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
agent_write_tpm2_shadow_key (ctrl_t ctrl, const unsigned char *grip,
|
||||
unsigned char *shadow_info)
|
||||
{
|
||||
gpg_error_t err;
|
||||
unsigned char *shdkey;
|
||||
unsigned char *pkbuf;
|
||||
size_t len;
|
||||
gcry_sexp_t s_pkey;
|
||||
|
||||
err = agent_public_key_from_file (ctrl, grip, &s_pkey);
|
||||
len = gcry_sexp_sprint(s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
pkbuf = xtrymalloc (len);
|
||||
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, pkbuf, len);
|
||||
gcry_sexp_release (s_pkey);
|
||||
|
||||
err = agent_shadow_key_type (pkbuf, shadow_info, "tpm2-v1", &shdkey);
|
||||
xfree (pkbuf);
|
||||
if (err)
|
||||
{
|
||||
log_error ("shadowing the key failed: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
||||
err = agent_write_private_key (grip, shdkey, len, 1 /*force*/,
|
||||
NULL, NULL, 0);
|
||||
xfree (shdkey);
|
||||
if (err)
|
||||
log_error ("error writing key: %s\n", gpg_strerror (err));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t s_skey)
|
||||
{
|
||||
int ret;
|
||||
/* shadow_info is always shielded so no special handling required */
|
||||
unsigned char *shadow_info;
|
||||
|
||||
ret = agent_tpm2d_writekey(ctrl, &shadow_info, s_skey);
|
||||
if (!ret) {
|
||||
ret = agent_write_tpm2_shadow_key (ctrl, grip, shadow_info);
|
||||
xfree (shadow_info);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len, int *r_padding)
|
||||
{
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
|
||||
*r_padding = -1;
|
||||
|
||||
(void)desc_text;
|
||||
|
||||
s = cipher;
|
||||
if (*s != '(')
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
if (!smatch (&s, n, "enc-val"))
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
if (*s != '(')
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
if (smatch (&s, n, "rsa"))
|
||||
{
|
||||
*r_padding = 0;
|
||||
if (*s != '(')
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
if (!smatch (&s, n, "a"))
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
n = snext (&s);
|
||||
}
|
||||
else if (smatch (&s, n, "ecdh"))
|
||||
{
|
||||
if (*s != '(')
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
if (smatch (&s, n, "s"))
|
||||
{
|
||||
n = snext (&s);
|
||||
s += n;
|
||||
if (*s++ != ')')
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
if (*s++ != '(')
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
}
|
||||
if (!smatch (&s, n, "e"))
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
n = snext (&s);
|
||||
}
|
||||
else
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
|
||||
|
||||
return agent_tpm2d_pkdecrypt (ctrl, s, n, shadow_info, r_buf, r_len);
|
||||
}
|
@ -102,6 +102,7 @@ enum cmd_and_opt_values
|
||||
oLCmessages,
|
||||
oXauthority,
|
||||
oScdaemonProgram,
|
||||
oTpm2daemonProgram,
|
||||
oDefCacheTTL,
|
||||
oDefCacheTTLSSH,
|
||||
oMaxCacheTTL,
|
||||
@ -199,6 +200,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 (oTpm2daemonProgram, "tpm2daemon-program",
|
||||
/* */ N_("|PGM|use PGM as the tpm2daemon program") ),
|
||||
ARGPARSE_s_n (oDisableCheckOwnSocket, "disable-check-own-socket", "@"),
|
||||
|
||||
ARGPARSE_s_s (oExtraSocket, "extra-socket",
|
||||
@ -905,7 +908,14 @@ parse_rereadable_options (gpgrt_argparse_t *pargs, int reread)
|
||||
opt.pinentry_invisible_char = xtrystrdup (pargs->r.ret_str); break;
|
||||
break;
|
||||
case oPinentryTimeout: opt.pinentry_timeout = pargs->r.ret_ulong; break;
|
||||
case oScdaemonProgram: opt.daemon_program[DAEMON_SCD] = pargs->r.ret_str; break;
|
||||
|
||||
case oTpm2daemonProgram:
|
||||
opt.daemon_program[DAEMON_TPM2D] = pargs->r.ret_str;
|
||||
break;
|
||||
|
||||
case oScdaemonProgram:
|
||||
opt.daemon_program[DAEMON_SCD] = pargs->r.ret_str;
|
||||
break;
|
||||
case oDisableScdaemon: opt.disable_daemon[DAEMON_SCD] = 1; break;
|
||||
case oDisableCheckOwnSocket: disable_check_own_socket = 1; break;
|
||||
|
||||
|
@ -312,8 +312,9 @@ to keys stored on a token:
|
||||
(comment whatever)
|
||||
)
|
||||
|
||||
The currently used protocol is "t1-v1" (token info version 1). The
|
||||
second list with the information has this layout:
|
||||
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":
|
||||
|
||||
(card_serial_number id_string_of_key fixed_pin_length)
|
||||
|
||||
@ -322,6 +323,13 @@ 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":
|
||||
|
||||
(parent tpm_private_string tpm_public_string)
|
||||
|
||||
Although this precise format is encapsulated inside the tpm2daemon
|
||||
itself and nothing in gpg ever uses this.
|
||||
|
||||
More items may be added to the list.
|
||||
|
||||
** OpenPGP Private Key Transfer Format
|
||||
|
@ -88,6 +88,10 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (agent_is_tpm2_key (s_skey))
|
||||
err = divert_tpm2_pkdecrypt (ctrl, desc_text, ciphertext, shadow_info,
|
||||
&buf, &len, r_padding);
|
||||
else
|
||||
err = divert_pkdecrypt (ctrl, desc_text, ctrl->keygrip, ciphertext,
|
||||
shadow_info, &buf, &len, r_padding);
|
||||
if (err)
|
||||
|
@ -397,6 +397,12 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
|
||||
if (desc_text)
|
||||
agent_modify_description (desc_text, NULL, s_pkey, &desc2);
|
||||
|
||||
if (agent_is_tpm2_key (s_skey))
|
||||
err = divert_tpm2_pksign (ctrl, desc2? desc2 : desc_text,
|
||||
data, datalen,
|
||||
ctrl->digest.algo,
|
||||
shadow_info, &buf, &len);
|
||||
else
|
||||
err = divert_pksign (ctrl, desc2? desc2 : desc_text,
|
||||
ctrl->keygrip,
|
||||
data, datalen,
|
||||
|
@ -1679,6 +1679,7 @@ agent_get_shadow_info_type (const unsigned char *shadowkey,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
agent_get_shadow_info (const unsigned char *shadowkey,
|
||||
unsigned char const **shadow_info)
|
||||
@ -1686,6 +1687,7 @@ agent_get_shadow_info(const unsigned char *shadowkey,
|
||||
return agent_get_shadow_info_type (shadowkey, shadow_info, NULL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
agent_is_tpm2_key (gcry_sexp_t s_skey)
|
||||
{
|
||||
@ -1701,12 +1703,14 @@ agent_is_tpm2_key(gcry_sexp_t s_skey)
|
||||
err = agent_get_shadow_info_type (buf, NULL, &type);
|
||||
if (err)
|
||||
return 0;
|
||||
xfree (buf);
|
||||
|
||||
err = strcmp (type, "tpm2-v1") == 0;
|
||||
xfree (type);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
agent_get_shadow_type (const unsigned char *shadowkey,
|
||||
unsigned char **shadow_type)
|
||||
@ -1714,6 +1718,7 @@ agent_get_shadow_type(const unsigned char *shadowkey,
|
||||
return agent_get_shadow_info_type (shadowkey, NULL, shadow_type);
|
||||
}
|
||||
|
||||
|
||||
/* Parse the canonical encoded SHADOW_INFO S-expression. On success
|
||||
the hex encoded serial number is returned as a malloced strings at
|
||||
R_HEXSN and the Id string as a malloced string at R_IDSTR. On
|
||||
|
Loading…
x
Reference in New Issue
Block a user