Created libtpmtss library handling access to v1.2 and v2.0 TPMs
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 2 Jun 2016 21:01:11 +0000 (23:01 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 22 Jun 2016 13:33:43 +0000 (15:33 +0200)
15 files changed:
conf/options/aikgen2.opt [deleted file]
conf/options/aikpub2.opt [new file with mode: 0644]
configure.ac
src/Makefile.am
src/aikgen/Makefile.am
src/aikgen/aikgen.c
src/aikpub2/Makefile.am
src/aikpub2/aikpub2.c
src/libtpmtss/Makefile.am [new file with mode: 0644]
src/libtpmtss/tpm_tss.c [new file with mode: 0644]
src/libtpmtss/tpm_tss.h [new file with mode: 0644]
src/libtpmtss/tpm_tss_trousers.c [new file with mode: 0644]
src/libtpmtss/tpm_tss_trousers.h [new file with mode: 0644]
src/libtpmtss/tpm_tss_tss2.c [new file with mode: 0644]
src/libtpmtss/tpm_tss_tss2.h [new file with mode: 0644]

diff --git a/conf/options/aikgen2.opt b/conf/options/aikgen2.opt
deleted file mode 100644 (file)
index 2acab4e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-aikgen2.load =
-       Plugins to load in aikgen2 tool.
diff --git a/conf/options/aikpub2.opt b/conf/options/aikpub2.opt
new file mode 100644 (file)
index 0000000..6a755d2
--- /dev/null
@@ -0,0 +1,2 @@
+aikpub2.load =
+       Plugins to load in aikpub2 tool.
index f067fa7..3777a48 100644 (file)
@@ -62,8 +62,6 @@ ARG_WITH_SUBST([routing-table],      [220], [set routing table to use for IPsec
 ARG_WITH_SUBST([routing-table-prio], [220], [set priority for IPsec routing table])
 ARG_WITH_SUBST([ipsec-script],       [ipsec], [change the name of the ipsec script])
 ARG_WITH_SUBST([fips-mode],          [0], [set openssl FIPS mode: disabled(0), enabled(1), Suite B enabled(2)])
-
-ARG_WITH_SET([tss],                  [no], [set implementation of the Trusted Computing Group's Software Stack (TSS). Currently the only supported value is "trousers"])
 ARG_WITH_SET([capabilities],         [no], [set capability dropping library. Currently supported values are "libcap" and "native"])
 ARG_WITH_SET([mpz_powm_sec],         [yes], [use the more side-channel resistant mpz_powm_sec in libgmp, if available])
 ARG_WITH_SET([dev-headers],          [no], [install strongSwan development headers to directory.])
@@ -303,6 +301,9 @@ ARG_ENABL_SET([python-eggs],    [enable build of provided python eggs.])
 ARG_ENABL_SET([python-eggs-install],[enable installation of provided python eggs.])
 ARG_ENABL_SET([perl-cpan],      [enable build of provided perl CPAN module.])
 ARG_ENABL_SET([perl-cpan-install],[enable installation of provided CPAN module.])
+ARG_ENABL_SET([tss-trousers],   [enable the use of the TrouSerS Trusted Software Stack])
+ARG_ENABL_SET([tss-tss2],       [enable the use of the TSS 2.0 Trusted Software Stack])
+
 # compile options
 ARG_ENABL_SET([coverage],       [enable lcov coverage report generation.])
 ARG_ENABL_SET([leak-detective], [enable malloc hooks to find memory leaks.])
@@ -961,16 +962,16 @@ if test x$systemd = xtrue; then
        )
 fi
 
-if test x$tss = xtrousers; then
+if test x$tss_trousers = xtrue; then
        AC_CHECK_LIB([tspi],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([TrouSerS library libtspi not found])],[])
        AC_CHECK_HEADER([trousers/tss.h],,[AC_MSG_ERROR([TrouSerS header trousers/tss.h not found!])])
-       AC_DEFINE([TSS_TROUSERS], [], [use TrouSerS library libtspi as TSS implementation])
+       AC_DEFINE([TSS_TROUSERS], [], [use TrouSerS library libtspi])
 fi
 
-if test x$tss = xtss2; then
+if test x$tss_tss2 = xtrue; then
        AC_CHECK_LIB([tss2],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([TTS 2.0 library libtss2 not found])],[])
        AC_CHECK_HEADER([tss2/tpm20.h],,[AC_MSG_ERROR([TSS 2.0 header tss2/tpm20.h not found!])])
-       AC_DEFINE([TSS_TSS2], [], [use TSS 2.0 library libtss2 as TSS implementation])
+       AC_DEFINE([TSS_TSS2], [], [use TSS 2.0 library libtss2])
 fi
 if test x$imv_swid = xtrue; then
        PKG_CHECK_MODULES(json, [json-c], [],
@@ -1623,6 +1624,7 @@ AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue)
 AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
 AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue)
 AM_CONDITIONAL(USE_LIBPTTLS, test x$tnc_tnccs = xtrue)
+AM_CONDITIONAL(USE_LIBTPMTSS, test x$tss_trousers = xtrue -o x$tss_tss2 = xtrue -o x$aikgen = xtrue -o x$aikpub2 = xtrue )
 AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue)
 AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$stroke = xtrue -o x$scepclient = xtrue -o x$conftest = xtrue)
 AM_CONDITIONAL(USE_LIBCAP, test x$capabilities = xlibcap)
@@ -1632,8 +1634,8 @@ AM_CONDITIONAL(USE_SIMAKA, test x$simaka = xtrue)
 AM_CONDITIONAL(USE_TLS, test x$tls = xtrue)
 AM_CONDITIONAL(USE_RADIUS, test x$radius = xtrue)
 AM_CONDITIONAL(USE_IMCV, test x$imcv = xtrue)
-AM_CONDITIONAL(USE_TROUSERS, test x$tss = xtrousers -o x$aikgen = xtrue)
-AM_CONDITIONAL(USE_TSS2, test x$tss = xtss2 -o x$aikpub2 = xtrue)
+AM_CONDITIONAL(USE_TROUSERS, test x$tss_trousers = xtrue -o x$aikgen = xtrue)
+AM_CONDITIONAL(USE_TSS2, test x$tss_tss2 = xtrue -o x$aikpub2 = xtrue)
 AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue)
 AM_CONDITIONAL(USE_SILENT_RULES, test x$enable_silent_rules = xyes)
 AM_CONDITIONAL(COVERAGE, test x$coverage = xtrue)
