Commit 0173d30a authored by David Woodhouse's avatar David Woodhouse

Support TPM2 auth

Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent b7b29a5a
......@@ -43,10 +43,12 @@
#include <tss2/tss2_esys.h>
struct oc_tpm2_ctx {
TPM2B_DIGEST userauth;
TPM2B_PUBLIC pub;
TPM2B_PRIVATE priv;
TPM2B_DIGEST userauth;
TPM2B_DIGEST ownerauth;
unsigned int need_userauth:1;
unsigned int need_ownerauth:1;
};
static TPM2B_PUBLIC primaryTemplate = {
......@@ -111,8 +113,8 @@ static TPML_PCR_SELECTION allCreationPCR = {
* @retval TSS2_RC_SUCCESS on success
* @retval TSS2_RCs according to the error
*/
static TSS2_RC init_tpm2_primary(struct openconnect_info *vpninfo,
ESYS_CONTEXT **ctx, ESYS_TR *primaryHandle)
static int init_tpm2_primary(struct openconnect_info *vpninfo,
ESYS_CONTEXT **ctx, ESYS_TR *primaryHandle)
{
TSS2_RC r;
*primaryHandle = ESYS_TR_NONE;
......@@ -140,7 +142,26 @@ static TSS2_RC init_tpm2_primary(struct openconnect_info *vpninfo,
}
vpn_progress(vpninfo, PRG_DEBUG, _("Creating primary key under owner.\n"));
reauth:
if (vpninfo->tpm2->need_ownerauth) {
char *pass = NULL;
int err = request_passphrase(vpninfo, "openconnect_tpm2_owner",
&pass, _("Enter TPM2 owner password:"));
if (err)
goto error;
if (strlen(pass) > sizeof(vpninfo->tpm2->ownerauth.buffer) - 1) {
vpn_progress(vpninfo, PRG_ERR,
_("TPM2 owner password too long; truncating\n"));
pass[sizeof(vpninfo->tpm2->ownerauth.buffer) - 1] = 0;
}
vpninfo->tpm2->ownerauth.size = strlen(pass);
strcpy((char *)vpninfo->tpm2->ownerauth.buffer, pass);
memset(pass, 0, strlen(pass));
free(pass);
vpninfo->tpm2->need_ownerauth = 0;
}
r = Esys_TR_SetAuth(*ctx, ESYS_TR_RH_OWNER, &vpninfo->tpm2->ownerauth);
if (r) {
vpn_progress(vpninfo, PRG_ERR,
......@@ -157,8 +178,8 @@ static TSS2_RC init_tpm2_primary(struct openconnect_info *vpninfo,
if (r == 0x000009a2) {
vpn_progress(vpninfo, PRG_DEBUG,
_("TPM2 Esys_CreatePrimary owner auth failed\n"));
/* XXX: Prompt and retry */
goto error;
vpninfo->tpm2->need_ownerauth = 1;
goto reauth;
} else if (r) {
vpn_progress(vpninfo, PRG_ERR,
_("TPM2 Esys_CreatePrimary failed: 0x%x\n"),
......@@ -166,14 +187,14 @@ static TSS2_RC init_tpm2_primary(struct openconnect_info *vpninfo,
goto error;
}
return TSS2_RC_SUCCESS;
return 0;
error:
if (*primaryHandle != ESYS_TR_NONE)
Esys_FlushContext(*ctx, *primaryHandle);
*primaryHandle = ESYS_TR_NONE;
Esys_Finalize(ctx);
return r;
return -EIO;
}
/** Initialize the ESYS TPM connection and load the key
......@@ -187,15 +208,14 @@ static TSS2_RC init_tpm2_primary(struct openconnect_info *vpninfo,
* @retval TSS2_RC_SUCCESS on success
* @retval TSS2_RCs according to the error
*/
static TSS2_RC init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *keyHandle,
struct openconnect_info *vpninfo)
static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *keyHandle,
struct openconnect_info *vpninfo)
{
TSS2_RC r;
ESYS_TR primaryHandle = ESYS_TR_NONE;
*keyHandle = ESYS_TR_NONE;
r = init_tpm2_primary(vpninfo, ctx, &primaryHandle);
if (r)
if (init_tpm2_primary(vpninfo, ctx, &primaryHandle))
goto error;
vpn_progress(vpninfo, PRG_DEBUG, _("Loading TPM2 key blob.\n"));
......@@ -220,15 +240,7 @@ static TSS2_RC init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *keyHandle,
}
primaryHandle = ESYS_TR_NONE;
r = Esys_TR_SetAuth(*ctx, *keyHandle, &vpninfo->tpm2->userauth);
if (r) {
vpn_progress(vpninfo, PRG_ERR,
_("TPM2 Esys_TR_SetAuth failed: 0x%x\n"),
r);
goto error;
}
return TSS2_RC_SUCCESS;
return 0;
error:
if (primaryHandle != ESYS_TR_NONE)
Esys_FlushContext(*ctx, primaryHandle);
......@@ -237,7 +249,46 @@ static TSS2_RC init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *keyHandle,
*keyHandle = ESYS_TR_NONE;
Esys_Finalize(ctx);
return r;
return -EIO;
}
static int auth_tpm2_key(struct openconnect_info *vpninfo, ESYS_CONTEXT *ctx, ESYS_TR key_handle)
{
TSS2_RC r;
if (vpninfo->tpm2->need_userauth || vpninfo->cert_password) {
char *pass = NULL;
if (vpninfo->cert_password) {
pass = vpninfo->cert_password;
vpninfo->cert_password = NULL;
} else {
int err = request_passphrase(vpninfo, "openconnect_tpm2_key",
&pass, _("Enter TPM2 key password:"));
if (err)
return err;
}
if (strlen(pass) > sizeof(vpninfo->tpm2->userauth.buffer) - 1) {
vpn_progress(vpninfo, PRG_ERR,
_("TPM2 key password too long; truncating\n"));
pass[sizeof(vpninfo->tpm2->userauth.buffer) - 1] = 0;
}
vpninfo->tpm2->userauth.size = strlen(pass);
strcpy((char *)vpninfo->tpm2->userauth.buffer, pass);
memset(pass, 0, strlen(pass));
free(pass);
vpninfo->tpm2->need_userauth = 0;
}
r = Esys_TR_SetAuth(ctx, key_handle, &vpninfo->tpm2->userauth);
if (r) {
vpn_progress(vpninfo, PRG_ERR,
_("TPM2 Esys_TR_SetAuth failed: 0x%x\n"),
r);
return -EIO;
}
return 0;
}
#define PKCS1_PAD_OVERHEAD 11
......@@ -277,18 +328,26 @@ static int tpm2_rsa_sign_fn(gnutls_privkey_t key, void *_vpninfo,
if (init_tpm2_key(&ectx, &key_handle, vpninfo))
goto out;
reauth:
if (auth_tpm2_key(vpninfo, ectx, key_handle))
goto out;
r = Esys_RSA_Decrypt(ectx, key_handle,
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
&digest, &inScheme, &label, &tsig);
if (r == 0x9a2) {
vpn_progress(vpninfo, PRG_DEBUG,
_("TPM2 Esys_RSA_Decrypt auth failed\n"));
vpninfo->tpm2->need_userauth = 1;
goto reauth;
}
if (r) {
vpn_progress(vpninfo, PRG_ERR,
_("TPM2 failed to generate RSA signature: %d\n"),
_("TPM2 failed to generate RSA signature: 0x%x\n"),
r);
goto out;
}
sig->data = malloc(tsig->size);
if (!sig->data)
goto out;
......@@ -337,7 +396,7 @@ int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, g
&vpninfo->tpm2->priv);
if (r) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to import RPM2 private key data: %d\n"),
_("Failed to import TPM2 private key data: 0x%x\n"),
r);
err_out:
release_tpm2_ctx(vpninfo);
......@@ -348,7 +407,7 @@ int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, g
&vpninfo->tpm2->pub);
if (r) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to import RPM2 private key data: %d\n"),
_("Failed to import TPM2 private key data: 0x%x\n"),
r);
goto err_out;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment