Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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: David Woodhouse <dwmw2@infradead.org>
  • Loading branch information
dwmw2 committed Oct 3, 2018
1 parent 60109f0 commit 584cbb0
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions configure.ac
Expand Up @@ -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)'])
Expand Down
34 changes: 26 additions & 8 deletions gnutls.c
Expand Up @@ -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. */
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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-----")) ||
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
Expand Down
4 changes: 4 additions & 0 deletions gnutls.h
Expand Up @@ -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__ */
60 changes: 60 additions & 0 deletions gnutls_tpm2.c
@@ -0,0 +1,60 @@
/*
* 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 */
4 changes: 4 additions & 0 deletions openconnect-internal.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 584cbb0

Please sign in to comment.