@@ -1874,6 +1876,7 @@ AC_CONFIG_FILES([
        src/libcharon/plugins/attr/Makefile
        src/libcharon/plugins/attr_sql/Makefile
        src/libcharon/tests/Makefile
+       src/libtpmtss/Makefile
        src/stroke/Makefile
        src/ipsec/Makefile
        src/starter/Makefile
index 4e4dfca..938335e 100644 (file)
@@ -32,6 +32,10 @@ if USE_LIBPTTLS
   SUBDIRS += libpttls
 endif
 
+if USE_LIBTPMTSS
+  SUBDIRS += libtpmtss
+endif
+
 if USE_IMCV
   SUBDIRS += libimcv
 endif
index dc59d20..860a8f7 100644 (file)
@@ -2,14 +2,13 @@ bin_PROGRAMS = aikgen
 
 aikgen_SOURCES = aikgen.c
 
-aikgen_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
-aikgen.o :     $(top_builddir)/config.status
+aikgen_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
+       $(top_builddir)/src/libtpmtss/libtpmtss.la
 
-if USE_TROUSERS
-  aikgen_LDADD += -ltspi
-endif
+aikgen.o :     $(top_builddir)/config.status
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/libstrongswan \
+       -I$(top_srcdir)/src/libtpmtss \
        -DIPSEC_CONFDIR=\"${sysconfdir}\" \
        -DPLUGINS=\""${aikgen_plugins}\""
index 6d04fc1..22e80ba 100644 (file)
@@ -1,38 +1,25 @@
 /*
- * Copyright (C) 2014 Andreas Steffen
+ * Copyright (C) 2014-2016 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
- * Copyright (c) 2008 Hal Finney
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
  *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
+ * 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 General Public License
+ * for more details.
  */
 
+#include "tpm_tss.h"
+
 #include <library.h>
 #include <utils/debug.h>
 #include <utils/optionsfrom.h>
 #include <credentials/certificates/x509.h>
 #include <credentials/keys/public_key.h>
-#include <asn1/oid.h>
-#include <asn1/asn1.h>
-
-#include <trousers/tss.h>
-#include <trousers/trousers.h>
 
 #include <syslog.h>
 #include <getopt.h>
@@ -47,9 +34,6 @@
 /* default name of AIK public key */
 #define DEFAULT_FILENAME_AIKPUBKEY             AIK_DIR "aikPub.der"
 
-/* size in bytes of a TSS AIK public key blob */
-#define AIK_PUBKEY_BLOB_SIZE                   284
-
 /* logging */
 static bool log_to_stderr = TRUE;
 static bool log_to_syslog = TRUE;
@@ -64,9 +48,7 @@ public_key_t *ca_pubkey;
 chunk_t ca_modulus;
 chunk_t aik_pubkey;
 chunk_t aik_keyid;
-
-/* TPM context */
-TSS_HCONTEXT  hContext;
+tpm_tss_t *tpm;
 
 /**
  * logging function for aikgen
@@ -128,12 +110,13 @@ static void init_log(const char *program)
 /**
  * @brief exit aikgen
  *
- * @param status 0 = OK, 1 = general discomfort
+ * @param status 0 = OK, -1 = general discomfort
  */
 static void exit_aikgen(err_t message, ...)
 {
        int status = 0;
 
+       DESTROY_IF(tpm);
        DESTROY_IF(cacert);
        DESTROY_IF(ca_pubkey);
        free(ca_modulus.ptr);
@@ -141,13 +124,6 @@ static void exit_aikgen(err_t message, ...)
        free(aik_keyid.ptr);
        options->destroy(options);
 
-       /* clean up TPM context */
-       if (hContext)
-       {
-               Tspi_Context_FreeMemory(hContext, NULL);
-               Tspi_Context_Close(hContext);
-       }
-
        /* print any error message to stderr */
        if (message != NULL && *message != '\0')
        {
@@ -158,7 +134,7 @@ static void exit_aikgen(err_t message, ...)
                vsnprintf(m, sizeof(m), message, args);
                va_end(args);
 
-               fprintf(stderr, "error: %s\n", m);
+               fprintf(stderr, "aikgen error: %s\n", m);
                status = -1;
        }
        library_deinit();
@@ -178,7 +154,7 @@ static void usage(const char *message)
                " [--aikblob <filename>] [--aikpubkey <filename>] \n"
                "              [--idreq <filename>] [--force]"
                " [--quiet] [--debug <level>]\n"
-               "       aikgen --help\n"
+               "       aikgen  --help\n"
                "\n"
                "Options:\n"
                " --cacert (-c)     certificate of [privacy] CA\n"
@@ -216,25 +192,9 @@ int main(int argc, char *argv[])
        bool force = FALSE;
        chunk_t identity_req;
        chunk_t aik_blob;
-       chunk_t aik_pubkey_blob;
        chunk_t aik_modulus;
        chunk_t aik_exponent;
 
-       /* TPM variables */
-       TSS_RESULT   result;
-       TSS_HTPM     hTPM;
-       TSS_HKEY     hSRK;
-       TSS_HKEY     hPCAKey;
-       TSS_HPOLICY  hSrkPolicy;
-       TSS_HPOLICY  hTPMPolicy;
-       TSS_HKEY     hIdentKey;
-       TSS_UUID     SRK_UUID = TSS_UUID_SRK;
-       BYTE         secret[] = TSS_WELL_KNOWN_SECRET;
-       BYTE        *IdentityReq;
-       UINT32       IdentityReqLen;
-       BYTE        *blob;
-       UINT32       blobLen;
-
        atexit(library_deinit);
        if (!library_init(NULL, "aikgen"))
        {
@@ -370,105 +330,29 @@ int main(int argc, char *argv[])
        if (ca_pubkey->get_type(ca_pubkey) != KEY_RSA ||
                ca_pubkey->get_keysize(ca_pubkey) != 2048)
        {
-               exit_aikgen("ca public key must be RSA 2048 but is %N %d",
+               exit_aikgen("CA public key must be RSA 2048 but is %N %d",
                                         key_type_names, ca_pubkey->get_type(ca_pubkey),
                                         ca_pubkey->get_keysize(ca_pubkey));
        }
        if (!ca_pubkey->get_encoding(ca_pubkey, PUBKEY_RSA_MODULUS, &ca_modulus))
        {
-               exit_aikgen("could not extract RSA modulus from ca public key");
+               exit_aikgen("could not extract RSA modulus from CA public key");
        }
 
-       /* initialize TSS context and connect to it */
-       result = Tspi_Context_Create(&hContext);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_Context_Create", result);
-       }
-       result = Tspi_Context_Connect(hContext, NULL);
-       if (result != TSS_SUCCESS)
+       /* try to find a TPM 1.2 */
+       tpm = tpm_tss_probe(TPM_VERSION_1_2);
+       if (!tpm)
        {
-               exit_aikgen("tss 0x%x on Tspi_Context_Connect", result);
+               exit_aikgen("no TPM 1.2 found");
        }
 
-       /* get SRK plus SRK policy and set SRK secret */
-       result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM,
-                                                                               SRK_UUID, &hSRK);
-       if (result != TSS_SUCCESS)
+       if (!tpm->generate_aik(tpm, ca_modulus, &aik_blob, &aik_pubkey,
+                                                 &identity_req))
        {
-               exit_aikgen("tss 0x%x on Tspi_Context_LoadKeyByUUID for SRK", result);
-       }
-       result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_GetPolicyObject for SRK", result);
-       }
-       result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_Policy_SetSecret for SRK", result);
-       }
-
-       /* get TPM plus TPM policy and set TPM secret */
-       result = Tspi_Context_GetTpmObject (hContext, &hTPM);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_Context_GetTpmObject", result);
-       }
-       result = Tspi_GetPolicyObject(hTPM, TSS_POLICY_USAGE, &hTPMPolicy);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_GetPolicyObject for TPM", result);
-       }
-       result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_Policy_SetSecret for TPM", result);
-       }
-
-       /* create context for a 2048 bit AIK */
-       result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
-                                       TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048 |
-                                       TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE, &hIdentKey);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_Context_CreateObject for key", result);
+               exit_aikgen("could not generate AIK");
        }
 
