Commit 584cbb01 authored by David Woodhouse's avatar David Woodhouse

Add shell of TPM2 support

This doesn't do anything useful at all yet. It would be nice if the two
available OpenSSL engines were actually compatible.
Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 60109f0b
......@@ -31,7 +31,7 @@ library_srcs = ssl.c http.c http-auth.c auth-common.c library.c compat.c lzs.c m
lib_srcs_cisco = auth.c cstp.c
lib_srcs_juniper = oncp.c lzo.c auth-juniper.c
lib_srcs_globalprotect = gpst.c auth-globalprotect.c
lib_srcs_gnutls = gnutls.c gnutls_tpm.c
lib_srcs_gnutls = gnutls.c gnutls_tpm.c gnutls_tpm2.c
lib_srcs_openssl = openssl.c openssl-pkcs11.c
lib_srcs_win32 = tun-win32.c sspi.c
lib_srcs_posix = tun.c
......
......@@ -483,6 +483,14 @@ case "$ssl_library" in
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)'])
......
......@@ -561,7 +561,7 @@ static int get_cert_name(gnutls_x509_crt_t cert, char *name, size_t namelen)
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. */
......@@ -611,7 +611,7 @@ static int verify_signed_data(gnutls_pubkey_t pubkey, gnutls_privkey_t privkey,
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)
......@@ -901,7 +901,7 @@ static int load_certificate(struct openconnect_info *vpninfo)
{
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;
......@@ -1319,6 +1319,21 @@ static int load_certificate(struct openconnect_info *vpninfo)
#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-----")) ||
......@@ -1462,7 +1477,7 @@ static int load_certificate(struct openconnect_info *vpninfo)
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
......@@ -1516,7 +1531,7 @@ static int load_certificate(struct openconnect_info *vpninfo)
}
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,
......@@ -1693,7 +1708,7 @@ static int load_certificate(struct openconnect_info *vpninfo)
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,
......@@ -1704,7 +1719,7 @@ static int load_certificate(struct openconnect_info *vpninfo)
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);
......@@ -1741,7 +1756,7 @@ static int load_certificate(struct openconnect_info *vpninfo)
}
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
......@@ -2315,6 +2330,9 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final)
vpninfo->https_cred = NULL;
#ifdef HAVE_TROUSERS
release_tpm1_ctx(vpninfo);
#endif
#ifdef HAVE_TSS2
release_tpm2_ctx(vpninfo);
#endif
}
}
......
......@@ -28,6 +28,10 @@ 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);
int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata,
gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig);
void release_tpm2_ctx(struct openconnect_info *info);
char *get_gnutls_cipher(gnutls_session_t session);
#endif /* __OPENCONNECT_GNUTLS_H__ */
/*
* 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 */
......@@ -346,6 +346,7 @@ struct esp {
struct oc_pcsc_ctx;
struct oc_tpm1_ctx;
struct oc_tpm2_ctx;
struct openconnect_info {
const struct vpn_proto *proto;
......@@ -503,6 +504,9 @@ struct openconnect_info {
#ifdef HAVE_TROUSERS
struct oc_tpm1_ctx *tpm1;
#endif
#ifdef HAVE_TSS2
struct oc_tpm2_ctx *tpm2;
#endif
#endif /* OPENCONNECT_GNUTLS */
struct pin_cache *pin_cache;
struct keepalive_info ssl_times;
......
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