2021-03-09 13:50:29 -08:00
|
|
|
#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
|
2022-05-20 13:43:08 +09:00
|
|
|
divert_tpm2_pksign (ctrl_t ctrl,
|
2021-03-09 13:50:29 -08:00
|
|
|
const unsigned char *digest, size_t digestlen, int algo,
|
|
|
|
const unsigned char *shadow_info, unsigned char **r_sig,
|
|
|
|
size_t *r_siglen)
|
|
|
|
{
|
2021-03-09 13:50:30 -08:00
|
|
|
(void)algo;
|
2021-03-09 13:50:29 -08:00
|
|
|
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,
|
2023-09-28 11:59:14 +09:00
|
|
|
unsigned char *shadow_info,
|
|
|
|
gcry_sexp_t s_key)
|
2021-03-09 13:50:29 -08:00
|
|
|
{
|
2023-09-28 11:59:14 +09:00
|
|
|
gpg_error_t err, err1;
|
2021-03-09 13:50:29 -08:00
|
|
|
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)
|
|
|
|
{
|
2023-09-28 11:59:14 +09:00
|
|
|
log_error ("shadowing the tpm key failed: %s\n", gpg_strerror (err));
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = agent_delete_key (ctrl, NULL, grip, 1, 0);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
log_error ("failed to delete unshadowed key: %s\n", gpg_strerror (err));
|
2021-03-09 13:50:29 -08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
2024-01-22 13:22:44 +01:00
|
|
|
err = agent_write_private_key (ctrl, grip, shdkey, len, 1 /*force*/,
|
2023-05-26 11:59:46 +02:00
|
|
|
NULL, NULL, NULL, 0);
|
2021-03-09 13:50:29 -08:00
|
|
|
xfree (shdkey);
|
|
|
|
if (err)
|
2023-09-28 11:59:14 +09:00
|
|
|
{
|
|
|
|
log_error ("error writing tpm key: %s\n", gpg_strerror (err));
|
|
|
|
|
|
|
|
len = gcry_sexp_sprint(s_key, GCRYSEXP_FMT_CANON, NULL, 0);
|
|
|
|
pkbuf = xtrymalloc(len);
|
|
|
|
if (!pkbuf)
|
|
|
|
return GPG_ERR_ENOMEM;
|
|
|
|
|
|
|
|
gcry_sexp_sprint(s_key, GCRYSEXP_FMT_CANON, pkbuf, len);
|
2024-01-22 13:22:44 +01:00
|
|
|
err1 = agent_write_private_key (ctrl, grip, pkbuf, len, 1 /*force*/,
|
2023-09-28 11:59:14 +09:00
|
|
|
NULL, NULL, NULL, 0);
|
|
|
|
xfree(pkbuf);
|
|
|
|
if (err1)
|
|
|
|
log_error ("error trying to restore private key: %s\n",
|
|
|
|
gpg_strerror (err1));
|
|
|
|
}
|
2021-03-09 13:50:29 -08:00
|
|
|
|
|
|
|
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) {
|
2023-09-28 11:59:14 +09:00
|
|
|
ret = agent_write_tpm2_shadow_key (ctrl, grip, shadow_info, s_skey);
|
2021-03-09 13:50:29 -08:00
|
|
|
xfree (shadow_info);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2022-05-20 13:43:08 +09:00
|
|
|
divert_tpm2_pkdecrypt (ctrl_t ctrl,
|
2021-03-09 13:50:29 -08:00
|
|
|
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;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|