-       /* create context for the Privacy CA public key and assign modulus */
-       result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
-                                       TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048, &hPCAKey);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_Context_CreateObject for PCA", result);
-       }
-       result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO,
-                                       TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, ca_modulus.len,
-                                       ca_modulus.ptr);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_SetAttribData for PCA modulus", result);
-       }
-       result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO,
-                                       TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_SetAttribUint32 for PCA "
-                                       "encryption scheme", result);
-       }
-
-       /* generate AIK */
-       DBG1(DBG_LIB, "Generating identity key...");
-       result = Tspi_TPM_CollateIdentityRequest(hTPM, hSRK, hPCAKey, 0, NULL,
-                                       hIdentKey, TSS_ALG_AES, &IdentityReqLen, &IdentityReq);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_TPM_CollateIdentityRequest", result);
-       }
-       identity_req = chunk_create(IdentityReq, IdentityReqLen);
-       DBG3(DBG_LIB, "Identity Request: %B", &identity_req);
-
-       /* optionally output identity request encrypted with ca public key */
+       /* optionally output identity request encrypted with CA public key */
        if (idreq_filename)
        {
                if (!chunk_write(identity_req, idreq_filename, 0022, force))
@@ -480,24 +364,7 @@ int main(int argc, char *argv[])
                                           idreq_filename, identity_req.len);
        }
 
