LIBS="$oldlibs"
CFLAGS="$oldcflags"
+ tss2lib=
+ AC_MSG_CHECKING([for tss2 library])
+ AC_CHECK_LIB([tss], [TSS_Create], [tss2lib=tss2],
+ AC_CHECK_LIB([TSS_Create], [ibmtss], [tss2lib=ibmtss], []))
+ if test "%tss2lib" != ""; then
+ AC_CHECK_HEADER($tss2lib/tss.h, AC_DEFINE_UNQUOTED(HAVE_TSS2, $tss2lib, [TSS2 library]), [])
+ fi
+
AC_DEFINE(OPENCONNECT_GNUTLS, 1, [Using GnuTLS])
AC_SUBST(SSL_PC, [gnutls])
AC_SUBST(SSL_LIBS, ['$(GNUTLS_LIBS)'])
return 0;
}
-#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined (HAVE_GNUTLS_SYSTEM_KEYS)
+#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_TSS2) || defined (HAVE_GNUTLS_SYSTEM_KEYS)
/* We have to convert the array of X509 certificates to gnutls_pcert_st
for ourselves. There's no function that takes a gnutls_privkey_t as
the key and gnutls_x509_crt_t certificates. */
return gnutls_pubkey_verify_data2(pubkey, algo, 0, data, sig);
}
-#endif /* (P11KIT || TROUSERS || SYSTEM_KEYS) */
+#endif /* (P11KIT || TROUSERS || TSS2 || SYSTEM_KEYS) */
static int openssl_hash_password(struct openconnect_info *vpninfo, char *pass,
gnutls_datum_t *key, gnutls_datum_t *salt)
{
gnutls_datum_t fdata;
gnutls_x509_privkey_t key = NULL;
-#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
+#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_TSS2) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
gnutls_privkey_t pkey = NULL;
gnutls_datum_t pkey_sig = {NULL, 0};
void *dummy_hash_data = &load_certificate;
#endif
}
+ /* Is it a PEM file with a TPM key blob? */
+ if (strstr((char *)fdata.data, "-----BEGIN TSS2 KEY BLOB-----")) {
+#ifndef HAVE_TSS2
+ vpn_progress(vpninfo, PRG_ERR,
+ _("This version of OpenConnect was built without TPM2 support\n"));
+ return -EINVAL;
+#else
+ ret = load_tpm2_key(vpninfo, &fdata, &pkey, &pkey_sig);
+ if (ret)
+ goto out;
+
+ goto match_cert;
+#endif
+ }
+
/* OK, try other PEM files... */
gnutls_x509_privkey_init(&key);
if ((pem_header = strstr((char *)fdata.data, "-----BEGIN RSA PRIVATE KEY-----")) ||
enabled we'll fall straight through the bit at match_cert: below, and go
directly to the bit where it prints the 'no match found' error and exits. */
-#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
+#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_TSS2) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
match_cert:
/* If we have a privkey from PKCS#11 or TPM, we can't do the simple comparison
of key ID that we do for software keys to find which certificate is a
}
gnutls_free(pkey_sig.data);
}
-#endif /* P11KIT || TROUSERS || SYSTEM_KEYS */
+#endif /* P11KIT || TROUSERS || TSS2 || SYSTEM_KEYS */
/* We shouldn't reach this. It means that we didn't find *any* matching cert */
vpn_progress(vpninfo, PRG_ERR,
key and certs. GnuTLS makes us do this differently for X509 privkeys
vs. TPM/PKCS#11 "generic" privkeys, and the latter is particularly
'fun' for GnuTLS 2.12... */
-#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
+#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_TSS2) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
if (pkey) {
err = assign_privkey(vpninfo, pkey,
supporting_certs,
of extra_certs[] may have been zeroed. */
}
} else
-#endif /* P11KIT || TROUSERS */
+#endif /* P11KIT || TROUSERS || TSS2 || SYSTEM_KEYS */
err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
supporting_certs,
nr_supporting_certs, key);
}
gnutls_free(extra_certs);
-#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
+#if defined(HAVE_P11KIT) || defined(HAVE_TROUSERS) || defined(HAVE_TSS2) || defined(HAVE_GNUTLS_SYSTEM_KEYS)
if (pkey)
gnutls_privkey_deinit(pkey);
/* If we support arbitrary privkeys, we might have abused fdata.data
vpninfo->https_cred = NULL;
#ifdef HAVE_TROUSERS
release_tpm1_ctx(vpninfo);
+#endif
+#ifdef HAVE_TSS2
+ release_tpm2_ctx(vpninfo);
#endif
}
}
--- /dev/null
+/*
+ * OpenConnect (SSL + DTLS) VPN client
+ *
+ * Copyright © 2018 David Woodhouse.
+ *
+ * Author: David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <gnutls/gnutls.h>
+#include "openconnect-internal.h"
+
+#include "gnutls.h"
+
+#ifdef HAVE_TSS2
+#define TSSINCLUDE(x) < HAVE_TSS2/x >
+#include TSSINCLUDE(tss.h)
+
+struct oc_tpm2_ctx {
+};
+
+int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata,
+ gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig)
+{
+ gnutls_datum_t asn1;
+ int err;
+
+ err = gnutls_pem_base64_decode_alloc("TSS2 KEY BLOB", fdata, &asn1);
+ if (err) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Error decoding TSS2 key blob: %s\n"),
+ gnutls_strerror(err));
+ return -EINVAL;
+ }
+ free(asn1.data);
+ vpn_progress(vpninfo, PRG_ERR,
+ _("TPM2 not really implemented yet\n"));
+ return -EINVAL;
+}
+
+void release_tpm2_ctx(struct openconnect_info *vpninfo)
+{
+ if (vpninfo->tpm2)
+ free(vpninfo->tpm2);
+ vpninfo->tpm2 = NULL;
+}
+#endif /* HAVE_TSS2 */