From 3a93d9b28a557964bdcedff6e25bb8b5b5c8a830 Mon Sep 17 00:00:00 2001 From: Tom Carroll Date: Sat, 2 May 2020 21:38:11 -0700 Subject: [PATCH] Provide password to load_tpm2_key Permit a single instance of tpm2. Return -EBUSY to inform of caller of existing instance. Duplicate password when necessary. Signed-off-by: Tom Carroll --- gnutls.c | 2 +- gnutls.h | 5 ++++- gnutls_tpm2.c | 10 +++++++++- gnutls_tpm2_esys.c | 19 ++++++++++++++----- gnutls_tpm2_ibm.c | 6 +++++- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/gnutls.c b/gnutls.c index c747962b..8c408c42 100644 --- a/gnutls.c +++ b/gnutls.c @@ -1679,7 +1679,7 @@ static int load_keycert(struct openconnect_info *vpninfo, _("This version of OpenConnect was built without TPM2 support\n")); return -EINVAL; #else - ret = load_tpm2_key(vpninfo, &fdata, &pkey, &pkey_sig); + ret = load_tpm2_key(vpninfo, &fdata, password, &pkey, &pkey_sig); if (ret) goto out; diff --git a/gnutls.h b/gnutls.h index 6d39f9be..30c99020 100644 --- a/gnutls.h +++ b/gnutls.h @@ -30,9 +30,12 @@ int load_tpm1_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, void release_tpm1_ctx(struct openconnect_info *info); int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, + const char *password, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig); void release_tpm2_ctx(struct openconnect_info *info); -int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, +int install_tpm2_key(struct openconnect_info *vpninfo, + const char *password, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, unsigned int parent, int emptyauth, int legacy, gnutls_datum_t *privdata, gnutls_datum_t *pubdata); diff --git a/gnutls_tpm2.c b/gnutls_tpm2.c index 698a9e2e..29b17e8a 100644 --- a/gnutls_tpm2.c +++ b/gnutls_tpm2.c @@ -175,6 +175,7 @@ static int decode_data(ASN1_TYPE n, gnutls_datum_t *r) } int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, + const char *password, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig) { gnutls_datum_t asn1, pubdata, privdata; @@ -187,6 +188,12 @@ int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, int err, ret = -EINVAL; const asn1_static_node *asn1tab; + if (vpninfo->tpm2) { + vpn_progress(vpninfo, PRG_ERR, + _("TPM2 is in use.\n")); + return -EBUSY; + } + err = gnutls_pem_base64_decode_alloc("TSS2 PRIVATE KEY", fdata, &asn1); if (!err) { asn1tab = tpmkey_asn1_tab; @@ -282,7 +289,8 @@ int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, /* Now we've extracted what we need from the ASN.1, invoke the * actual TPM2 code (whichever implementation we end up with */ - ret = install_tpm2_key(vpninfo, pkey, pkey_sig, parent, emptyauth, + ret = install_tpm2_key(vpninfo, password, + pkey, pkey_sig, parent, emptyauth, asn1tab == tpmkey_asn1_tab_old, &privdata, &pubdata); if (ret < 0) goto out_tpmkey; diff --git a/gnutls_tpm2_esys.c b/gnutls_tpm2_esys.c index c5eabd82..746eea1c 100644 --- a/gnutls_tpm2_esys.c +++ b/gnutls_tpm2_esys.c @@ -65,6 +65,7 @@ struct oc_tpm2_ctx { TPM2B_PRIVATE priv; TPM2B_DIGEST userauth; TPM2B_DIGEST ownerauth; + char *key_pass; unsigned int need_userauth:1; unsigned int need_ownerauth:1; unsigned int did_ownerauth:1; @@ -356,12 +357,12 @@ static int auth_tpm2_key(struct openconnect_info *vpninfo, ESYS_CONTEXT *ctx, ES { TSS2_RC r; - if (vpninfo->tpm2->need_userauth || vpninfo->cert_password) { + if (vpninfo->tpm2->need_userauth || vpninfo->tpm2->key_pass) { char *pass = NULL; - if (vpninfo->cert_password) { - pass = vpninfo->cert_password; - vpninfo->cert_password = NULL; + if (vpninfo->tpm2->key_pass) { + pass = vpninfo->tpm2->key_pass; + vpninfo->tpm2->key_pass = NULL; } else { int err = request_passphrase(vpninfo, "openconnect_tpm2_key", &pass, _("Enter TPM2 key password:")); @@ -524,7 +525,9 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, return ret; } -int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, +int install_tpm2_key(struct openconnect_info *vpninfo, + const char *password, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, unsigned int parent, int emptyauth, int legacy, gnutls_datum_t *privdata, gnutls_datum_t *pubdata) { TSS2_RC r; @@ -541,6 +544,11 @@ int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, g if (!vpninfo->tpm2) return -ENOMEM; + if (password && (vpninfo->tpm2->key_pass = strdup(password)) == NULL) { + free(vpninfo->tpm2); + return -ENOMEM; + } + vpninfo->tpm2->parent = parent; r = Tss2_MU_TPM2B_PRIVATE_Unmarshal(privdata->data, privdata->size, NULL, @@ -583,6 +591,7 @@ void release_tpm2_ctx(struct openconnect_info *vpninfo) if (vpninfo->tpm2) { clear_mem(vpninfo->tpm2->ownerauth.buffer, sizeof(vpninfo->tpm2->ownerauth.buffer)); clear_mem(vpninfo->tpm2->userauth.buffer, sizeof(vpninfo->tpm2->userauth.buffer)); + free_pass(&vpninfo->tpm2->key_pass); free(vpninfo->tpm2); } vpninfo->tpm2 = NULL; diff --git a/gnutls_tpm2_ibm.c b/gnutls_tpm2_ibm.c index 3fe33b6c..c86d13a3 100644 --- a/gnutls_tpm2_ibm.c +++ b/gnutls_tpm2_ibm.c @@ -470,7 +470,9 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, return ret; } -int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, +int install_tpm2_key(struct openconnect_info *vpninfo, + const char *password, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, unsigned int parent, int emptyauth, int legacy, gnutls_datum_t *privdata, gnutls_datum_t *pubdata) { @@ -478,6 +480,8 @@ int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, g BYTE *der; INT32 dersize; + (void) password; + if (!parent_is_persistent(parent) && parent != TPM_RH_OWNER && parent != TPM_RH_NULL && parent != TPM_RH_ENDORSEMENT && parent != TPM_RH_PLATFORM) { -- 2.50.1