-       /* load identity key */
-       result = Tspi_Key_LoadKey (hIdentKey, hSRK);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_Key_LoadKey for AIK\n", result);
-       }
-
-       /* output AIK private key in TSS blob format */
-       result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
-                                       TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_GetAttribData for private key blob",
-                                        result);
-       }
-       aik_blob = chunk_create(blob, blobLen);
-       DBG3(DBG_LIB, "AIK private key blob: %B", &aik_blob);
-
+       /* output AIK private key blob */
        if (!chunk_write(aik_blob, aikblob_filename, 0022, force))
        {
                exit_aikgen("could not write AIK blob file '%s': %s",
@@ -506,32 +373,7 @@ int main(int argc, char *argv[])
        DBG1(DBG_LIB, "AIK private key blob written to '%s' (%u bytes)",
                                   aikblob_filename, aik_blob.len);
 
-       /* output AIK Public Key in TSS blob format */
-       result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
-                                       TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blobLen, &blob);
-       if (result != TSS_SUCCESS)
-       {
-               exit_aikgen("tss 0x%x on Tspi_GetAttribData for public key blob",
-                                        result);
-       }
-       aik_pubkey_blob = chunk_create(blob, blobLen);
-       DBG3(DBG_LIB, "AIK public key blob: %B", &aik_pubkey_blob);
-
-       /* create a trusted AIK public key */
-       if (aik_pubkey_blob.len != AIK_PUBKEY_BLOB_SIZE)
-       {
-               exit_aikgen("AIK public key is not in TSS blob format");
-       }
-       aik_modulus = chunk_skip(aik_pubkey_blob, AIK_PUBKEY_BLOB_SIZE - 256);
-       aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
-
-       /* output subjectPublicKeyInfo encoding of AIK public key */
-       if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL,
-                                       &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
-                                       CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
-       {
-               exit_aikgen("subjectPublicKeyInfo encoding of AIK key failed");
-       }
+       /* output AIK public key */
        if (!chunk_write(aik_pubkey, aikpubkey_filename, 0022, force))
        {
                exit_aikgen("could not write AIK public key file '%s': %s",
index c43435f..a9ab138 100644 (file)
@@ -2,14 +2,14 @@ bin_PROGRAMS = aikpub2
 
 aikpub2_SOURCES = aikpub2.c
 
-aikpub2_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
-aikpub2.o :    $(top_builddir)/config.status
+aikpub2_LDADD = \
+       $(top_builddir)/src/libstrongswan/libstrongswan.la \
+       $(top_builddir)/src/libtpmtss/libtpmtss.la
 
-if USE_TSS2
-  aikpub2_LDADD += -ltctisocket -ltss2
-endif
+aikpub2.o :    $(top_builddir)/config.status
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/libstrongswan \
+       -I$(top_srcdir)/src/libtpmtss \
        -DIPSEC_CONFDIR=\"${sysconfdir}\" \
        -DPLUGINS=\""${aikgen_plugins}\""
index feaca72..fea58ed 100644 (file)
  * for more details.
  */
 
+#include "tpm_tss.h"
+
 #include <library.h>
 #include <utils/debug.h>
 #include <utils/optionsfrom.h>
-#include <asn1/asn1.h>
-#include <asn1/oid.h>
-
-#include <tss2/tpm20.h>
-#include <tcti/tcti_socket.h>
 
 #include <syslog.h>
 #include <getopt.h>
@@ -29,7 +26,7 @@
 /* default directory where AIK keys are stored */
 #define AIK_DIR                                                        IPSEC_CONFDIR "/pts/"
 
-/* default name of AIK private key blob */
+/* default name of AIK public key blob */
 #define DEFAULT_FILENAME_AIKPUBKEY             AIK_DIR "aikPub.der"
 
 /* logging */
@@ -40,8 +37,6 @@ static level_t default_loglevel = 1;
 /* options read by optionsfrom */
 options_t *options;
 
-/* global variables */
-chunk_t aik_blob;
 chunk_t aik_pubkey;
 chunk_t aik_keyid;
 
@@ -105,13 +100,12 @@ static void init_log(const char *program)
 /**
  * @brief exit aikgen
  *
- * @param status 0 = OK, 1 = general discomfort
+ * @param status 0 = OK, -1 = general discomfort
  */
 static void exit_aikpub2(err_t message, ...)
 {
        int status = 0;
 
-       free(aik_blob.ptr);
        free(aik_pubkey.ptr);
        free(aik_keyid.ptr);
        options->destroy(options);
@@ -126,7 +120,7 @@ static void exit_aikpub2(err_t message, ...)
                vsnprintf(m, sizeof(m), message, args);
                va_end(args);
 
-               fprintf(stderr, "error: %s\n", m);
+               fprintf(stderr, "aikpub2 error: %s\n", m);
                status = -1;
        }
        library_deinit();
@@ -142,12 +136,11 @@ static void exit_aikpub2(err_t message, ...)
 static void usage(const char *message)
 {
        fprintf(stderr,
-               "Usage: aikpub2 [--in <filename>|--handle <handle>] --out <filename>\n"
+               "Usage: aikpub2  --handle <handle> --out <filename>\n"
                "               [--force] [--quiet] [--debug <level>]\n"
-               "       aikpub2 --help\n"
+               "       aikpub2  --help\n"
                "\n"
                "Options:\n"
-               " --in (-i)         TSS 2.0 AIK public key blob\n"
                " --handle (-H)     TSS 2.0 AIK object handle\n"
                " --out (-o)        AIK public key in PKCS #1 format\n"
                " --force (-f)      force to overwrite existing files\n"
@@ -160,105 +153,9 @@ static void usage(const char *message)
        exit_aikpub2(message);
 }
 
-/**
- * Some symbols required by libtctisocket
- */
-FILE *outFp;
-uint8_t simulator = 1;
-
-int TpmClientPrintf (uint8_t type, const char *format, ...)
-{
-    return 0;
-}
 
 /**
- * read the public key portion of a TSS 2.0 AIK key from NVRAM
- */
-void read_public(TPMI_DH_OBJECT handle, TPM2B_PUBLIC *public)
-{
-       size_t tcti_context_size;
-       uint32_t sys_context_size, rval;
-
-       TCTI_SOCKET_CONF rm_if_config = { DEFAULT_HOSTNAME,
-                                                                         DEFAULT_RESMGR_TPM_PORT
-                                                                       };
-
-       TSS2_ABI_VERSION abi_version = { TSSWG_INTEROP,
-                                                                        TSS_SAPI_FIRST_FAMILY,
-                                                                        TSS_SAPI_FIRST_LEVEL,
-                                                                        TSS_SAPI_FIRST_VERSION
-                                                                  };
-
-       TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } };
-       TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } };
-
-       TSS2_TCTI_CONTEXT *tcti_context;
-       TSS2_SYS_CONTEXT  *sys_context;
-
-       TPMS_AUTH_RESPONSE session_data;
-       TSS2_SYS_RSP_AUTHS sessions_data;
-       TPMS_AUTH_RESPONSE *session_data_array[1];
-
-       session_data_array[0]  = &session_data;
-       sessions_data.rspAuths = &session_data_array[0];
-       sessions_data.rspAuthsCount = 1;
-
-       /* determine size of tcti context */
-       rval = InitSocketTcti(NULL, &tcti_context_size, &rm_if_config, 0);
-       if (rval != TSS2_RC_SUCCESS)
-       {
-               exit_aikpub2("could not get tcti_context size: 0x%06x", rval);
-       }
-
-       /* allocate memory for tcti context */
-       tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
-
-       /* initialize tcti context */
-       rval = InitSocketTcti(tcti_context, &tcti_context_size, &rm_if_config, 0);
-       if (rval != TSS2_RC_SUCCESS)
-       {
-               exit_aikpub2("could not get tcti_context: 0x%06x", rval);
-       }
-
-       /* determine size of sys context */
-       sys_context_size = Tss2_Sys_GetContextSize(0);
-
-       /* allocate memory for sys context */
-       sys_context = malloc(sys_context_size);
-
-       /* initialize sys context */
-       rval = Tss2_Sys_Initialize(sys_context, sys_context_size, tcti_context,
-                                                          &abi_version);
-       if (rval != TSS2_RC_SUCCESS)
-       {
-               TeardownSocketTcti(tcti_context);
-               exit_aikpub2("could not get sys_context: 0x%06x", rval);
-       }
-
-       /* always send simulator platform command, ignored by true RM */
-       PlatformCommand(tcti_context ,MS_SIM_POWER_ON );
-       PlatformCommand(tcti_context, MS_SIM_NV_ON );
-
-       /* read public key for a given object handle from TPM 2.0 NVRAM */
-       rval = Tss2_Sys_ReadPublic(sys_context, handle, 0, public, &name,
-                                                          &qualified_name, &sessions_data);
-
-       PlatformCommand(tcti_context, MS_SIM_POWER_OFF);
-
-       /* clean up connection to TPM 2.0 */
-       TeardownSocketTcti(tcti_context);
-       Tss2_Sys_Finalize(sys_context);
-       free(sys_context);
-
-       if (rval != TPM_RC_SUCCESS)
-       {
-               exit_aikpub2("could not read TSS 2.0 public key from handle 0x%08x:"
-                                        " 0x%06x", handle, rval);
-       }
-}
-
-/**
- * @brief main of aikpub2 which generates an Attestation Identity Key (AIK)
+ * @brief main of aikpub2 which extracts an Attestation Identity Key (AIK)
  *
  * @param argc number of arguments
  * @param argv pointer to the argument values
@@ -269,15 +166,11 @@ int main(int argc, char *argv[])
        extern char * optarg;
        extern int optind;
 
-       uint32_t aik_handle = 0;
-       char *aik_in_filename   = NULL;
        char *aik_out_filename = DEFAULT_FILENAME_AIKPUBKEY;
-       chunk_t *aik_mapped;
+       uint32_t aik_handle = 0;
        bool force = FALSE;
        hasher_t *hasher;
-
-       /* TSS 2.0 variables */
-       TPM2B_PUBLIC public = { { 0, } };
+       tpm_tss_t *tpm;
 
        atexit(library_deinit);
        if (!library_init(NULL, "aikpub2"))
