From e1f2bb72e6adc935ca897e7fe91ee9e3ccb8761f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 3 Oct 2018 15:46:26 +0100 Subject: [PATCH] Parse TPM2 ASN.1 blob Signed-off-by: David Woodhouse --- configure.ac | 20 ++++++++---- gnutls_tpm2.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 55376d46..36510062 100644 --- a/configure.ac +++ b/configure.ac @@ -484,17 +484,23 @@ case "$ssl_library" in 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]), []) + AC_CHECK_LIB([tss], [TSS_Create], [tss2inc=tss2 + tss2lib=tss], + AC_CHECK_LIB([TSS_Create], [ibmtss], [tss2inc=ibmtss + tss2lib=ibmtss], [])) + if test "$tss2lib" != ""; then + PKG_CHECK_MODULES(TASN1, libtasn1, [], [tss2lib=]) + fi + if test "$tss2lib" != ""; then + AC_CHECK_HEADER($tss2inc/tss.h, + [AC_DEFINE_UNQUOTED(HAVE_TSS2, $tss2inc, [TSS2 library]) + AC_SUBST(TSS2_LIBS, [-l$tss2lib])], []) fi AC_DEFINE(OPENCONNECT_GNUTLS, 1, [Using GnuTLS]) AC_SUBST(SSL_PC, [gnutls]) - AC_SUBST(SSL_LIBS, ['$(GNUTLS_LIBS)']) - AC_SUBST(SSL_CFLAGS, ['$(GNUTLS_CFLAGS)']) + AC_SUBST(SSL_LIBS, ['$(GNUTLS_LIBS) $(TASN1_LIBS) $(TSS2_LIBS)']) + AC_SUBST(SSL_CFLAGS, ['$(GNUTLS_CFLAGS) $(TASN1_CFLAGS)']) ;; *) diff --git a/gnutls_tpm2.c b/gnutls_tpm2.c index f7ef8266..0d640e15 100644 --- a/gnutls_tpm2.c +++ b/gnutls_tpm2.c @@ -22,7 +22,7 @@ #include #include "openconnect-internal.h" - +#include #include "gnutls.h" #ifdef HAVE_TSS2 @@ -31,12 +31,33 @@ struct oc_tpm2_ctx { }; +#include + +const asn1_static_node tpmkey_asn1_tab[] = { + { "TPMKey", 536875024, NULL }, + { NULL, 1073741836, NULL }, + { "TPMKey", 536870917, NULL }, + { "type", 1073741836, NULL }, + { "emptyAuth", 1610637316, NULL }, + { NULL, 2056, "0"}, + { "parent", 1610637315, NULL }, + { NULL, 2056, "1"}, + { "pubkey", 1610637319, NULL }, + { NULL, 2056, "2"}, + { "privkey", 7, NULL }, + { NULL, 0, NULL } +}; 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; + ASN1_TYPE tpmkey_def = ASN1_TYPE_EMPTY, tpmkey = ASN1_TYPE_EMPTY; + char value_buf[16]; + int value_buflen; + int emptyauth = 0; + unsigned int parent; err = gnutls_pem_base64_decode_alloc("TSS2 KEY BLOB", fdata, &asn1); if (err) { @@ -45,9 +66,74 @@ int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, gnutls_strerror(err)); return -EINVAL; } - free(asn1.data); + + err = asn1_array2tree(tpmkey_asn1_tab, &tpmkey_def, NULL); + if (err != ASN1_SUCCESS) { + vpn_progress(vpninfo, PRG_ERR, + _("Failed to create ASN.1 type for TPM2: %s\n"), + asn1_strerror(err)); + goto out_asn1; + } + + asn1_create_element(tpmkey_def, "TPMKey.TPMKey", &tpmkey); + err = asn1_der_decoding(&tpmkey, asn1.data, asn1.size, NULL); + if (err != ASN1_SUCCESS) { + vpn_progress(vpninfo, PRG_ERR, + _("Failed to decode TPM2 key ASN.1: %s\n"), + asn1_strerror(err)); + goto out_tpmkey; + } + asn1_print_structure(stdout, tpmkey, "", ASN1_PRINT_ALL); + + value_buflen = sizeof(value_buf); + err = asn1_read_value(tpmkey, "type", value_buf, &value_buflen); + if (err != ASN1_SUCCESS) { + vpn_progress(vpninfo, PRG_ERR, + _("Failed to identify type of TPM2 key: %s\n"), + asn1_strerror(err)); + goto out_tpmkey; + } + if (strcmp(value_buf, "2.23.133.10.2")) { + vpn_progress(vpninfo, PRG_ERR, + _("Unsupported TPM2 key OID: %s\n"), + value_buf); + goto out_tpmkey; + } + + value_buflen = sizeof(value_buf); + if (!asn1_read_value(tpmkey, "emptyAuth", value_buf, &value_buflen) || + !strcmp(value_buf, "TRUE")) + emptyauth = 1; + + memset(value_buf, 0, 4); + value_buflen = 4; + err = asn1_read_value(tpmkey, "parent", value_buf, &value_buflen); + if (err == ASN1_ELEMENT_NOT_FOUND) + parent = TPM_RH_OWNER; + else if (err != ASN1_SUCCESS) { + vpn_progress(vpninfo, PRG_ERR, + _("Failed to parse TPM2 key parent: %s\n"), + asn1_strerror(err)); + goto out_tpmkey; + } else { + int i; + parent = 0; + + for (i = 0; i < value_buflen; i++) + parent |= value_buf[value_buflen - i - 1] << (8 * i); + } + vpn_progress(vpninfo, PRG_DEBUG, + _("Parsed TPM2 key with parent %x, emptyauth %d\n"), + parent, emptyauth); + vpn_progress(vpninfo, PRG_ERR, _("TPM2 not really implemented yet\n")); + + out_tpmkey: + asn1_delete_structure(&tpmkey); + asn1_delete_structure(&tpmkey_def); + out_asn1: + free(asn1.data); return -EINVAL; }