diff --git a/gnutls.c b/gnutls.c index 49dad286..dc285570 100644 --- a/gnutls.c +++ b/gnutls.c @@ -33,11 +33,6 @@ #include #include -#ifdef HAVE_TROUSERS -#include -#include -#endif - #ifdef HAVE_P11KIT #include #include @@ -1316,7 +1311,7 @@ static int load_certificate(struct openconnect_info *vpninfo) _("This version of OpenConnect was built without TPM support\n")); return -EINVAL; #else - ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig); + ret = load_tpm1_key(vpninfo, &fdata, &pkey, &pkey_sig); if (ret) goto out; @@ -2319,26 +2314,7 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final) gnutls_certificate_free_credentials(vpninfo->https_cred); vpninfo->https_cred = NULL; #ifdef HAVE_TROUSERS - if (vpninfo->tpm_key_policy) { - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy); - vpninfo->tpm_key = 0; - } - if (vpninfo->tpm_key) { - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key); - vpninfo->tpm_key = 0; - } - if (vpninfo->srk_policy) { - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy); - vpninfo->srk_policy = 0; - } - if (vpninfo->srk) { - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk); - vpninfo->srk = 0; - } - if (vpninfo->tpm_context) { - Tspi_Context_Close(vpninfo->tpm_context); - vpninfo->tpm_context = 0; - } + release_tpm1_ctx(vpninfo); #endif } } diff --git a/gnutls.h b/gnutls.h index 5eeacb0f..93ad42dc 100644 --- a/gnutls.h +++ b/gnutls.h @@ -24,8 +24,9 @@ #include "openconnect-internal.h" -int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, - gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig); +int load_tpm1_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig); +void release_tpm1_ctx(struct openconnect_info *info); char *get_gnutls_cipher(gnutls_session_t session); diff --git a/gnutls_tpm.c b/gnutls_tpm.c index ed417d19..9f55b2b8 100644 --- a/gnutls_tpm.c +++ b/gnutls_tpm.c @@ -31,6 +31,16 @@ #include "gnutls.h" #ifdef HAVE_TROUSERS +#include +#include + +struct oc_tpm1_ctx { + TSS_HCONTEXT tpm_context; + TSS_HKEY srk; + TSS_HPOLICY srk_policy; + TSS_HKEY tpm_key; + TSS_HPOLICY tpm_key_policy; +}; /* Signing function for TPM privkeys, set with gnutls_privkey_import_ext() */ static int tpm_sign_fn(gnutls_privkey_t key, void *_vpninfo, @@ -44,7 +54,7 @@ static int tpm_sign_fn(gnutls_privkey_t key, void *_vpninfo, _("TPM sign function called for %d bytes.\n"), data->size); - err = Tspi_Context_CreateObject(vpninfo->tpm_context, TSS_OBJECT_TYPE_HASH, + err = Tspi_Context_CreateObject(vpninfo->tpm1->tpm_context, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hash); if (err) { vpn_progress(vpninfo, PRG_ERR, @@ -57,13 +67,13 @@ static int tpm_sign_fn(gnutls_privkey_t key, void *_vpninfo, vpn_progress(vpninfo, PRG_ERR, _("Failed to set value in TPM hash object: %s\n"), Trspi_Error_String(err)); - Tspi_Context_CloseObject(vpninfo->tpm_context, hash); + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, hash); return GNUTLS_E_PK_SIGN_FAILED; } - err = Tspi_Hash_Sign(hash, vpninfo->tpm_key, &sig->size, &sig->data); - Tspi_Context_CloseObject(vpninfo->tpm_context, hash); + err = Tspi_Hash_Sign(hash, vpninfo->tpm1->tpm_key, &sig->size, &sig->data); + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, hash); if (err) { - if (vpninfo->tpm_key_policy || err != TPM_E_AUTHFAIL) + if (vpninfo->tpm1->tpm_key_policy || err != TPM_E_AUTHFAIL) vpn_progress(vpninfo, PRG_ERR, _("TPM hash signature failed: %s\n"), Trspi_Error_String(err)); @@ -75,8 +85,8 @@ static int tpm_sign_fn(gnutls_privkey_t key, void *_vpninfo, return 0; } -int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, - gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig) +int load_tpm1_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig) { static const TSS_UUID SRK_UUID = TSS_UUID_SRK; gnutls_datum_t asn1; @@ -91,6 +101,7 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, gnutls_strerror(err)); return -EINVAL; } + vpninfo->tpm1 = calloc(1, sizeof(*vpninfo->tpm1)); /* Ick. We have to parse the ASN1 OCTET_STRING for ourselves. */ if (asn1.size < 2 || asn1.data[0] != 0x04 /* OCTET_STRING */) { vpn_progress(vpninfo, PRG_ERR, @@ -122,29 +133,29 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, goto out_blob; } - err = Tspi_Context_Create(&vpninfo->tpm_context); + err = Tspi_Context_Create(&vpninfo->tpm1->tpm_context); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to create TPM context: %s\n"), Trspi_Error_String(err)); goto out_blob; } - err = Tspi_Context_Connect(vpninfo->tpm_context, NULL); + err = Tspi_Context_Connect(vpninfo->tpm1->tpm_context, NULL); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to connect TPM context: %s\n"), Trspi_Error_String(err)); goto out_context; } - err = Tspi_Context_LoadKeyByUUID(vpninfo->tpm_context, TSS_PS_TYPE_SYSTEM, - SRK_UUID, &vpninfo->srk); + err = Tspi_Context_LoadKeyByUUID(vpninfo->tpm1->tpm_context, TSS_PS_TYPE_SYSTEM, + SRK_UUID, &vpninfo->tpm1->srk); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to load TPM SRK key: %s\n"), Trspi_Error_String(err)); goto out_context; } - err = Tspi_GetPolicyObject(vpninfo->srk, TSS_POLICY_USAGE, &vpninfo->srk_policy); + err = Tspi_GetPolicyObject(vpninfo->tpm1->srk, TSS_POLICY_USAGE, &vpninfo->tpm1->srk_policy); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to load TPM SRK policy object: %s\n"), @@ -159,11 +170,11 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, /* We don't seem to get the error here... */ if (pass) - err = Tspi_Policy_SetSecret(vpninfo->srk_policy, + err = Tspi_Policy_SetSecret(vpninfo->tpm1->srk_policy, TSS_SECRET_MODE_PLAIN, strlen(pass), (BYTE *)pass); else /* Well-known NULL key */ - err = Tspi_Policy_SetSecret(vpninfo->srk_policy, + err = Tspi_Policy_SetSecret(vpninfo->tpm1->srk_policy, TSS_SECRET_MODE_SHA1, sizeof(nullpass), (BYTE *)nullpass); if (err) { @@ -176,9 +187,9 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, free(pass); /* ... we get it here instead. */ - err = Tspi_Context_LoadKeyByBlob(vpninfo->tpm_context, vpninfo->srk, + err = Tspi_Context_LoadKeyByBlob(vpninfo->tpm1->tpm_context, vpninfo->tpm1->srk, tss_len, asn1.data + ofs, - &vpninfo->tpm_key); + &vpninfo->tpm1->tpm_key); if (!err) break; @@ -205,19 +216,19 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, retry_sign: err = gnutls_privkey_sign_data(*pkey, GNUTLS_DIG_SHA1, 0, fdata, pkey_sig); if (err == GNUTLS_E_INSUFFICIENT_CREDENTIALS) { - if (!vpninfo->tpm_key_policy) { - err = Tspi_Context_CreateObject(vpninfo->tpm_context, + if (!vpninfo->tpm1->tpm_key_policy) { + err = Tspi_Context_CreateObject(vpninfo->tpm1->tpm_context, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, - &vpninfo->tpm_key_policy); + &vpninfo->tpm1->tpm_key_policy); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to create key policy object: %s\n"), Trspi_Error_String(err)); goto out_key; } - err = Tspi_Policy_AssignToObject(vpninfo->tpm_key_policy, - vpninfo->tpm_key); + err = Tspi_Policy_AssignToObject(vpninfo->tpm1->tpm_key_policy, + vpninfo->tpm1->tpm_key); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to assign policy to key: %s\n"), @@ -230,7 +241,7 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, if (err) goto out_key_policy; - err = Tspi_Policy_SetSecret(vpninfo->tpm_key_policy, + err = Tspi_Policy_SetSecret(vpninfo->tpm1->tpm_key_policy, TSS_SECRET_MODE_PLAIN, strlen(pass), (void *)pass); free(pass); @@ -247,23 +258,53 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, free(asn1.data); return 0; out_key_policy: - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy); - vpninfo->tpm_key_policy = 0; + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->tpm_key_policy); + vpninfo->tpm1->tpm_key_policy = 0; out_key: - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key); - vpninfo->tpm_key = 0; + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->tpm_key); + vpninfo->tpm1->tpm_key = 0; out_srkpol: - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy); - vpninfo->srk_policy = 0; + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->srk_policy); + vpninfo->tpm1->srk_policy = 0; out_srk: - Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk); - vpninfo->srk = 0; + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->srk); + vpninfo->tpm1->srk = 0; out_context: - Tspi_Context_Close(vpninfo->tpm_context); - vpninfo->tpm_context = 0; + Tspi_Context_Close(vpninfo->tpm1->tpm_context); + vpninfo->tpm1->tpm_context = 0; out_blob: free(asn1.data); + free(vpninfo->tpm1); + vpninfo->tpm1 = NULL; return -EIO; } +void release_tpm1_ctx(struct openconnect_info *vpninfo) +{ + if (!vpninfo->tpm1) + return; + + if (vpninfo->tpm1->tpm_key_policy) { + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->tpm_key_policy); + vpninfo->tpm1->tpm_key = 0; + } + if (vpninfo->tpm1->tpm_key) { + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->tpm_key); + vpninfo->tpm1->tpm_key = 0; + } + if (vpninfo->tpm1->srk_policy) { + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->srk_policy); + vpninfo->tpm1->srk_policy = 0; + } + if (vpninfo->tpm1->srk) { + Tspi_Context_CloseObject(vpninfo->tpm1->tpm_context, vpninfo->tpm1->srk); + vpninfo->tpm1->srk = 0; + } + if (vpninfo->tpm1->tpm_context) { + Tspi_Context_Close(vpninfo->tpm1->tpm_context); + vpninfo->tpm1->tpm_context = 0; + } + free(vpninfo->tpm1); + vpninfo->tpm1 = NULL; +}; #endif /* HAVE_TROUSERS */ diff --git a/openconnect-internal.h b/openconnect-internal.h index 118571de..63547a4a 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -57,10 +57,6 @@ #include #include #include -#ifdef HAVE_TROUSERS -#include -#include -#endif #endif #ifdef HAVE_ICONV @@ -349,6 +345,7 @@ struct esp { }; struct oc_pcsc_ctx; +struct oc_tpm1_ctx; struct openconnect_info { const struct vpn_proto *proto; @@ -504,11 +501,7 @@ struct openconnect_info { char local_cert_md5[MD5_SIZE * 2 + 1]; /* For CSD */ char gnutls_prio[256]; #ifdef HAVE_TROUSERS - TSS_HCONTEXT tpm_context; - TSS_HKEY srk; - TSS_HPOLICY srk_policy; - TSS_HKEY tpm_key; - TSS_HPOLICY tpm_key_policy; + struct oc_tpm1_ctx *tpm1; #endif #endif /* OPENCONNECT_GNUTLS */ struct pin_cache *pin_cache;