@@ -331,10 +224,6 @@ int main(int argc, char *argv[])
                                aik_handle = strtoll(optarg, NULL, 16);
                                continue;
 
-                       case 'i':       /* --in <filename> */
-                               aik_in_filename = optarg;
-                               continue;
-
                        case 'o':       /* --out <filename> */
                                aik_out_filename = optarg;
                                continue;
@@ -365,90 +254,26 @@ int main(int argc, char *argv[])
        {
                exit_aikpub2("plugin loading failed");
        }
-       if (!aik_in_filename && !aik_handle)
+       if (!aik_handle)
        {
-               usage("either --in or --handle option is required");
+               usage("--handle option is required");
        }
 
-       if (aik_handle)
-       {
-               /* read public key blob directly from TPM 2.0 */
-               read_public(aik_handle, &public);
-               aik_blob = chunk_clone(chunk_create((u_char*)&public, sizeof(public)));
-       }
-       else
+       /* try to find a TPM 2.0 */
+       tpm = tpm_tss_probe(TPM_VERSION_2_0);
+       if (!tpm)
        {
-               /* read stored TPM 2.0 public key blob from a file */
-               aik_mapped = chunk_map(aik_in_filename, FALSE);
-               if (!aik_mapped)
-               {
-                       exit_aikpub2("could not read TSS 2.0 public key file '%s'",
-                                                 aik_in_filename);
-               }
-               aik_blob = chunk_clone(*aik_mapped);
-               chunk_unmap(aik_mapped);
-
-               if (aik_blob.len != sizeof(TPM2B_PUBLIC))
-               {
-                       exit_aikpub2("size of aikblob is not %d bytes",
-                                                 sizeof(TPM2B_PUBLIC));
-               }
-               public = *(TPM2B_PUBLIC*)aik_blob.ptr;
+               exit_aikpub2("no TPM 2.0 found");       
        }
-       DBG3(DBG_LIB, "TSS 2.0 AIK blob: %B", &aik_blob);
 
+       /* get AIK public key from TPM */
+       aik_pubkey = tpm->get_public(tpm, aik_handle);
+       tpm->destroy(tpm);
 
-       switch (public.t.publicArea.type)
+       /* exit if AIK public key retrieval failed */
+       if (aik_pubkey.len == 0)
        {
-               case TPM_ALG_RSA:
-               {
-                       TPM2B_PUBLIC_KEY_RSA *rsa;
-                       chunk_t aik_exponent, aik_modulus;
-
-                       rsa = &public.t.publicArea.unique.rsa;
-                       aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
-                       aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
-
-                       /* subjectPublicKeyInfo encoding of AIK RSA key */
-                       if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
-                                       NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
-                                       CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
-                       {
-                               exit_aikpub2("subjectPublicKeyInfo encoding of AIK key failed");
-                       }
-                       break;
-               }
-               case TPM_ALG_ECC:
-               {
-                       TPMS_ECC_POINT *ecc;
-                       chunk_t ecc_point;
-                       uint8_t *pos;
-
-                       ecc = &public.t.publicArea.unique.ecc;
-
-                       /* allocate space for bit string */
-                       pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
-                                                                       2 + ecc->x.t.size + ecc->y.t.size);
-                       /* bit string length is a multiple of octets */
-                       *pos++ = 0x00;
-                       /* uncompressed ECC point format */
-                       *pos++ = 0x04;
-                       /* copy x coordinate of ECC point */
-                       memcpy(pos, ecc->x.t.buffer, ecc->x.t.size);
-                       pos += ecc->x.t.size;
-                       /* copy y coordinate of ECC point */
-                       memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
-                       /* subjectPublicKeyInfo encoding of AIK ECC key */
-                       aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
-                                                       asn1_wrap(ASN1_SEQUENCE, "mm",
-                                                               asn1_build_known_oid(OID_EC_PUBLICKEY),
-                                                               asn1_build_known_oid(ecc->x.t.size == 32 ?
-                                                                               OID_PRIME256V1 : OID_SECT384R1)),
-                                                       ecc_point);
-                       break;
-               }
-               default:
-                       exit_aikpub2("unsupported key type");
+               exit_aikpub2("retrieval of AIK public key failed");
        }
 
        /* store AIK subjectPublicKeyInfo to file */
