diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2017-02-16 08:39:47 +0100 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2017-02-22 12:18:26 +0100 |
commit | af9341c2c01063bae551454a572343eddbab02aa (patch) | |
tree | f7536b92f58bc313b1a163aeb47a8f8b7e123c78 | |
parent | e8736028e6a228adc0072f112543cb8b64879397 (diff) | |
download | strongswan-af9341c2c01063bae551454a572343eddbab02aa.tar.bz2 strongswan-af9341c2c01063bae551454a572343eddbab02aa.tar.xz |
Use of TPM 2.0 private keys for signatures via tpm plugin
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | src/checksum/Makefile.am | 4 | ||||
-rw-r--r-- | src/checksum/checksum_builder.c | 3 | ||||
-rw-r--r-- | src/libtpmtss/Makefile.am | 27 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/Makefile.am | 20 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_plugin.c | 76 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_plugin.h | 42 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_private_key.c | 239 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_private_key.h | 49 |
10 files changed, 468 insertions, 9 deletions
@@ -8,6 +8,11 @@ strongswan-5.5.2 draft-ietf-ipsecme-eddsa. Ed25519-based public key pairs, X.509 certificates and CRLs can be generated and printed by the pki tool. +- The new "tpm" libtpmtss plugin allows to use persistent private RSA and ECDSA + keys bound to a TPM 2.0 for both IKE and TLS authentication. Using the + TPM 2.0 object handle as keyid parameter, the pki --pub tool can extract + the public key from the TPM thereby replacing the aikpub2 tool. + - In-place update of cached base and delta CRLs does not leave dozens of stale copies in cache memory. diff --git a/configure.ac b/configure.ac index ddedad184..a450e87e8 100644 --- a/configure.ac +++ b/configure.ac @@ -201,6 +201,7 @@ ARG_ENABL_SET([ext-auth], [enable plugin calling an external authorization ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.]) ARG_ENABL_SET([keychain], [enables OS X Keychain Services credential set.]) ARG_ENABL_SET([pkcs11], [enables the PKCS11 token support plugin.]) +ARG_ENABL_SET([tpm], [enables the TPM plugin.]) ARG_DISBL_SET([revocation], [disable X509 CRL/OCSP revocation check plugin.]) ARG_ENABL_SET([whitelist], [enable peer identity whitelisting plugin.]) ARG_DISBL_SET([xauth-generic], [disable generic XAuth backend.]) @@ -1320,15 +1321,17 @@ cmd_plugins= aikgen_plugins= # location specific lists for checksumming, -# for src/libcharon, src/libstrongswan and src/libtnccs +# for src/libcharon, src/libstrongswan, src/libtnccs and src/libtpmtss c_plugins= s_plugins= t_plugins= +p_plugins= ADD_PLUGIN([test-vectors], [s charon scepclient pki]) ADD_PLUGIN([unbound], [s charon scripts]) ADD_PLUGIN([ldap], [s charon scepclient scripts nm cmd]) ADD_PLUGIN([pkcs11], [s charon pki nm cmd]) +ADD_PLUGIN([tpm], [p charon pki nm cmd]) ADD_PLUGIN([aesni], [s charon scepclient pki scripts medsrv attest nm cmd aikgen]) ADD_PLUGIN([aes], [s charon scepclient pki scripts nm cmd]) ADD_PLUGIN([des], [s charon scepclient pki scripts nm cmd]) @@ -1471,7 +1474,7 @@ AC_SUBST(cmd_plugins) AC_SUBST(aikgen_plugins) AC_SUBST(c_plugins) -AC_SUBST(h_plugins) +AC_SUBST(p_plugins) AC_SUBST(s_plugins) AC_SUBST(t_plugins) @@ -1529,6 +1532,7 @@ AM_CONDITIONAL(USE_GCRYPT, test x$gcrypt = xtrue) AM_CONDITIONAL(USE_AGENT, test x$agent = xtrue) AM_CONDITIONAL(USE_KEYCHAIN, test x$keychain = xtrue) AM_CONDITIONAL(USE_PKCS11, test x$pkcs11 = xtrue) +AM_CONDITIONAL(USE_TPM, test x$tpm = xtrue) AM_CONDITIONAL(USE_CHAPOLY, test x$chapoly = xtrue) AM_CONDITIONAL(USE_CTR, test x$ctr = xtrue) AM_CONDITIONAL(USE_CCM, test x$ccm = xtrue) @@ -1655,7 +1659,7 @@ AM_CONDITIONAL(USE_LIBNTTFFT, test x$bliss = xtrue -o x$newhope = 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 -o x$imcv = xtrue) +AM_CONDITIONAL(USE_LIBTPMTSS, test x$tss_trousers = xtrue -o x$tss_tss2 = xtrue -o x$tpm -o x$aikgen = xtrue -o x$aikpub2 = xtrue -o x$imcv = 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) @@ -1914,6 +1918,7 @@ AC_CONFIG_FILES([ src/libcharon/plugins/attr_sql/Makefile src/libcharon/tests/Makefile src/libtpmtss/Makefile + src/libtpmtss/plugins/tpm/Makefile src/stroke/Makefile src/ipsec/Makefile src/starter/Makefile @@ -1981,4 +1986,5 @@ AC_MSG_RESULT([-----------------------------------------------------]) AC_MSG_RESULT([libstrongswan:$s_plugins]) AC_MSG_RESULT([libcharon: $c_plugins]) AC_MSG_RESULT([libtnccs: $t_plugins]) +AC_MSG_RESULT([libtpmtss: $p_plugins]) AC_MSG_RESULT([]) diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am index 88210908a..5db5b79c0 100644 --- a/src/checksum/Makefile.am +++ b/src/checksum/Makefile.am @@ -61,6 +61,10 @@ endif if USE_LIBTPMTSS deps += $(top_builddir)/src/libtpmtss/libtpmtss.la libs += $(DESTDIR)$(ipseclibdir)/libtpmtss.so +if !MONOLITHIC + AM_CPPFLAGS += -DP_PLUGINS=\""${p_plugins}\"" +endif + endif if USE_LIBTNCCS diff --git a/src/checksum/checksum_builder.c b/src/checksum/checksum_builder.c index e8998d5a7..a36014634 100644 --- a/src/checksum/checksum_builder.c +++ b/src/checksum/checksum_builder.c @@ -157,6 +157,9 @@ int main(int argc, char* argv[]) #ifdef S_PLUGINS build_plugin_checksums(S_PLUGINS); #endif +#ifdef P_PLUGINS + build_plugin_checksums(P_PLUGINS); +#endif #ifdef T_PLUGINS build_plugin_checksums(T_PLUGINS); #endif diff --git a/src/libtpmtss/Makefile.am b/src/libtpmtss/Makefile.am index e2c159710..c7ac39a09 100644 --- a/src/libtpmtss/Makefile.am +++ b/src/libtpmtss/Makefile.am @@ -8,12 +8,6 @@ AM_LDFLAGS = \ -no-undefined ipseclib_LTLIBRARIES = libtpmtss.la -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 libtpmtss_la_LIBADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la @@ -26,3 +20,24 @@ if USE_TROUSERS libtpmtss_la_LIBADD += -ltspi endif +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 + +if MONOLITHIC +SUBDIRS = +else +SUBDIRS = . +endif + +if USE_TPM + SUBDIRS += plugins/tpm +if MONOLITHIC + libtpmtss_la_LIBADD += plugins/tpm/libstrongswan-tpm.la +endif +endif + + diff --git a/src/libtpmtss/plugins/tpm/Makefile.am b/src/libtpmtss/plugins/tpm/Makefile.am new file mode 100644 index 000000000..c12f09b55 --- /dev/null +++ b/src/libtpmtss/plugins/tpm/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtpmtss + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-tpm.la +else +plugin_LTLIBRARIES = libstrongswan-tpm.la +libstrongswan_tpm_la_LIBADD = \ + $(top_builddir)/src/libtpmtss/libtpmtss.la +endif + +libstrongswan_tpm_la_SOURCES = \ + tpm_plugin.h tpm_plugin.c \ + tpm_private_key.h tpm_private_key.c + +libstrongswan_tpm_la_LDFLAGS = -module -avoid-version diff --git a/src/libtpmtss/plugins/tpm/tpm_plugin.c b/src/libtpmtss/plugins/tpm/tpm_plugin.c new file mode 100644 index 000000000..3d6321e9e --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_plugin.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 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_plugin.h" +#include "tpm_private_key.h" + +#include <library.h> + +typedef struct private_tpm_plugin_t private_tpm_plugin_t; + +/** + * private data of tpm_plugin + */ +struct private_tpm_plugin_t { + + /** + * public functions + */ + tpm_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_tpm_plugin_t *this) +{ + return "tpm"; +} + +METHOD(plugin_t, get_features, int, + private_tpm_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_REGISTER(PRIVKEY, tpm_private_key_connect, FALSE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), + }; + *features = f; + + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_tpm_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *tpm_plugin_create() +{ + private_tpm_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libtpmtss/plugins/tpm/tpm_plugin.h b/src/libtpmtss/plugins/tpm/tpm_plugin.h new file mode 100644 index 000000000..bf419b328 --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 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 tpm + * @ingroup plugins + * + * @defgroup tpm_plugin tpm_plugin + * @{ @ingroup tpm + */ + +#ifndef TPM_PLUGIN_H_ +#define TPM_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct tpm_plugin_t tpm_plugin_t; + +/** + * Plugin providing TPM token support. + */ +struct tpm_plugin_t { + + /** + * Implements plugin interface, + */ + plugin_t plugin; +}; + +#endif /** TPM_PLUGIN_H_ @}*/ diff --git a/src/libtpmtss/plugins/tpm/tpm_private_key.c b/src/libtpmtss/plugins/tpm/tpm_private_key.c new file mode 100644 index 000000000..bd5a8baeb --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_private_key.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2017 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_private_key.h" + +#include <tpm_tss.h> +#include <utils/debug.h> + +typedef struct private_tpm_private_key_t private_tpm_private_key_t; + +/** + * Private data of an tpm_private_key_t object. + */ +struct private_tpm_private_key_t { + + /** + * Public tpm_private_key_t interface. + */ + tpm_private_key_t public; + + /** + * Token keyid used to reference optional PIN for TPM key + */ + identification_t *keyid; + + /** + * Trusted Platform Module + */ + tpm_tss_t *tpm; + + /** + * TPM key object handle + */ + uint32_t handle; + + /** + * Hierarchy the TPM key object is attached to + */ + uint32_t hierarchy; + + /** + * Associated public key + */ + public_key_t *pubkey; + + /** + * References to this key + */ + refcount_t ref; + +}; + + +METHOD(private_key_t, get_type, key_type_t, + private_tpm_private_key_t *this) +{ + return this->pubkey->get_type(this->pubkey); +} + +METHOD(private_key_t, get_keysize, int, + private_tpm_private_key_t *this) +{ + return this->pubkey->get_keysize(this->pubkey); +} + +METHOD(private_key_t, sign, bool, + private_tpm_private_key_t *this, signature_scheme_t scheme, + chunk_t data, chunk_t *signature) +{ + chunk_t pin = chunk_empty; + shared_key_t *shared; + enumerator_t *enumerator; + + /* check for optional PIN */ + enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, + SHARED_PIN, this->keyid, NULL); + if (enumerator->enumerate(enumerator, &shared, NULL, NULL)) + { + pin = shared->get_key(shared); + } + enumerator->destroy(enumerator); + + return this->tpm->sign(this->tpm, this->hierarchy, this->handle, scheme, + data, pin, signature); +} + +METHOD(private_key_t, decrypt, bool, + private_tpm_private_key_t *this, encryption_scheme_t scheme, + chunk_t crypt, chunk_t *plain) +{ + return FALSE; +} + +METHOD(private_key_t, get_public_key, public_key_t*, + private_tpm_private_key_t *this) +{ + return this->pubkey->get_ref(this->pubkey); +} + +METHOD(private_key_t, get_fingerprint, bool, + private_tpm_private_key_t *this, cred_encoding_type_t type, + chunk_t *fingerprint) +{ + return this->pubkey->get_fingerprint(this->pubkey, type, fingerprint); +} + +METHOD(private_key_t, get_encoding, bool, + private_tpm_private_key_t *this, cred_encoding_type_t type, + chunk_t *encoding) +{ + return FALSE; +} + +METHOD(private_key_t, get_ref, private_key_t*, + private_tpm_private_key_t *this) +{ + ref_get(&this->ref); + return &this->public.key; +} + +METHOD(private_key_t, destroy, void, + private_tpm_private_key_t *this) +{ + if (ref_put(&this->ref)) + { + DESTROY_IF(this->pubkey); + this->tpm->destroy(this->tpm); + this->keyid->destroy(this->keyid); + free(this); + } +} + +/** + * See header. + */ +tpm_private_key_t *tpm_private_key_connect(key_type_t type, va_list args) +{ + private_tpm_private_key_t *this; + tpm_tss_t *tpm; + chunk_t keyid = chunk_empty, pubkey_blob = chunk_empty; + char handle_str[4]; + size_t len; + uint32_t hierarchy = 0x4000000B; /* TPM_RH_ENDORSEMENT */ + uint32_t handle; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_PKCS11_KEYID: + keyid = va_arg(args, chunk_t); + continue; + case BUILD_PKCS11_SLOT: + hierarchy = va_arg(args, int); + continue; + case BUILD_PKCS11_MODULE: + va_arg(args, char*); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + /* convert keyid into 32 bit TPM key object handle */ + if (!keyid.len) + { + return NULL; + } + len = min(keyid.len, 4); + memset(handle_str, 0x00, 4); + memcpy(handle_str + 4 - len, keyid.ptr + keyid.len - len, len); + handle = untoh32(handle_str); + + /* try to find a TPM 2.0 */ + tpm = tpm_tss_probe(TPM_VERSION_2_0); + if (!tpm) + { + DBG1(DBG_LIB, "no TPM 2.0 found"); + return NULL; + } + + INIT(this, + .public = { + .key = { + .get_type = _get_type, + .sign = _sign, + .decrypt = _decrypt, + .get_keysize = _get_keysize, + .get_public_key = _get_public_key, + .equals = private_key_equals, + .belongs_to = private_key_belongs_to, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = private_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .tpm = tpm, + .keyid = identification_create_from_encoding(ID_KEY_ID, keyid), + .handle = handle, + .hierarchy = hierarchy, + .ref = 1, + ); + + /* get public key from TPM */ + pubkey_blob = tpm->get_public(tpm, handle); + if (!pubkey_blob.len) + { + destroy(this); + return NULL; + } + this->pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + BUILD_BLOB_ASN1_DER, pubkey_blob, BUILD_END); + chunk_free(&pubkey_blob); + + if (!this->pubkey) + { + destroy(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libtpmtss/plugins/tpm/tpm_private_key.h b/src/libtpmtss/plugins/tpm/tpm_private_key.h new file mode 100644 index 000000000..d3745e2af --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_private_key.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 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_private_key tpm_private_key + * @{ @ingroup tpm + */ + +#ifndef TPM_PRIVATE_KEY_H_ +#define TPM_PRIVATE_KEY_H_ + +typedef struct tpm_private_key_t tpm_private_key_t; + +#include <credentials/builder.h> +#include <credentials/keys/private_key.h> + +/** + * Private Key implementation for the TPM 2.0 Trusted Platform Module + */ +struct tpm_private_key_t { + + /** + * Implements private_key_t interface. + */ + private_key_t key; +}; + +/** + * Connect to a private key bound to the TPM + * + * @param type type of the key + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +tpm_private_key_t *tpm_private_key_connect(key_type_t type, va_list args); + +#endif /** tpm_PRIVATE_KEY_H_ @}*/ |