aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/options/aikgen2.opt2
-rw-r--r--conf/options/aikpub2.opt2
-rw-r--r--configure.ac19
-rw-r--r--src/Makefile.am4
-rw-r--r--src/aikgen/Makefile.am9
-rw-r--r--src/aikgen/aikgen.c214
-rw-r--r--src/aikpub2/Makefile.am10
-rw-r--r--src/aikpub2/aikpub2.c219
-rw-r--r--src/libtpmtss/Makefile.am23
-rw-r--r--src/libtpmtss/tpm_tss.c46
-rw-r--r--src/libtpmtss/tpm_tss.h83
-rw-r--r--src/libtpmtss/tpm_tss_trousers.c332
-rw-r--r--src/libtpmtss/tpm_tss_trousers.h31
-rw-r--r--src/libtpmtss/tpm_tss_tss2.c305
-rw-r--r--src/libtpmtss/tpm_tss_tss2.h31
15 files changed, 927 insertions, 403 deletions
diff --git a/conf/options/aikgen2.opt b/conf/options/aikgen2.opt
deleted file mode 100644
index 2acab4ebf..000000000
--- a/conf/options/aikgen2.opt
+++ /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
index 000000000..6a755d211
--- /dev/null
+++ b/conf/options/aikpub2.opt
@@ -0,0 +1,2 @@
+aikpub2.load =
+ Plugins to load in aikpub2 tool.
diff --git a/configure.ac b/configure.ac
index f067fa7eb..3777a4841 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/src/Makefile.am b/src/Makefile.am
index 4e4dfca56..938335e78 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,10 @@ if USE_LIBPTTLS
SUBDIRS += libpttls
endif
+if USE_LIBTPMTSS
+ SUBDIRS += libtpmtss
+endif
+
if USE_IMCV
SUBDIRS += libimcv
endif
diff --git a/src/aikgen/Makefile.am b/src/aikgen/Makefile.am
index dc59d20cf..860a8f7a6 100644
--- a/src/aikgen/Makefile.am
+++ b/src/aikgen/Makefile.am
@@ -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}\""
diff --git a/src/aikgen/aikgen.c b/src/aikgen/aikgen.c
index 6d04fc1ca..22e80badb 100644
--- a/src/aikgen/aikgen.c
+++ b/src/aikgen/aikgen.c
@@ -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",
diff --git a/src/aikpub2/Makefile.am b/src/aikpub2/Makefile.am
index c43435f5e..a9ab13870 100644
--- a/src/aikpub2/Makefile.am
+++ b/src/aikpub2/Makefile.am
@@ -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}\""
diff --git a/src/aikpub2/aikpub2.c b/src/aikpub2/aikpub2.c
index feaca72a5..fea58ed27 100644
--- a/src/aikpub2/aikpub2.c
+++ b/src/aikpub2/aikpub2.c
@@ -13,14 +13,11 @@
* 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
index 000000000..94058bc18
--- /dev/null
+++ b/src/libtpmtss/Makefile.am
@@ -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
index 000000000..687f9f398
--- /dev/null
+++ b/src/libtpmtss/tpm_tss.c
@@ -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
index 000000000..1442cc402
--- /dev/null
+++ b/src/libtpmtss/tpm_tss.h
@@ -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
index 000000000..99d413254
--- /dev/null
+++ b/src/libtpmtss/tpm_tss_trousers.c
@@ -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
index 000000000..a52d73afa
--- /dev/null
+++ b/src/libtpmtss/tpm_tss_trousers.h
@@ -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
index 000000000..75d25b073
--- /dev/null
+++ b/src/libtpmtss/tpm_tss_tss2.c
@@ -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
index 000000000..f3a11e5fd
--- /dev/null
+++ b/src/libtpmtss/tpm_tss_tss2.h
@@ -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_ @}*/