diff --git a/src/libtpmtss/Makefile.am b/src/libtpmtss/Makefile.am
new file mode 100644 (file)
index 0000000..94058bc
--- /dev/null
@@ -0,0 +1,23 @@
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/src/libstrongswan
+
+AM_LDFLAGS = \
+       -no-undefined
+
+ipseclib_LTLIBRARIES = libtpmtss.la
+libtpmtss_la_SOURCES = \
+       tpm_tss.h tpm_tss.c \
+       tpm_tss_trousers.h tpm_tss_trousers.c \
+       tpm_tss_tss2.h tpm_tss_tss2.c
+
+libtpmtss_la_LIBADD = \
+       $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+if USE_TSS2
+libtpmtss_la_LIBADD += -ltctisocket -ltss2
+endif
+
+if USE_TROUSERS
+libtpmtss_la_LIBADD += -ltspi
+endif
+
diff --git a/src/libtpmtss/tpm_tss.c b/src/libtpmtss/tpm_tss.c
new file mode 100644 (file)
index 0000000..687f9f3
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 General Public License
+ * for more details.
+ */
+
+#include "tpm_tss.h"
+#include "tpm_tss_tss2.h"
+#include "tpm_tss_trousers.h"
+
+typedef tpm_tss_t*(*tpm_tss_create)();
+
+/**
+ * See header.
+ */
+tpm_tss_t *tpm_tss_probe(tpm_version_t version)
+{
+       tpm_tss_create stacks[] = {
+               tpm_tss_tss2_create,
+               tpm_tss_trousers_create,
+       };
+       tpm_tss_t *tpm;
+       int i;
+
+       for (i = 0; i < countof(stacks); i++)
+       {
+               tpm = stacks[i]();
+               if (tpm)
+               {
+                       if (version == TPM_VERSION_ANY || version == tpm->get_version(tpm))
+                       {
+                               return tpm;
+                       }
+               }
+       }
+       return NULL;
+}
diff --git a/src/libtpmtss/tpm_tss.h b/src/libtpmtss/tpm_tss.h
new file mode 100644 (file)
index 0000000..1442cc4
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tpm_tss tpm_tss
+ * @{ @ingroup libtpmtss
+ */
+
+#ifndef TPM_TSS_H_
+#define TPM_TSS_H_
+
+#include <library.h>
+
+typedef enum tpm_version_t tpm_version_t;
+typedef struct tpm_tss_t tpm_tss_t;
+
+/**
+ * TPM Versions
+ */
+enum tpm_version_t {
+       TPM_VERSION_ANY,
+       TPM_VERSION_1_2,
+       TPM_VERSION_2_0,
+};
+
+/**
+ * TPM access via TSS public interface
+ */
+struct tpm_tss_t {
+
+       /**
+        * Get TPM version supported by TSS
+        *
+        * @return              TPM version
+        */
+       tpm_version_t (*get_version)(tpm_tss_t *this);
+
+       /**
+        * Generate AIK key pair bound to TPM (TPM 1.2 only)
+        *
+        * @param ca_modulus    RSA modulus of CA public key
+        * @param aik_blob              AIK private key blob
+        * @param aik_pubkey    AIK public key
+        * @return                              TRUE if AIK key generation succeeded
+        */
+       bool (*generate_aik)(tpm_tss_t *this, chunk_t ca_modulus,
+                                                chunk_t *aik_blob, chunk_t *aik_pubkey,
+                                                chunk_t *identity_req);
+
+       /**
+        * Get public key from TPM using its object handle (TPM 2.0 only)
+        *
+        * @param handle        key object handle
+        * @return                      public key in PKCS#1 format
+        */
+       chunk_t (*get_public)(tpm_tss_t *this, uint32_t handle);
+
+       /**
+        * Destroy a tpm_tss_t.
+        */
+       void (*destroy)(tpm_tss_t *this);
+};
+
+/**
+ * Create a tpm_tss instance.
+ *
+ * @param version      TPM version that must be supported by TSS
+ */
+tpm_tss_t *tpm_tss_probe(tpm_version_t version);
+
+#endif /** TPM_TSS_H_ @}*/
diff --git a/src/libtpmtss/tpm_tss_trousers.c b/src/libtpmtss/tpm_tss_trousers.c
new file mode 100644 (file)
index 0000000..99d4132
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (c) 2008 Hal Finney
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "tpm_tss_trousers.h"
+
+#ifdef TSS_TROUSERS
+
+#include <trousers/tss.h>
+#include <trousers/trousers.h>
+
+#define LABEL  "TPM 1.2 -"
+
+/* size in bytes of a TSS AIK public key blob */
+#define AIK_PUBKEY_BLOB_SIZE                   284
+
+typedef struct private_tpm_tss_trousers_t private_tpm_tss_trousers_t;
+
+/**
+ * Private data of an tpm_tss_trousers_t object.
+ */
+struct private_tpm_tss_trousers_t {
+
+       /**
+        * Public tpm_tss_trousers_t interface.
+        */
+       tpm_tss_t public;
+
+       /**
+        * TSS context
+        */
+       TSS_HCONTEXT hContext;
+
+};
+
+/**
+ * Initialize TSS context
+ */
+static bool initialize_context(private_tpm_tss_trousers_t *this)
+{
+       TSS_HTPM hTPM;
+       TSS_RESULT result;
+
+       result = Tspi_Context_Create(&this->hContext);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s could not created context: 0x%x", LABEL, result);
+               return FALSE;
+       }
+
+       result = Tspi_Context_Connect(this->hContext, NULL);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s could not connect with context: 0x%x", LABEL, result);
+               return FALSE;
+       }
+
+       result = Tspi_Context_GetTpmObject (this->hContext, &hTPM);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s could not get TPM object: 0x%x", LABEL, result);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+/**
+ * Finalize TSS context
+ */
+static void finalize_context(private_tpm_tss_trousers_t *this)
+{
+       if (this->hContext)
+       {
+               Tspi_Context_FreeMemory(this->hContext, NULL);
+               Tspi_Context_Close(this->hContext);
+       }
+}
+
+METHOD(tpm_tss_t, get_version, tpm_version_t,
+       private_tpm_tss_trousers_t *this)
+{
+       return TPM_VERSION_1_2;
+}
+
+METHOD(tpm_tss_t, generate_aik, bool,
+       private_tpm_tss_trousers_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
+       chunk_t *aik_pubkey, chunk_t *identity_req)
+{
+       chunk_t aik_pubkey_blob;
+       chunk_t aik_modulus;
+       chunk_t aik_exponent;
+
+       TSS_RESULT   result;
+       TSS_HTPM     hTPM;
+       TSS_HKEY     hSRK;
+       TSS_HKEY     hPCAKey;
+       TSS_HPOLICY  hSrkPolicy;
+       TSS_HPOLICY  hTPMPolicy;
+       TSS_HKEY     hIdentKey;
+       TSS_UUID     SRK_UUID = TSS_UUID_SRK;
+       BYTE         secret[] = TSS_WELL_KNOWN_SECRET;
+       BYTE        *IdentityReq;
+       UINT32       IdentityReqLen;
+       BYTE        *blob;
+       UINT32       blobLen;
+
+       /* get SRK plus SRK policy and set SRK secret */
+       result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
+                                                                               SRK_UUID, &hSRK);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_GetPolicyObject or SRK failed: 0x%x ",
+                                          LABEL, result);
+               return FALSE;
+       }
+       result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x ",
+                                          LABEL, result);
+               return FALSE;
+       }
+
+       /* get TPM plus TPM policy and set TPM secret */
+       result = Tspi_Context_GetTpmObject (this->hContext, &hTPM);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_Context_GetTpmObject failed:  0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       result = Tspi_GetPolicyObject(hTPM, TSS_POLICY_USAGE, &hTPMPolicy);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for TPM failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS,"%s Tspi_Policy_SetSecret for TPM failed: 0x%x",
+                                         LABEL, result);
+               return FALSE;
+       }
+
+       /* create context for a 2048 bit AIK */
+       result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
+                                       TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048 |
+                                       TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE, &hIdentKey);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for key failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+
+       /* create context for the Privacy CA public key and assign modulus */
+       result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
+                                       TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048, &hPCAKey);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for PCA failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO,
+                                       TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, ca_modulus.len,
+                                       ca_modulus.ptr);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_SetAttribData for PCA modulus failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO,
+                                       TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS,"%s Tspi_SetAttribUint32 for PCA encryption scheme "
+                                        "failed: 0x%x", LABEL, result);
+               return FALSE;
+       }
+
+       /* generate AIK */
+       DBG1(DBG_LIB, "Generating identity key...");
+       result = Tspi_TPM_CollateIdentityRequest(hTPM, hSRK, hPCAKey, 0, NULL,
+                                       hIdentKey, TSS_ALG_AES, &IdentityReqLen, &IdentityReq);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_TPM_CollateIdentityRequest failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       *identity_req = chunk_create(IdentityReq, IdentityReqLen);
+       DBG3(DBG_LIB, "%s Identity Request: %B", LABEL, identity_req);
+
+       /* load identity key */
+       result = Tspi_Key_LoadKey (hIdentKey, hSRK);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_Key_LoadKey for AIK failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+
+       /* output AIK private key in TSS blob format */
+       result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
+                                       TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_GetAttribData for private key blob failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       *aik_blob = chunk_create(blob, blobLen);
+       DBG3(DBG_LIB, "%s AIK private key blob: %B", LABEL, aik_blob);
+
+       /* output AIK Public Key in TSS blob format */
+       result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
+                                       TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blobLen, &blob);
+       if (result != TSS_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s Tspi_GetAttribData for public key blob failed: 0x%x",
+                                          LABEL, result);
+               return FALSE;
+       }
+       aik_pubkey_blob = chunk_create(blob, blobLen);
+       DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_pubkey_blob);
+
+       /* create a trusted AIK public key */
+       if (aik_pubkey_blob.len != AIK_PUBKEY_BLOB_SIZE)
+       {
+               DBG1(DBG_PTS, "%s AIK public key is not in TSS blob format",
+                                          LABEL);
+               return FALSE;
+       }
+       aik_modulus = chunk_skip(aik_pubkey_blob, AIK_PUBKEY_BLOB_SIZE - 256);
+       aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
+
+       /* output subjectPublicKeyInfo encoding of AIK public key */
+       if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL,
+                                       aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
+                                       CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
+       {
+               DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key failed",
+                                          LABEL);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+METHOD(tpm_tss_t, get_public, chunk_t,
+       private_tpm_tss_trousers_t *this, uint32_t handle)
+{
+       return chunk_empty;
+}
+
+METHOD(tpm_tss_t, destroy, void,
+       private_tpm_tss_trousers_t *this)
+{
+       finalize_context(this);
+       free(this);
+}
+
+/**
+ * See header
+ */
+tpm_tss_t *tpm_tss_trousers_create()
+{
+       private_tpm_tss_trousers_t *this;
+       bool available;
+
+       INIT(this,
+               .public = {
+                       .get_version = _get_version,
+                       .generate_aik = _generate_aik,
+                       .get_public = _get_public,
+                       .destroy = _destroy,
+               },
+       );
+
+       available = initialize_context(this);
+       DBG1(DBG_PTS, "TPM 1.2 via TrouSerS %savailable", available ? "" : "not ");
+
+       if (!available)
+       {
+               destroy(this);
+               return NULL;
+       }
+       return &this->public;
+}
+
+#else /* TSS_TROUSERS */
+
+tpm_tss_t *tpm_tss_trousers_create()
+{
+       return NULL;
+}
+
+#endif /* TSS_TROUSERS */
+
+
+
diff --git a/src/libtpmtss/tpm_tss_trousers.h b/src/libtpmtss/tpm_tss_trousers.h
new file mode 100644 (file)
index 0000000..a52d73a
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tpm_tss_trousers tpm_tss_trousers
+ * @{ @ingroup libtpmtss
+ */
+
+#ifndef TPM_TSS_TROUSERS_H_
+#define TPM_TSS_TROUSERS_H_
+
+#include "tpm_tss.h"
+
+/**
+ * Create a tpm_tss_trousers instance.
+ */
+tpm_tss_t *tpm_tss_trousers_create();
+
+#endif /** TPM_TSS_TROUSERS_H_ @}*/
diff --git a/src/libtpmtss/tpm_tss_tss2.c b/src/libtpmtss/tpm_tss_tss2.c
new file mode 100644 (file)
index 0000000..75d25b0
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 General Public License
+ * for more details.
+ */
+
+#include "tpm_tss_tss2.h"
+
+#ifdef TSS_TSS2
+
+#include <asn1/asn1.h>
+#include <asn1/oid.h>
+
+#include <tss2/tpm20.h>
+#include <tcti/tcti_socket.h>
+
+#define LABEL  "TPM 2.0 -"
+
+typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
+
+/**
+ * Private data of an tpm_tss_tss2_t object.
+ */
+struct private_tpm_tss_tss2_t {
+
+       /**
+        * Public tpm_tss_tss2_t interface.
+        */
+       tpm_tss_t public;
+
+       /**
+        * TCTI context
+        */
+       TSS2_TCTI_CONTEXT *tcti_context;
+
+       /**
+        * SYS context
+        */
+       TSS2_SYS_CONTEXT  *sys_context;
+
+};
+
+/**
+ * Some symbols required by libtctisocket
+ */
+FILE *outFp;
+uint8_t simulator = 1;
+
+int TpmClientPrintf (uint8_t type, const char *format, ...)
+{
+    return 0;
+}
+
+/**
+ * Initialize TSS context
+ */
+static bool initialize_context(private_tpm_tss_tss2_t *this)
+{
+       size_t   tcti_context_size;
+       uint32_t sys_context_size;
+       uint32_t rval;
+
+       TCTI_SOCKET_CONF rm_if_config = { DEFAULT_HOSTNAME,
+                                                                         DEFAULT_RESMGR_TPM_PORT
+                                                                       };
+
+       TSS2_ABI_VERSION abi_version = { TSSWG_INTEROP,
+                                                                        TSS_SAPI_FIRST_FAMILY,
+                                                                        TSS_SAPI_FIRST_LEVEL,
+                                                                        TSS_SAPI_FIRST_VERSION
+                                                                  };
+
+       /* determine size of tcti context */
+       rval = InitSocketTcti(NULL, &tcti_context_size, &rm_if_config, 0);
+       if (rval != TSS2_RC_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x",
+                                          LABEL, rval);
+               return FALSE;
+       }
+
+       /* allocate memory for tcti context */
+       this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
+
+       /* initialize tcti context */
+       rval = InitSocketTcti(this->tcti_context, &tcti_context_size,
+                                                 &rm_if_config, 0);
+       if (rval != TSS2_RC_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x",
+                                          LABEL, rval);
+               return FALSE;
+       }
+
+       /* determine size of sys context */
+       sys_context_size = Tss2_Sys_GetContextSize(0);
+
+       /* allocate memory for sys context */
+       this->sys_context = malloc(sys_context_size);
+
+       /* initialize sys context */
+       rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size,
+                                                          this->tcti_context, &abi_version);
+       if (rval != TSS2_RC_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s could not get sys_context: 0x%06x",
+                                          LABEL, rval);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+/**
+ * Finalize TSS context
+ */
+static void finalize_context(private_tpm_tss_tss2_t *this)
+{
+       if (this->tcti_context)
+       {
+               TeardownSocketTcti(this->tcti_context);
+       }
+       if (this->sys_context)
+       {
+               Tss2_Sys_Finalize(this->sys_context);
+               free(this->sys_context);
+       }
+}
+
+METHOD(tpm_tss_t, get_version, tpm_version_t,
+       private_tpm_tss_tss2_t *this)
+{
+       return TPM_VERSION_2_0;
+}
+
+/**
+ * read the public key portion of a TSS 2.0 AIK key from NVRAM
+ */
+bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
+       TPM2B_PUBLIC *public)
+{
+       uint32_t rval;
+
+       TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } };
+       TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } };
+
+       TPMS_AUTH_RESPONSE session_data;
+       TSS2_SYS_RSP_AUTHS sessions_data;
+       TPMS_AUTH_RESPONSE *session_data_array[1];
+
+       session_data_array[0]  = &session_data;
+       sessions_data.rspAuths = &session_data_array[0];
+       sessions_data.rspAuthsCount = 1;
+
+       /* always send simulator platform command, ignored by true RM */
+       PlatformCommand(this->tcti_context ,MS_SIM_POWER_ON );
+       PlatformCommand(this->tcti_context, MS_SIM_NV_ON );
+
+       /* read public key for a given object handle from TPM 2.0 NVRAM */
+       rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
+                                                          &qualified_name, &sessions_data);
+
+       PlatformCommand(this->tcti_context, MS_SIM_POWER_OFF);
+
+       if (rval != TPM_RC_SUCCESS)
+       {
+               DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
+                                          LABEL, handle, rval);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+METHOD(tpm_tss_t, generate_aik, bool,
+       private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
+       chunk_t *aik_pubkey, chunk_t *identity_req)
+{
+       return FALSE;
+}
+
+METHOD(tpm_tss_t, get_public, chunk_t,
+       private_tpm_tss_tss2_t *this, uint32_t handle)
+{
+       TPM2B_PUBLIC public = { { 0, } };
+       chunk_t aik_blob, aik_pubkey = chunk_empty;
+
+       if (!read_public(this, handle, &public))
+       {
+               return chunk_empty;
+       }
+
+       aik_blob = chunk_create((u_char*)&public, sizeof(public));
+       DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_blob);
+
+       /* convert TSS 2.0 AIK public key blot into PKCS#1 format */
+       switch (public.t.publicArea.type)
+       {
+               case TPM_ALG_RSA:
+               {
+                       TPM2B_PUBLIC_KEY_RSA *rsa;
+                       chunk_t aik_exponent, aik_modulus;
+
+                       rsa = &public.t.publicArea.unique.rsa;
+                       aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
+                       aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
+
+                       /* subjectPublicKeyInfo encoding of AIK RSA key */
+                       if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
+                                       NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
+                                       CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
+                       {
+                               DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key "
+                                                         "failed", LABEL);
+                       }
+                       break;
+               }
+               case TPM_ALG_ECC:
+               {
+                       TPMS_ECC_POINT *ecc;
+                       chunk_t ecc_point;
+                       uint8_t *pos;
+
+                       ecc = &public.t.publicArea.unique.ecc;
+
+                       /* allocate space for bit string */
+                       pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
+                                                                       2 + ecc->x.t.size + ecc->y.t.size);
+                       /* bit string length is a multiple of octets */
+                       *pos++ = 0x00;
+                       /* uncompressed ECC point format */
+                       *pos++ = 0x04;
+                       /* copy x coordinate of ECC point */
+                       memcpy(pos, ecc->x.t.buffer, ecc->x.t.size);
+                       pos += ecc->x.t.size;
+                       /* copy y coordinate of ECC point */
+                       memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
+                       /* subjectPublicKeyInfo encoding of AIK ECC key */
+                       aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
+                                                       asn1_wrap(ASN1_SEQUENCE, "mm",
+                                                               asn1_build_known_oid(OID_EC_PUBLICKEY),
+                                                               asn1_build_known_oid(ecc->x.t.size == 32 ?
+                                                                               OID_PRIME256V1 : OID_SECT384R1)),
+                                                       ecc_point);
+                       break;
+               }
+               default:
+                       DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
+       }
+
+       return aik_pubkey;
+}
+
+METHOD(tpm_tss_t, destroy, void,
+       private_tpm_tss_tss2_t *this)
+{
+       finalize_context(this);
+       free(this);
+}
+
+/**
+ * See header
+ */
+tpm_tss_t *tpm_tss_tss2_create()
+{
+       private_tpm_tss_tss2_t *this;
+       bool available;
+
+       INIT(this,
+               .public = {
+                       .get_version = _get_version,
+                       .generate_aik = _generate_aik,
+                       .get_public = _get_public,
+                       .destroy = _destroy,
+               },
+       );
+
+       available = initialize_context(this);
+       DBG1(DBG_PTS, "TPM 2.0 via TSS2 %savailable", available ? "" : "not ");
+
+       if (!available)
+       {
+               destroy(this);
+               return NULL;
+       }
+       return &this->public;
+}
+
+#else /* TSS_TSS2 */
+
+tpm_tss_t *tpm_tss_tss2_create()
+{
+       return NULL;
+}
+
+#endif /* TSS_TSS2 */
+
+
diff --git a/src/libtpmtss/tpm_tss_tss2.h b/src/libtpmtss/tpm_tss_tss2.h
new file mode 100644 (file)
index 0000000..f3a11e5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tpm_tss_tss2 tpm_tss_tss2
+ * @{ @ingroup libtpmtss
+ */
+
+#ifndef TPM_TSS_TSS2_H_
+#define TPM_TSS_TSS2_H_
+
+#include "tpm_tss.h"
+
+/**
+ * Create a tpm_tss_tss2 instance.
+ */
+tpm_tss_t *tpm_tss_tss2_create();
+
+#endif /** TPM_TSS_TSS2_H_ @}*/