summaryrefslogtreecommitdiff
path: root/src/libtpmtss
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2018-09-24 15:11:14 +0200
committerYves-Alexis Perez <corsac@debian.org>2018-09-24 15:11:14 +0200
commite0e280b7669435b991b7e457abd8aa450930b3e8 (patch)
tree3e6084f13b14ad2df104e2ce6e589eb96c5f7ac9 /src/libtpmtss
parent51a71ee15c1bcf0e82f363a16898f571e211f9c3 (diff)
downloadvyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.tar.gz
vyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.zip
New upstream version 5.7.0
Diffstat (limited to 'src/libtpmtss')
-rw-r--r--src/libtpmtss/Makefile.am4
-rw-r--r--src/libtpmtss/Makefile.in24
-rw-r--r--src/libtpmtss/plugins/tpm/Makefile.in11
-rw-r--r--src/libtpmtss/plugins/tpm/tpm_plugin.c7
-rw-r--r--src/libtpmtss/plugins/tpm/tpm_private_key.c2
-rw-r--r--src/libtpmtss/tpm_tss.c14
-rw-r--r--src/libtpmtss/tpm_tss.h24
-rw-r--r--src/libtpmtss/tpm_tss_trousers.c3
-rw-r--r--src/libtpmtss/tpm_tss_trousers.h2
-rw-r--r--src/libtpmtss/tpm_tss_tss2.h16
-rw-r--r--src/libtpmtss/tpm_tss_tss2_names_v1.c (renamed from src/libtpmtss/tpm_tss_tss2_names.c)12
-rw-r--r--src/libtpmtss/tpm_tss_tss2_names_v2.c98
-rw-r--r--src/libtpmtss/tpm_tss_tss2_v1.c (renamed from src/libtpmtss/tpm_tss_tss2.c)75
-rw-r--r--src/libtpmtss/tpm_tss_tss2_v2.c1190
14 files changed, 1428 insertions, 54 deletions
diff --git a/src/libtpmtss/Makefile.am b/src/libtpmtss/Makefile.am
index 1b3a9706f..d192fc126 100644
--- a/src/libtpmtss/Makefile.am
+++ b/src/libtpmtss/Makefile.am
@@ -24,8 +24,8 @@ libtpmtss_la_SOURCES = \
tpm_tss.h tpm_tss.c \
tpm_tss_quote_info.h tpm_tss_quote_info.c \
tpm_tss_trousers.h tpm_tss_trousers.c \
- tpm_tss_tss2.h tpm_tss_tss2.c \
- tpm_tss_tss2_names.h tpm_tss_tss2_names.c
+ tpm_tss_tss2.h tpm_tss_tss2_v1.c tpm_tss_tss2_v2.c \
+ tpm_tss_tss2_names.h tpm_tss_tss2_names_v1.c tpm_tss_tss2_names_v2.c
if MONOLITHIC
SUBDIRS =
diff --git a/src/libtpmtss/Makefile.in b/src/libtpmtss/Makefile.in
index 50861bcdd..724906de9 100644
--- a/src/libtpmtss/Makefile.in
+++ b/src/libtpmtss/Makefile.in
@@ -146,7 +146,8 @@ libtpmtss_la_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) $(am__append_4)
am_libtpmtss_la_OBJECTS = tpm_tss.lo tpm_tss_quote_info.lo \
- tpm_tss_trousers.lo tpm_tss_tss2.lo tpm_tss_tss2_names.lo
+ tpm_tss_trousers.lo tpm_tss_tss2_v1.lo tpm_tss_tss2_v2.lo \
+ tpm_tss_tss2_names_v1.lo tpm_tss_tss2_names_v2.lo
libtpmtss_la_OBJECTS = $(am_libtpmtss_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -355,7 +356,6 @@ PYTHON_VERSION = @PYTHON_VERSION@
PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
-RUBY = @RUBY@
RUBYGEMDIR = @RUBYGEMDIR@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -381,6 +381,8 @@ am__tar = @am__tar@
am__untar = @am__untar@
attest_plugins = @attest_plugins@
bindir = @bindir@
+botan_CFLAGS = @botan_CFLAGS@
+botan_LIBS = @botan_LIBS@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
@@ -401,8 +403,6 @@ dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
fuzz_plugins = @fuzz_plugins@
-gtk_CFLAGS = @gtk_CFLAGS@
-gtk_LIBS = @gtk_LIBS@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
@@ -457,8 +457,6 @@ random_device = @random_device@
resolv_conf = @resolv_conf@
routing_table = @routing_table@
routing_table_prio = @routing_table_prio@
-ruby_CFLAGS = @ruby_CFLAGS@
-ruby_LIBS = @ruby_LIBS@
runstatedir = @runstatedir@
s_plugins = @s_plugins@
sbindir = @sbindir@
@@ -487,8 +485,12 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
tss2_CFLAGS = @tss2_CFLAGS@
tss2_LIBS = @tss2_LIBS@
+tss2_esys_CFLAGS = @tss2_esys_CFLAGS@
+tss2_esys_LIBS = @tss2_esys_LIBS@
tss2_socket_CFLAGS = @tss2_socket_CFLAGS@
tss2_socket_LIBS = @tss2_socket_LIBS@
+tss2_sys_CFLAGS = @tss2_sys_CFLAGS@
+tss2_sys_LIBS = @tss2_sys_LIBS@
tss2_tabrmd_CFLAGS = @tss2_tabrmd_CFLAGS@
tss2_tabrmd_LIBS = @tss2_tabrmd_LIBS@
urandom_device = @urandom_device@
@@ -511,8 +513,8 @@ libtpmtss_la_SOURCES = \
tpm_tss.h tpm_tss.c \
tpm_tss_quote_info.h tpm_tss_quote_info.c \
tpm_tss_trousers.h tpm_tss_trousers.c \
- tpm_tss_tss2.h tpm_tss_tss2.c \
- tpm_tss_tss2_names.h tpm_tss_tss2_names.c
+ tpm_tss_tss2.h tpm_tss_tss2_v1.c tpm_tss_tss2_v2.c \
+ tpm_tss_tss2_names.h tpm_tss_tss2_names_v1.c tpm_tss_tss2_names_v2.c
@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3)
@MONOLITHIC_TRUE@SUBDIRS = $(am__append_3)
@@ -600,8 +602,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_quote_info.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_trousers.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_tss2.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_tss2_names.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_tss2_names_v1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_tss2_names_v2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_tss2_v1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_tss_tss2_v2.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
diff --git a/src/libtpmtss/plugins/tpm/Makefile.in b/src/libtpmtss/plugins/tpm/Makefile.in
index e03e73656..7cbd25414 100644
--- a/src/libtpmtss/plugins/tpm/Makefile.in
+++ b/src/libtpmtss/plugins/tpm/Makefile.in
@@ -312,7 +312,6 @@ PYTHON_VERSION = @PYTHON_VERSION@
PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
-RUBY = @RUBY@
RUBYGEMDIR = @RUBYGEMDIR@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -338,6 +337,8 @@ am__tar = @am__tar@
am__untar = @am__untar@
attest_plugins = @attest_plugins@
bindir = @bindir@
+botan_CFLAGS = @botan_CFLAGS@
+botan_LIBS = @botan_LIBS@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
@@ -358,8 +359,6 @@ dvidir = @dvidir@
exec_prefix = @exec_prefix@
fips_mode = @fips_mode@
fuzz_plugins = @fuzz_plugins@
-gtk_CFLAGS = @gtk_CFLAGS@
-gtk_LIBS = @gtk_LIBS@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
@@ -414,8 +413,6 @@ random_device = @random_device@
resolv_conf = @resolv_conf@
routing_table = @routing_table@
routing_table_prio = @routing_table_prio@
-ruby_CFLAGS = @ruby_CFLAGS@
-ruby_LIBS = @ruby_LIBS@
runstatedir = @runstatedir@
s_plugins = @s_plugins@
sbindir = @sbindir@
@@ -444,8 +441,12 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
tss2_CFLAGS = @tss2_CFLAGS@
tss2_LIBS = @tss2_LIBS@
+tss2_esys_CFLAGS = @tss2_esys_CFLAGS@
+tss2_esys_LIBS = @tss2_esys_LIBS@
tss2_socket_CFLAGS = @tss2_socket_CFLAGS@
tss2_socket_LIBS = @tss2_socket_LIBS@
+tss2_sys_CFLAGS = @tss2_sys_CFLAGS@
+tss2_sys_LIBS = @tss2_sys_LIBS@
tss2_tabrmd_CFLAGS = @tss2_tabrmd_CFLAGS@
tss2_tabrmd_LIBS = @tss2_tabrmd_LIBS@
urandom_device = @urandom_device@
diff --git a/src/libtpmtss/plugins/tpm/tpm_plugin.c b/src/libtpmtss/plugins/tpm/tpm_plugin.c
index e98899852..a00f46ea2 100644
--- a/src/libtpmtss/plugins/tpm/tpm_plugin.c
+++ b/src/libtpmtss/plugins/tpm/tpm_plugin.c
@@ -18,6 +18,7 @@
#include "tpm_cert.h"
#include "tpm_rng.h"
+#include <tpm_tss.h>
#include <library.h>
typedef struct private_tpm_plugin_t private_tpm_plugin_t;
@@ -80,6 +81,7 @@ METHOD(plugin_t, destroy, void,
private_tpm_plugin_t *this)
{
free(this);
+ libtpmtss_deinit();
}
/*
@@ -89,6 +91,11 @@ plugin_t *tpm_plugin_create()
{
private_tpm_plugin_t *this;
+ if (!libtpmtss_init())
+ {
+ return NULL;
+ }
+
INIT(this,
.public = {
.plugin = {
diff --git a/src/libtpmtss/plugins/tpm/tpm_private_key.c b/src/libtpmtss/plugins/tpm/tpm_private_key.c
index 0df5ee94c..3b7582ae3 100644
--- a/src/libtpmtss/plugins/tpm/tpm_private_key.c
+++ b/src/libtpmtss/plugins/tpm/tpm_private_key.c
@@ -93,7 +93,7 @@ METHOD(private_key_t, sign, bool,
enumerator->destroy(enumerator);
return this->tpm->sign(this->tpm, this->hierarchy, this->handle, scheme,
- data, pin, signature);
+ params, data, pin, signature);
}
METHOD(private_key_t, decrypt, bool,
diff --git a/src/libtpmtss/tpm_tss.c b/src/libtpmtss/tpm_tss.c
index 42a341896..72fd45b81 100644
--- a/src/libtpmtss/tpm_tss.c
+++ b/src/libtpmtss/tpm_tss.c
@@ -27,12 +27,20 @@
/**
* Described in header.
*/
-void libtpmtss_init(void)
+bool libtpmtss_init(void)
{
- /* empty */
+ return tpm_tss_tss2_init();
}
-typedef tpm_tss_t*(*tpm_tss_create)();
+/**
+ * Described in header.
+ */
+void libtpmtss_deinit(void)
+{
+ tpm_tss_tss2_deinit();
+}
+
+typedef tpm_tss_t*(*tpm_tss_create)(void);
/**
* See header.
diff --git a/src/libtpmtss/tpm_tss.h b/src/libtpmtss/tpm_tss.h
index bcb7ab949..11e4a7c15 100644
--- a/src/libtpmtss/tpm_tss.h
+++ b/src/libtpmtss/tpm_tss.h
@@ -48,14 +48,14 @@ struct tpm_tss_t {
/**
* Get TPM version supported by TSS
*
- * @return TPM version
+ * @return TPM version
*/
tpm_version_t (*get_version)(tpm_tss_t *this);
/**
* Get TPM version info (TPM 1.2 only)
*
- * @return TPM version info struct
+ * @return TPM version info struct
*/
chunk_t (*get_version_info)(tpm_tss_t *this);
@@ -74,8 +74,8 @@ struct tpm_tss_t {
/**
* 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
+ * @param handle key object handle
+ * @return public key in PKCS#1 format
*/
chunk_t (*get_public)(tpm_tss_t *this, uint32_t handle);
@@ -125,14 +125,15 @@ struct tpm_tss_t {
* @param handle object handle of TPM key to be used for signature
* @param hierarchy hierarchy the TPM key object is attached to
* @param scheme scheme to be used for signature
+ * @param param signature scheme parameters
* @param data data to be hashed and signed
* @param pin PIN code or empty chunk
* @param signature returns signature
* @return TRUE if signature succeeded
*/
bool (*sign)(tpm_tss_t *this, uint32_t hierarchy, uint32_t handle,
- signature_scheme_t scheme, chunk_t data, chunk_t pin,
- chunk_t *signature);
+ signature_scheme_t scheme, void *params, chunk_t data,
+ chunk_t pin, chunk_t *signature);
/**
* Get random bytes from the TPM
@@ -169,8 +170,15 @@ struct tpm_tss_t {
tpm_tss_t *tpm_tss_probe(tpm_version_t version);
/**
- * Dummy libtpmtss initialization function needed for integrity test
+ * libtpmtss initialization function
+ *
+ * @return TRUE if initialization was successful
+ */
+bool libtpmtss_init(void);
+
+/**
+ * libtpmtss de-initialization function
*/
-void libtpmtss_init(void);
+void libtpmtss_deinit(void);
#endif /** TPM_TSS_H_ @}*/
diff --git a/src/libtpmtss/tpm_tss_trousers.c b/src/libtpmtss/tpm_tss_trousers.c
index 6ed57af9d..81e542d02 100644
--- a/src/libtpmtss/tpm_tss_trousers.c
+++ b/src/libtpmtss/tpm_tss_trousers.c
@@ -584,7 +584,8 @@ err1:
METHOD(tpm_tss_t, sign, bool,
private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle,
- signature_scheme_t scheme, chunk_t data, chunk_t pin, chunk_t *signature)
+ signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
+ chunk_t *signature)
{
return FALSE;
}
diff --git a/src/libtpmtss/tpm_tss_trousers.h b/src/libtpmtss/tpm_tss_trousers.h
index 3afba0db2..3ff3e6685 100644
--- a/src/libtpmtss/tpm_tss_trousers.h
+++ b/src/libtpmtss/tpm_tss_trousers.h
@@ -47,6 +47,6 @@ struct tpm_tss_trousers_t {
/**
* Create a tpm_tss_trousers instance.
*/
-tpm_tss_t *tpm_tss_trousers_create();
+tpm_tss_t *tpm_tss_trousers_create(void);
#endif /** TPM_TSS_TROUSERS_H_ @}*/
diff --git a/src/libtpmtss/tpm_tss_tss2.h b/src/libtpmtss/tpm_tss_tss2.h
index f3a11e5fd..f2846c916 100644
--- a/src/libtpmtss/tpm_tss_tss2.h
+++ b/src/libtpmtss/tpm_tss_tss2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2016-2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -26,6 +26,18 @@
/**
* Create a tpm_tss_tss2 instance.
*/
-tpm_tss_t *tpm_tss_tss2_create();
+tpm_tss_t *tpm_tss_tss2_create(void);
+
+/**
+ * Initialize the tpm_tss_tss2 library.
+ *
+ * @return TRUE if initialization was successful
+ */
+bool tpm_tss_tss2_init(void);
+
+/**
+ * /De-initialize the tpm_tss_tss2 library.
+ */
+void tpm_tss_tss2_deinit(void);
#endif /** TPM_TSS_TSS2_H_ @}*/
diff --git a/src/libtpmtss/tpm_tss_tss2_names.c b/src/libtpmtss/tpm_tss_tss2_names_v1.c
index a613ac566..d2a4b5b57 100644
--- a/src/libtpmtss/tpm_tss_tss2_names.c
+++ b/src/libtpmtss/tpm_tss_tss2_names_v1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2016-2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,7 +15,7 @@
#include "tpm_tss_tss2_names.h"
-#ifdef TSS_TSS2
+#ifdef TSS_TSS2_V1
#include <tpm20.h>
@@ -102,7 +102,9 @@ ENUM_NEXT(tpm_ecc_curve_names, TPM_ECC_SM2_P256, TPM_ECC_SM2_P256, TPM_ECC_BN_P6
);
ENUM_END(tpm_ecc_curve_names, TPM_ECC_SM2_P256);
-#else /* TSS_TSS2 */
+#else /* TSS_TSS2_V1 */
+
+#ifndef TSS_TSS2_V2
/**
* TPM 2.0 algorithm ID names
@@ -118,6 +120,8 @@ ENUM(tpm_ecc_curve_names, 0, 0,
"NONE"
);
-#endif /* TSS_TSS2 */
+#endif /* !TSS_TSS2_V2 */
+
+#endif /* TSS_TSS2_V1 */
diff --git a/src/libtpmtss/tpm_tss_tss2_names_v2.c b/src/libtpmtss/tpm_tss_tss2_names_v2.c
new file mode 100644
index 000000000..c8d29e4e6
--- /dev/null
+++ b/src/libtpmtss/tpm_tss_tss2_names_v2.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifdef TSS_TSS2_V2
+
+#include "tpm_tss_tss2_names.h"
+
+#include <tss2/tss2_sys.h>
+
+/**
+ * TPM 2.0 algorithm ID names
+ */
+ENUM_BEGIN(tpm_alg_id_names, TPM2_ALG_ERROR, TPM2_ALG_RSA,
+ "ERROR",
+ "RSA"
+);
+ENUM_NEXT(tpm_alg_id_names, TPM2_ALG_SHA1, TPM2_ALG_KEYEDHASH, TPM2_ALG_RSA,
+ "SHA1",
+ "HMAC",
+ "AES",
+ "MGF1",
+ "KEYEDHASH"
+);
+ENUM_NEXT(tpm_alg_id_names, TPM2_ALG_XOR, TPM2_ALG_SHA512, TPM2_ALG_KEYEDHASH,
+ "XOR",
+ "SHA256",
+ "SHA384",
+ "SHA512"
+);
+ENUM_NEXT(tpm_alg_id_names, TPM2_ALG_NULL, TPM2_ALG_NULL, TPM2_ALG_SHA512,
+ "NULL"
+);
+ENUM_NEXT(tpm_alg_id_names, TPM2_ALG_SM3_256, TPM2_ALG_ECMQV, TPM2_ALG_NULL,
+ "SM3_256",
+ "SM4",
+ "RSASSA",
+ "RSAES",
+ "RSAPSS",
+ "OAEP",
+ "ECDSA",
+ "ECDH",
+ "SM2",
+ "ECSCHNORR",
+ "ECMQV"
+);
+ENUM_NEXT(tpm_alg_id_names, TPM2_ALG_KDF1_SP800_56A, TPM2_ALG_ECC, TPM2_ALG_ECMQV,
+ "KDF1_SP800_56A",
+ "KDF2",
+ "KDF1_SP800_108",
+ "ECC"
+);
+ENUM_NEXT(tpm_alg_id_names, TPM2_ALG_SYMCIPHER, TPM2_ALG_CAMELLIA, TPM2_ALG_ECC,
+ "SYMCIPHER",
+ "CAMELLIA"
+);
+ENUM_NEXT(tpm_alg_id_names, TPM2_ALG_CTR, TPM2_ALG_ECB, TPM2_ALG_CAMELLIA,
+ "CTR",
+ "OFB",
+ "CBC",
+ "CFB",
+ "ECB"
+);
+ENUM_END(tpm_alg_id_names, TPM2_ALG_ECB);
+
+/**
+ * TPM 2.0 ECC curve names
+ */
+ENUM_BEGIN(tpm_ecc_curve_names, TPM2_ECC_NONE, TPM2_ECC_NIST_P521,
+ "NONE",
+ "NIST_P192",
+ "NIST_P224",
+ "NIST_P256",
+ "NIST_P384",
+ "NIST_P521"
+);
+ENUM_NEXT(tpm_ecc_curve_names, TPM2_ECC_BN_P256, TPM2_ECC_BN_P638, TPM2_ECC_NIST_P521,
+ "BN_P256",
+ "BN_P638"
+);
+ENUM_NEXT(tpm_ecc_curve_names, TPM2_ECC_SM2_P256, TPM2_ECC_SM2_P256, TPM2_ECC_BN_P638,
+ "SM2_P256"
+);
+ENUM_END(tpm_ecc_curve_names, TPM2_ECC_SM2_P256);
+
+#endif /* TSS_TSS2_V2 */
+
diff --git a/src/libtpmtss/tpm_tss_tss2.c b/src/libtpmtss/tpm_tss_tss2_v1.c
index 90a16c103..9ed2798f7 100644
--- a/src/libtpmtss/tpm_tss_tss2.c
+++ b/src/libtpmtss/tpm_tss_tss2_v1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2016-2018 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,7 +16,7 @@
#include "tpm_tss_tss2.h"
#include "tpm_tss_tss2_names.h"
-#ifdef TSS_TSS2
+#ifdef TSS_TSS2_V1
#include <asn1/asn1.h>
#include <asn1/oid.h>
@@ -24,9 +24,9 @@
#include <tpm20.h>
-#ifdef TSS2_TCTI_TABRMD
+#ifdef TSS2_TCTI_TABRMD_V1
#include <tcti/tcti-tabrmd.h>
-#endif /* TSS2_TCTI_TABRMD */
+#endif /* TSS2_TCTI_TABRMD_V1 */
#ifdef TSS2_TCTI_SOCKET
#include <tcti_socket.h>
@@ -828,10 +828,12 @@ METHOD(tpm_tss_t, quote, bool,
METHOD(tpm_tss_t, sign, bool,
private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
- signature_scheme_t scheme, chunk_t data, chunk_t pin, chunk_t *signature)
+ signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
+ chunk_t *signature)
{
key_type_t key_type;
hash_algorithm_t hash_alg;
+ rsa_pss_params_t *rsa_pss_params;
uint32_t rval;
TPM_ALG_ID alg_id;
@@ -870,8 +872,17 @@ METHOD(tpm_tss_t, sign, bool,
}
*( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
- key_type = key_type_from_signature_scheme(scheme);
- hash_alg = hasher_from_signature_scheme(scheme, NULL);
+ if (scheme == SIGN_RSA_EMSA_PSS)
+ {
+ key_type = KEY_RSA;
+ rsa_pss_params = (rsa_pss_params_t *)params;
+ hash_alg = rsa_pss_params->hash;
+ }
+ else
+ {
+ key_type = key_type_from_signature_scheme(scheme);
+ hash_alg = hasher_from_signature_scheme(scheme, NULL);
+ }
/* Check if hash algorithm is supported by TPM */
alg_id = hash_alg_to_tpm_alg_id(hash_alg);
@@ -890,8 +901,16 @@ METHOD(tpm_tss_t, sign, bool,
if (key_type == KEY_RSA && public.t.publicArea.type == TPM_ALG_RSA)
{
- sig_scheme.scheme = TPM_ALG_RSASSA;
- sig_scheme.details.rsassa.hashAlg = alg_id;
+ if (scheme == SIGN_RSA_EMSA_PSS)
+ {
+ sig_scheme.scheme = TPM_ALG_RSAPSS;
+ sig_scheme.details.rsapss.hashAlg = alg_id;
+ }
+ else
+ {
+ sig_scheme.scheme = TPM_ALG_RSASSA;
+ sig_scheme.details.rsassa.hashAlg = alg_id;
+ }
}
else if (key_type == KEY_ECDSA && public.t.publicArea.type == TPM_ALG_ECC)
{
@@ -983,6 +1002,12 @@ METHOD(tpm_tss_t, sign, bool,
sig.signature.rsassa.sig.t.buffer,
sig.signature.rsassa.sig.t.size));
break;
+ case SIGN_RSA_EMSA_PSS:
+ *signature = chunk_clone(
+ chunk_create(
+ sig.signature.rsapss.sig.t.buffer,
+ sig.signature.rsapss.sig.t.size));
+ break;
case SIGN_ECDSA_256:
case SIGN_ECDSA_384:
case SIGN_ECDSA_521:
@@ -1046,12 +1071,14 @@ METHOD(tpm_tss_t, get_data, bool,
private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
chunk_t pin, chunk_t *data)
{
- uint16_t nv_size, nv_offset = 0;
+ uint16_t max_data_size, nv_size, nv_offset = 0;
uint32_t rval;
+ TPMS_CAPABILITY_DATA cap_data;
+ TPMI_YES_NO more_data;
TPM2B_NAME nv_name = { { sizeof(TPM2B_NAME)-2, } };
TPM2B_NV_PUBLIC nv_public = { { 0, } };
- TPM2B_MAX_NV_BUFFER nv_data = { { sizeof(TPM2B_MAX_NV_BUFFER)-2, } };
+ TPM2B_MAX_NV_BUFFER nv_data = { { MAX_NV_BUFFER_SIZE, } };
TPMS_AUTH_COMMAND session_data_cmd;
TPMS_AUTH_RESPONSE session_data_rsp;
TSS2_SYS_CMD_AUTHS sessions_data_cmd;
@@ -1059,6 +1086,18 @@ METHOD(tpm_tss_t, get_data, bool,
TPMS_AUTH_COMMAND *session_data_cmd_array[1];
TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
+ /* query maximum TPM data transmission size */
+ rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_TPM_PROPERTIES,
+ TPM_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
+ if (rval != TPM_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for "
+ "TPM_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+ max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
+ MAX_NV_BUFFER_SIZE);
+
/* get size of NV object */
rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
&nv_name, 0);
@@ -1093,11 +1132,11 @@ METHOD(tpm_tss_t, get_data, bool,
}
*( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
- /* read NV data an NV buffer block at a time */
+ /* read NV data a maximum data size block at a time */
while (nv_size > 0)
{
rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle,
- &sessions_data_cmd, min(nv_size, MAX_NV_BUFFER_SIZE),
+ &sessions_data_cmd, min(nv_size, max_data_size),
nv_offset, &nv_data, &sessions_data_rsp);
if (rval != TPM_RC_SUCCESS)
@@ -1154,7 +1193,7 @@ tpm_tss_t *tpm_tss_tss2_create()
{
available = initialize_sys_context(this);
}
- DBG1(DBG_PTS, "TPM 2.0 via TSS2 %savailable", available ? "" : "not ");
+ DBG1(DBG_PTS, "TPM 2.0 via TSS2 v1 %savailable", available ? "" : "not ");
if (!available)
{
@@ -1164,13 +1203,15 @@ tpm_tss_t *tpm_tss_tss2_create()
return &this->public;
}
-#else /* TSS_TSS2 */
+#else /* TSS_TSS2_V1 */
-tpm_tss_t *tpm_tss_tss2_create()
+#ifndef TSS_TSS2_V2
+tpm_tss_t *tpm_tss_tss2_create(void)
{
return NULL;
}
+#endif /* !TSS_TSS2_V2 */
-#endif /* TSS_TSS2 */
+#endif /* TSS_TSS2_V1 */
diff --git a/src/libtpmtss/tpm_tss_tss2_v2.c b/src/libtpmtss/tpm_tss_tss2_v2.c
new file mode 100644
index 000000000..7cb0d48a9
--- /dev/null
+++ b/src/libtpmtss/tpm_tss_tss2_v2.c
@@ -0,0 +1,1190 @@
+/*
+ * Copyright (C) 2018 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"
+#include "tpm_tss_tss2_names.h"
+
+#ifdef TSS_TSS2_V2
+
+#include <asn1/asn1.h>
+#include <asn1/oid.h>
+#include <bio/bio_reader.h>
+
+#include <tss2/tss2_sys.h>
+
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define LABEL "TPM 2.0 -"
+
+#define PLATFORM_PCR 24
+
+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;
+
+ /**
+ * Number of supported algorithms
+ */
+ size_t supported_algs_count;
+
+ /**
+ * List of supported algorithms
+ */
+ TPM2_ALG_ID supported_algs[TPM2_PT_ALGORITHM_SET];
+};
+
+/**
+ * Global TCTI dynamic library handle and init function
+ */
+static void *tcti_handle;
+
+static TSS2_TCTI_INIT_FUNC tcti_init;
+
+static char *tcti_opts;
+
+/**
+ * Empty AUTH_COMMAND
+ */
+static const TPMS_AUTH_COMMAND auth_cmd_empty;
+
+/**
+ * Convert hash algorithm to TPM2_ALG_ID
+ */
+static TPM2_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg)
+{
+ switch (alg)
+ {
+ case HASH_SHA1:
+ return TPM2_ALG_SHA1;
+ case HASH_SHA256:
+ return TPM2_ALG_SHA256;
+ case HASH_SHA384:
+ return TPM2_ALG_SHA384;
+ case HASH_SHA512:
+ return TPM2_ALG_SHA512;
+ default:
+ return TPM2_ALG_ERROR;
+ }
+}
+
+/**
+ * Convert TPM2_ALG_ID to hash algorithm
+ */
+static hash_algorithm_t hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg)
+{
+ switch (alg)
+ {
+ case TPM2_ALG_SHA1:
+ return HASH_SHA1;
+ case TPM2_ALG_SHA256:
+ return HASH_SHA256;
+ case TPM2_ALG_SHA384:
+ return HASH_SHA384;
+ case TPM2_ALG_SHA512:
+ return HASH_SHA512;
+ default:
+ return HASH_UNKNOWN;
+ }
+}
+
+/**
+ * Check if an algorithm given by its TPM2_ALG_ID is supported by the TPM
+ */
+static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM2_ALG_ID alg_id)
+{
+ int i;
+
+ if (alg_id == TPM2_ALG_ERROR)
+ {
+ return FALSE;
+ }
+
+ for (i = 0; i < this->supported_algs_count; i++)
+ {
+ if (this->supported_algs[i] == alg_id)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * Get a list of supported algorithms
+ */
+static bool get_algs_capability(private_tpm_tss_tss2_t *this)
+{
+ TPMS_CAPABILITY_DATA cap_data;
+ TPMS_TAGGED_PROPERTY tp;
+ TPMI_YES_NO more_data;
+ TPM2_ALG_ID alg;
+ uint32_t rval, i, offset, revision = 0, year = 0;
+ size_t len = BUF_LEN;
+ char buf[BUF_LEN], manufacturer[5], vendor_string[17];
+ char *pos = buf;
+ int written;
+
+ /* get fixed properties */
+ rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
+ TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES,
+ &more_data, &cap_data, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_TPM_PROPERTIES: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+ memset(manufacturer, '\0', sizeof(manufacturer));
+ memset(vendor_string, '\0', sizeof(vendor_string));
+
+ /* print fixed properties */
+ for (i = 0; i < cap_data.data.tpmProperties.count; i++)
+ {
+ tp = cap_data.data.tpmProperties.tpmProperty[i];
+ switch (tp.property)
+ {
+ case TPM2_PT_REVISION:
+ revision = tp.value;
+ break;
+ case TPM2_PT_YEAR:
+ year = tp.value;
+ break;
+ case TPM2_PT_MANUFACTURER:
+ htoun32(manufacturer, tp.value);
+ break;
+ case TPM2_PT_VENDOR_STRING_1:
+ case TPM2_PT_VENDOR_STRING_2:
+ case TPM2_PT_VENDOR_STRING_3:
+ case TPM2_PT_VENDOR_STRING_4:
+ offset = 4 * (tp.property - TPM2_PT_VENDOR_STRING_1);
+ htoun32(vendor_string + offset, tp.value);
+ break;
+ default:
+ break;
+ }
+ }
+ DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u", LABEL, manufacturer,
+ vendor_string, (float)revision/100, year);
+
+ /* get supported algorithms */
+ rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ALGS,
+ 0, TPM2_PT_ALGORITHM_SET, &more_data, &cap_data, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_ALGS: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+
+ /* Number of supported algorithms */
+ this->supported_algs_count = cap_data.data.algorithms.count;
+
+ /* store and print supported algorithms */
+ for (i = 0; i < this->supported_algs_count; i++)
+ {
+ alg = cap_data.data.algorithms.algProperties[i].alg;
+ this->supported_algs[i] = alg;
+
+ written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+ }
+ DBG2(DBG_PTS, "%s algorithms:%s", LABEL, buf);
+
+ /* get supported ECC curves */
+ rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ECC_CURVES,
+ 0, TPM2_PT_LOADED_CURVES, &more_data, &cap_data, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s GetCapability failed for TPM2_ECC_CURVES: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+
+ /* reset print buffer */
+ pos = buf;
+ len = BUF_LEN;
+
+ /* print supported ECC curves */
+ for (i = 0; i < cap_data.data.eccCurves.count; i++)
+ {
+ written = snprintf(pos, len, " %N", tpm_ecc_curve_names,
+ cap_data.data.eccCurves.eccCurves[i]);
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+ }
+ DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf);
+
+ return TRUE;
+}
+
+/**
+ * Initialize TSS2 TCTI context
+ */
+static bool initialize_tcti_context(private_tpm_tss_tss2_t *this)
+{
+ size_t tcti_context_size;
+ uint32_t rval;
+
+ if (!tcti_init)
+ {
+ return FALSE;
+ }
+
+ /* determine size of tcti context */
+ rval = tcti_init(NULL, &tcti_context_size, tcti_opts);
+ if (rval != TSS2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s tcti init setup failed: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+
+ /* allocate and initialize memory for tcti context */
+ this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
+ memset(this->tcti_context, 0x00, tcti_context_size);
+
+ /* initialize tcti context */
+ rval = tcti_init(this->tcti_context, &tcti_context_size, tcti_opts);
+ if (rval != TSS2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s tcti init allocation failed: 0x%06x", LABEL,rval);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Initialize TSS2 Sys context
+ */
+static bool initialize_sys_context(private_tpm_tss_tss2_t *this)
+{
+ uint32_t sys_context_size;
+ uint32_t rval;
+
+ TSS2_ABI_VERSION abi_version = {
+ .tssCreator = 1,
+ .tssFamily = 2,
+ .tssLevel = 1,
+ .tssVersion = 108
+ };
+
+ /* determine size of sys context */
+ sys_context_size = Tss2_Sys_GetContextSize(0);
+
+ /* allocate memory for sys context */
+ this->sys_context = (TSS2_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;
+ }
+
+ /* get a list of supported algorithms and ECC curves */
+ return get_algs_capability(this);
+}
+
+/**
+ * Finalize TSS context
+ */
+static void finalize_context(private_tpm_tss_tss2_t *this)
+{
+ if (this->tcti_context)
+ {
+ Tss2_Tcti_Finalize(this->tcti_context);
+ free(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;
+}
+
+METHOD(tpm_tss_t, get_version_info, chunk_t,
+ private_tpm_tss_tss2_t *this)
+{
+ return chunk_empty;
+}
+
+/**
+ * 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, };
+ TSS2L_SYS_AUTH_RESPONSE auth_rsp;
+
+
+ /* 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, &auth_rsp);
+ if (rval != TPM2_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, };
+ TPM2_ALG_ID sig_alg, digest_alg;
+ 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.publicArea.type)
+ {
+ case TPM2_ALG_RSA:
+ {
+ TPM2B_PUBLIC_KEY_RSA *rsa;
+ TPMT_RSA_SCHEME *scheme;
+ chunk_t aik_exponent, aik_modulus;
+
+ scheme = &public.publicArea.parameters.rsaDetail.scheme;
+ sig_alg = scheme->scheme;
+ digest_alg = scheme->details.anySig.hashAlg;
+
+ rsa = &public.publicArea.unique.rsa;
+ aik_modulus = chunk_create(rsa->buffer, rsa->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);
+ return chunk_empty;
+ }
+ break;
+ }
+ case TPM2_ALG_ECC:
+ {
+ TPMS_ECC_POINT *ecc;
+ TPMT_ECC_SCHEME *scheme;
+ chunk_t ecc_point;
+ uint8_t *pos;
+
+ scheme = &public.publicArea.parameters.eccDetail.scheme;
+ sig_alg = scheme->scheme;
+ digest_alg = scheme->details.anySig.hashAlg;
+
+ ecc = &public.publicArea.unique.ecc;
+
+ /* allocate space for bit string */
+ pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
+ 2 + ecc->x.size + ecc->y.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.buffer, ecc->x.size);
+ pos += ecc->x.size;
+ /* copy y coordinate of ECC point */
+ memcpy(pos, ecc->y.buffer, ecc->y.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.size == 32 ?
+ OID_PRIME256V1 : OID_SECT384R1)),
+ ecc_point);
+ break;
+ }
+ default:
+ DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
+ return chunk_empty;
+ }
+ DBG1(DBG_PTS, "AIK signature algorithm is %N with %N hash",
+ tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
+ return aik_pubkey;
+}
+
+/**
+ * Configure a PCR Selection assuming a maximum of 24 registers
+ */
+static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
+ hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
+{
+ TPM2_ALG_ID alg_id;
+ uint32_t pcr;
+
+ /* check if hash algorithm is supported by TPM */
+ alg_id = hash_alg_to_tpm_alg_id(alg);
+ if (!is_supported_alg(this, alg_id))
+ {
+ DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
+ LABEL, hash_algorithm_short_names, alg);
+ return FALSE;
+ }
+
+ /* initialize the PCR Selection structure,*/
+ pcr_sel->count = 1;
+ pcr_sel->pcrSelections[0].hash = alg_id;
+ pcr_sel->pcrSelections[0].sizeofSelect = 3;
+ pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
+ pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
+ pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
+
+ /* set the selected PCRs */
+ for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
+ {
+ if (pcrs & (1 << pcr))
+ {
+ pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
+ }
+ }
+ return TRUE;
+}
+
+METHOD(tpm_tss_t, read_pcr, bool,
+ private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
+ hash_algorithm_t alg)
+{
+ TPML_PCR_SELECTION pcr_selection;
+ TPML_DIGEST pcr_values;
+
+ uint32_t pcr_update_counter, rval;
+ uint8_t *pcr_value_ptr;
+ size_t pcr_value_len;
+
+ if (pcr_num >= PLATFORM_PCR)
+ {
+ DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
+ LABEL, PLATFORM_PCR);
+ return FALSE;
+ }
+
+ if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
+ {
+ return FALSE;
+ }
+
+ /* initialize the PCR Digest structure */
+ memset(&pcr_values, 0, sizeof(TPML_DIGEST));
+
+ /* read the PCR value */
+ rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
+ &pcr_update_counter, &pcr_selection, &pcr_values, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
+ LABEL, rval);
+ return FALSE;
+ }
+ pcr_value_ptr = (uint8_t *)pcr_values.digests[0].buffer;
+ pcr_value_len = (size_t) pcr_values.digests[0].size;
+
+ *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
+
+ return TRUE;
+}
+
+METHOD(tpm_tss_t, extend_pcr, bool,
+ private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
+ chunk_t data, hash_algorithm_t alg)
+{
+ uint32_t rval;
+ TPM2_ALG_ID alg_id;
+ TPML_DIGEST_VALUES digest_values;
+ TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
+ TSS2L_SYS_AUTH_RESPONSE auth_rsp;
+
+ auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
+
+ /* check if hash algorithm is supported by TPM */
+ alg_id = hash_alg_to_tpm_alg_id(alg);
+ if (!is_supported_alg(this, alg_id))
+ {
+ DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
+ LABEL, hash_algorithm_short_names, alg);
+ return FALSE;
+ }
+
+ digest_values.count = 1;
+ digest_values.digests[0].hashAlg = alg_id;
+
+ switch (alg)
+ {
+ case HASH_SHA1:
+ if (data.len != HASH_SIZE_SHA1)
+ {
+ return FALSE;
+ }
+ memcpy(digest_values.digests[0].digest.sha1, data.ptr,
+ HASH_SIZE_SHA1);
+ break;
+ case HASH_SHA256:
+ if (data.len != HASH_SIZE_SHA256)
+ {
+ return FALSE;
+ }
+ memcpy(digest_values.digests[0].digest.sha256, data.ptr,
+ HASH_SIZE_SHA256);
+ break;
+ case HASH_SHA384:
+ if (data.len != HASH_SIZE_SHA384)
+ {
+ return FALSE;
+ }
+ memcpy(digest_values.digests[0].digest.sha384, data.ptr,
+ HASH_SIZE_SHA384);
+ break;
+ case HASH_SHA512:
+ if (data.len != HASH_SIZE_SHA512)
+ {
+ return FALSE;
+ }
+ memcpy(digest_values.digests[0].digest.sha512, data.ptr,
+ HASH_SIZE_SHA512);
+ break;
+ default:
+ return FALSE;
+ }
+
+ /* extend PCR */
+ rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &auth_cmd,
+ &digest_values, &auth_rsp);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x",
+ LABEL, pcr_num, rval);
+ return FALSE;
+ }
+
+ /* get updated PCR value */
+ return read_pcr(this, pcr_num, pcr_value, alg);
+}
+
+METHOD(tpm_tss_t, quote, bool,
+ private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
+ hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
+ tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
+{
+ chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
+ firmware_version, pcr_select, pcr_digest;
+ hash_algorithm_t pcr_digest_alg;
+ bio_reader_t *reader;
+ uint32_t rval;
+
+ TPM2B_DATA qualifying_data;
+ TPML_PCR_SELECTION pcr_selection;
+ TPM2B_ATTEST quoted = { sizeof(TPM2B_ATTEST)-2, };
+ TPMT_SIG_SCHEME scheme;
+ TPMT_SIGNATURE sig;
+ TPMI_ALG_HASH hash_alg;
+ TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
+ TSS2L_SYS_AUTH_RESPONSE auth_rsp;
+
+ auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
+
+ qualifying_data.size = data.len;
+ memcpy(qualifying_data.buffer, data.ptr, data.len);
+
+ scheme.scheme = TPM2_ALG_NULL;
+ memset(&sig, 0x00, sizeof(sig));
+
+ /* set Quote mode */
+ *quote_mode = TPM_QUOTE_TPM2;
+
+ if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
+ {
+ return FALSE;
+ }
+
+ rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &auth_cmd,
+ &qualifying_data, &scheme, &pcr_selection, &quoted,
+ &sig, &auth_rsp);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+ quoted_chunk = chunk_create(quoted.attestationData, quoted.size);
+
+ reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
+ if (!reader->read_data16(reader, &qualified_signer) ||
+ !reader->read_data16(reader, &extra_data) ||
+ !reader->read_data (reader, 17, &clock_info) ||
+ !reader->read_data (reader, 8, &firmware_version) ||
+ !reader->read_data (reader, 10, &pcr_select) ||
+ !reader->read_data16(reader, &pcr_digest))
+ {
+ DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
+ reader->destroy(reader);
+ return FALSE;
+ }
+ reader->destroy(reader);
+
+ DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
+ DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
+ DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
+ DBG2(DBG_PTS, "extraData: %B", &extra_data);
+ DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
+ DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
+ DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
+
+ /* extract signature */
+ switch (sig.sigAlg)
+ {
+ case TPM2_ALG_RSASSA:
+ case TPM2_ALG_RSAPSS:
+ *quote_sig = chunk_clone(
+ chunk_create(
+ sig.signature.rsassa.sig.buffer,
+ sig.signature.rsassa.sig.size));
+ hash_alg = sig.signature.rsassa.hash;
+ break;
+ case TPM2_ALG_ECDSA:
+ case TPM2_ALG_ECDAA:
+ case TPM2_ALG_SM2:
+ case TPM2_ALG_ECSCHNORR:
+ *quote_sig = chunk_cat("cc",
+ chunk_create(
+ sig.signature.ecdsa.signatureR.buffer,
+ sig.signature.ecdsa.signatureR.size),
+ chunk_create(
+ sig.signature.ecdsa.signatureS.buffer,
+ sig.signature.ecdsa.signatureS.size));
+ hash_alg = sig.signature.ecdsa.hash;
+ break;
+ default:
+ DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
+ LABEL, tpm_alg_id_names, sig.sigAlg);
+ return FALSE;
+ };
+
+ DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
+ pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
+
+ DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
+
+ /* Create and initialize Quote Info object */
+ *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
+ pcr_digest);
+ (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
+ pcr_select);
+ (*quote_info)->set_version_info(*quote_info, firmware_version);
+
+ return TRUE;
+}
+
+METHOD(tpm_tss_t, sign, bool,
+ private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
+ signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
+ chunk_t *signature)
+{
+ key_type_t key_type;
+ hash_algorithm_t hash_alg;
+ rsa_pss_params_t *rsa_pss_params;
+ uint32_t rval;
+
+ TPM2_ALG_ID alg_id;
+ TPM2B_MAX_BUFFER buffer;
+ TPM2B_DIGEST hash = { sizeof(TPM2B_DIGEST)-2, };
+ TPMT_TK_HASHCHECK validation;
+ TPM2B_PUBLIC public = { 0, };
+ TPMT_SIG_SCHEME sig_scheme;
+ TPMT_SIGNATURE sig;
+ TPMS_AUTH_COMMAND *cmd;
+ TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
+ TSS2L_SYS_AUTH_RESPONSE auth_rsp;
+
+ cmd = &auth_cmd.auths[0];
+ cmd->sessionHandle = TPM2_RS_PW;
+
+ if (pin.len > 0)
+ {
+ cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
+ memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
+ }
+
+ if (scheme == SIGN_RSA_EMSA_PSS)
+ {
+ key_type = KEY_RSA;
+ rsa_pss_params = (rsa_pss_params_t *)params;
+ hash_alg = rsa_pss_params->hash;
+ }
+ else
+ {
+ key_type = key_type_from_signature_scheme(scheme);
+ hash_alg = hasher_from_signature_scheme(scheme, NULL);
+ }
+
+ /* Check if hash algorithm is supported by TPM */
+ alg_id = hash_alg_to_tpm_alg_id(hash_alg);
+ if (!is_supported_alg(this, alg_id))
+ {
+ DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
+ LABEL, hash_algorithm_short_names, hash_alg);
+ return FALSE;
+ }
+
+ /* Get public key */
+ if (!read_public(this, handle, &public))
+ {
+ return FALSE;
+ }
+
+ if (key_type == KEY_RSA && public.publicArea.type == TPM2_ALG_RSA)
+ {
+ if (scheme == SIGN_RSA_EMSA_PSS)
+ {
+ sig_scheme.scheme = TPM2_ALG_RSAPSS;
+ sig_scheme.details.rsapss.hashAlg = alg_id;
+ }
+ else
+ {
+ sig_scheme.scheme = TPM2_ALG_RSASSA;
+ sig_scheme.details.rsassa.hashAlg = alg_id;
+ }
+ }
+ else if (key_type == KEY_ECDSA && public.publicArea.type == TPM2_ALG_ECC)
+ {
+ sig_scheme.scheme = TPM2_ALG_ECDSA;
+ sig_scheme.details.ecdsa.hashAlg = alg_id;
+
+ }
+ else
+ {
+ DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key",
+ LABEL, signature_scheme_names, scheme);
+ return FALSE;
+ }
+
+ if (data.len <= TPM2_MAX_DIGEST_BUFFER)
+ {
+ memcpy(buffer.buffer, data.ptr, data.len);
+ buffer.size = data.len;
+
+ rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
+ &hash, &validation, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+ }
+ else
+ {
+ TPMI_DH_OBJECT sequence_handle;
+ TPM2B_AUTH null_auth;
+
+ null_auth.size = 0;
+ rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
+ alg_id, &sequence_handle, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+
+ while (data.len > 0)
+ {
+ buffer.size = min(data.len, TPM2_MAX_DIGEST_BUFFER);
+ memcpy(buffer.buffer, data.ptr, buffer.size);
+ data.ptr += buffer.size;
+ data.len -= buffer.size;
+
+ rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
+ &auth_cmd, &buffer, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+ }
+ buffer.size = 0;
+
+ rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
+ &auth_cmd, &buffer, hierarchy,
+ &hash, &validation, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
+ LABEL, rval);
+ return FALSE;
+ }
+ }
+
+ rval = Tss2_Sys_Sign(this->sys_context, handle, &auth_cmd, &hash,
+ &sig_scheme, &validation, &sig, &auth_rsp);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+
+ /* extract signature */
+ switch (scheme)
+ {
+ case SIGN_RSA_EMSA_PKCS1_SHA1:
+ case SIGN_RSA_EMSA_PKCS1_SHA2_256:
+ case SIGN_RSA_EMSA_PKCS1_SHA2_384:
+ case SIGN_RSA_EMSA_PKCS1_SHA2_512:
+ *signature = chunk_clone(
+ chunk_create(
+ sig.signature.rsassa.sig.buffer,
+ sig.signature.rsassa.sig.size));
+ break;
+ case SIGN_RSA_EMSA_PSS:
+ *signature = chunk_clone(
+ chunk_create(
+ sig.signature.rsapss.sig.buffer,
+ sig.signature.rsapss.sig.size));
+ break;
+ case SIGN_ECDSA_256:
+ case SIGN_ECDSA_384:
+ case SIGN_ECDSA_521:
+ *signature = chunk_cat("cc",
+ chunk_create(
+ sig.signature.ecdsa.signatureR.buffer,
+ sig.signature.ecdsa.signatureR.size),
+ chunk_create(
+ sig.signature.ecdsa.signatureS.buffer,
+ sig.signature.ecdsa.signatureS.size));
+ break;
+ case SIGN_ECDSA_WITH_SHA256_DER:
+ case SIGN_ECDSA_WITH_SHA384_DER:
+ case SIGN_ECDSA_WITH_SHA512_DER:
+ *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_integer("c",
+ chunk_create(
+ sig.signature.ecdsa.signatureR.buffer,
+ sig.signature.ecdsa.signatureR.size)),
+ asn1_integer("c",
+ chunk_create(
+ sig.signature.ecdsa.signatureS.buffer,
+ sig.signature.ecdsa.signatureS.size)));
+ break;
+ default:
+ DBG1(DBG_PTS, "%s unsupported %N signature scheme",
+ LABEL, signature_scheme_names, scheme);
+ return FALSE;
+ };
+
+ return TRUE;
+}
+
+METHOD(tpm_tss_t, get_random, bool,
+ private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
+{
+ size_t len, random_len= sizeof(TPM2B_DIGEST)-2;
+ TPM2B_DIGEST random = { random_len, };
+ uint8_t *pos = buffer;
+ uint32_t rval;
+
+ while (bytes > 0)
+ {
+ len = min(bytes, random_len);
+
+ rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL);
+ if (rval != TSS2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+ memcpy(pos, random.buffer, random.size);
+ pos += random.size;
+ bytes -= random.size;
+ }
+
+ return TRUE;
+}
+
+METHOD(tpm_tss_t, get_data, bool,
+ private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
+ chunk_t pin, chunk_t *data)
+{
+ uint16_t max_data_size, nv_size, nv_offset = 0;
+ uint32_t rval;
+
+ TPMS_CAPABILITY_DATA cap_data;
+ TPMI_YES_NO more_data;
+ TPM2B_NAME nv_name = { sizeof(TPM2B_NAME)-2, };
+ TPM2B_NV_PUBLIC nv_public = { 0, };
+ TPM2B_MAX_NV_BUFFER nv_data = { TPM2_MAX_NV_BUFFER_SIZE, };
+ TPMS_AUTH_COMMAND *cmd;
+ TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
+ TSS2L_SYS_AUTH_RESPONSE auth_rsp;
+
+ /* query maximum TPM data transmission size */
+ rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
+ TPM2_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for "
+ "TPM2_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+ max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
+ TPM2_MAX_NV_BUFFER_SIZE);
+
+ /* get size of NV object */
+ rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
+ &nv_name, 0);
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval);
+ return FALSE;
+ }
+ nv_size = nv_public.nvPublic.dataSize;
+ *data = chunk_alloc(nv_size);
+
+ /* prepare NV read session */
+ cmd = &auth_cmd.auths[0];
+ cmd->sessionHandle = TPM2_RS_PW;
+
+ if (pin.len > 0)
+ {
+ cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
+ memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
+ }
+
+ /* read NV data a maximum data size block at a time */
+ while (nv_size > 0)
+ {
+ rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, &auth_cmd,
+ min(nv_size, max_data_size), nv_offset, &nv_data, &auth_rsp);
+
+ if (rval != TPM2_RC_SUCCESS)
+ {
+ DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval);
+ chunk_free(data);
+ return FALSE;
+ }
+ memcpy(data->ptr + nv_offset, nv_data.buffer, nv_data.size);
+ nv_offset += nv_data.size;
+ nv_size -= nv_data.size;
+ }
+
+ return TRUE;
+}
+
+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,
+ .get_version_info = _get_version_info,
+ .generate_aik = _generate_aik,
+ .get_public = _get_public,
+ .read_pcr = _read_pcr,
+ .extend_pcr = _extend_pcr,
+ .quote = _quote,
+ .sign = _sign,
+ .get_random = _get_random,
+ .get_data = _get_data,
+ .destroy = _destroy,
+ },
+ );
+
+ available = initialize_tcti_context(this);
+ if (available)
+ {
+ available = initialize_sys_context(this);
+ }
+ DBG1(DBG_PTS, "TPM 2.0 via TSS2 v2 %savailable", available ? "" : "not ");
+
+ if (!available)
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
+/**
+ * See header
+ */
+bool tpm_tss_tss2_init(void)
+{
+ TSS2_TCTI_INFO_FUNC infofn;
+ const TSS2_TCTI_INFO *info;
+ char tcti_lib_format[] = "libtss2-tcti-%s.so.0";
+ char tcti_lib[BUF_LEN];
+ char *tcti_names[] = { "device", "tabrmd", "mssim" };
+ char *tcti_options[] = { "/dev/tpmrm0", "", "" };
+ char *tcti_name;
+ bool match = FALSE;
+ struct stat st;
+ int i = 0;
+
+ /* check for the existence of an in-kernel TPM resource manager */
+ if (stat(tcti_options[i], &st))
+ {
+ i = 1;
+ }
+ DBG2(DBG_PTS, "%s \"%s\" in-kernel resource manager is %spresent",
+ LABEL, tcti_options[0], i ? "not " : "");
+
+ /* select a dynamic TCTI library (device, tabrmd or mssim) */
+ tcti_name = lib->settings->get_str(lib->settings,
+ "%s.plugins.tpm.tcti.name", tcti_names[i], lib->ns);
+ snprintf(tcti_lib, BUF_LEN, tcti_lib_format, tcti_name);
+
+ for (i = 0; i < countof(tcti_names); i++)
+ {
+ if (streq(tcti_name, tcti_names[i]))
+ {
+ match = TRUE;
+ break;
+ }
+ }
+ if (!match)
+ {
+ DBG1(DBG_PTS, "%s \"%s\" is not a valid TCTI library name",
+ LABEL, tcti_lib);
+ return FALSE;
+ }
+
+ tcti_opts = lib->settings->get_str(lib->settings,
+ "%s.plugins.tpm.tcti.opts", tcti_options[i], lib->ns);
+
+ /* open the selected dynamic TCTI library */
+ tcti_handle = dlopen(tcti_lib, RTLD_LAZY);
+ if (!tcti_handle)
+ {
+ DBG1(DBG_PTS, "%s could not load \"%s\"", LABEL, tcti_lib);
+ return FALSE;
+ }
+
+ infofn = (TSS2_TCTI_INFO_FUNC)dlsym(tcti_handle, TSS2_TCTI_INFO_SYMBOL);
+ if (!infofn)
+ {
+ DBG1(DBG_PTS, "%s symbol \"%s\" not found in \"%s\"", LABEL,
+ TSS2_TCTI_INFO_SYMBOL, tcti_lib);
+ tpm_tss_tss2_deinit();
+
+ return FALSE;
+ }
+ DBG2(DBG_PTS, "%s \"%s\" successfully loaded", LABEL, tcti_lib);
+ info = infofn();
+ tcti_init = info->init;
+
+ return TRUE;
+}
+
+/**
+ * See header
+ */
+void tpm_tss_tss2_deinit(void)
+{
+ dlclose(tcti_handle);
+ tcti_handle = NULL;
+ tcti_init = NULL;
+ tcti_opts = NULL;
+}
+
+#else /* TSS_TSS2_V2 */
+
+/**
+ * See header
+ */
+bool tpm_tss_tss2_init(void)
+{
+ return TRUE;
+}
+
+/**
+ * See header
+ */
+void tpm_tss_tss2_deinit(void)
+{
+ /* empty */
+}
+
+#endif /* TSS_TSS2_V2 */
+