diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2017-03-18 14:51:30 +0100 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2017-03-20 21:16:10 +0100 |
commit | 2b233c8a6401ec7911177079aa89bbbf30feeefb (patch) | |
tree | 77b65d2183021a583e1ff2451092fea01f8b319d | |
parent | 46d4d2a71e483de41ca0e0412c73da41b3b2f675 (diff) | |
download | strongswan-2b233c8a6401ec7911177079aa89bbbf30feeefb.tar.bz2 strongswan-2b233c8a6401ec7911177079aa89bbbf30feeefb.tar.xz |
The tpm plugin offers random number generation
The tpm plugin can be used to derive true random numbers from a
TPM 2.0 device. The get_random method must be explicitly enabled
in strongswan.conf with the plugin.tpm.use_rng = yes option.
-rw-r--r-- | conf/Makefile.am | 1 | ||||
-rw-r--r-- | conf/plugins/tpm.opt | 2 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/Makefile.am | 3 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_plugin.c | 24 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_rng.c | 94 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_rng.h | 47 | ||||
-rw-r--r-- | src/libtpmtss/tpm_tss.h | 9 | ||||
-rw-r--r-- | src/libtpmtss/tpm_tss_trousers.c | 7 | ||||
-rw-r--r-- | src/libtpmtss/tpm_tss_tss2.c | 27 |
9 files changed, 211 insertions, 3 deletions
diff --git a/conf/Makefile.am b/conf/Makefile.am index 41912c43a..731446a3e 100644 --- a/conf/Makefile.am +++ b/conf/Makefile.am @@ -93,6 +93,7 @@ plugins = \ plugins/tnc-pdp.opt \ plugins/tnccs-11.opt \ plugins/tnccs-20.opt \ + plugins/tpm.opt \ plugins/unbound.opt \ plugins/updown.opt \ plugins/vici.opt \ diff --git a/conf/plugins/tpm.opt b/conf/plugins/tpm.opt new file mode 100644 index 000000000..cd666dde8 --- /dev/null +++ b/conf/plugins/tpm.opt @@ -0,0 +1,2 @@ +charon.plugins.tpm.use_rng = no + Whether the TPM should be used as RNG. diff --git a/src/libtpmtss/plugins/tpm/Makefile.am b/src/libtpmtss/plugins/tpm/Makefile.am index c12f09b55..281281022 100644 --- a/src/libtpmtss/plugins/tpm/Makefile.am +++ b/src/libtpmtss/plugins/tpm/Makefile.am @@ -15,6 +15,7 @@ endif libstrongswan_tpm_la_SOURCES = \ tpm_plugin.h tpm_plugin.c \ - tpm_private_key.h tpm_private_key.c + tpm_private_key.h tpm_private_key.c \ + tpm_rng.h tpm_rng.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 index 3d6321e9e..b9a4c12a8 100644 --- a/src/libtpmtss/plugins/tpm/tpm_plugin.c +++ b/src/libtpmtss/plugins/tpm/tpm_plugin.c @@ -15,6 +15,7 @@ #include "tpm_plugin.h" #include "tpm_private_key.h" +#include "tpm_rng.h" #include <library.h> @@ -40,13 +41,32 @@ METHOD(plugin_t, get_name, char*, METHOD(plugin_t, get_features, int, private_tpm_plugin_t *this, plugin_feature_t *features[]) { - static plugin_feature_t f[] = { + static plugin_feature_t f_rng[] = { + PLUGIN_REGISTER(RNG, tpm_rng_create), + PLUGIN_PROVIDE(RNG, RNG_STRONG), + PLUGIN_PROVIDE(RNG, RNG_TRUE), + }; + static plugin_feature_t f_privkey[] = { PLUGIN_REGISTER(PRIVKEY, tpm_private_key_connect, FALSE), PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), }; + static plugin_feature_t f[countof(f_rng) + countof(f_privkey)] = {}; + + static int count = 0; + + if (!count) + { + plugin_features_add(f, f_privkey, countof(f_privkey), &count); + + if (lib->settings->get_bool(lib->settings, + "%s.plugins.tpm.use_rng", FALSE, lib->ns)) + { + plugin_features_add(f, f_rng, countof(f_rng), &count); + } + } *features = f; - return countof(f); + return count; } METHOD(plugin_t, destroy, void, diff --git a/src/libtpmtss/plugins/tpm/tpm_rng.c b/src/libtpmtss/plugins/tpm/tpm_rng.c new file mode 100644 index 000000000..d96bc4936 --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_rng.c @@ -0,0 +1,94 @@ +/* + * 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_rng.h" + +#include <tpm_tss.h> +#include <utils/debug.h> + +typedef struct private_tpm_rng_t private_tpm_rng_t; + +/** + * Private data of an tpm_rng_t object. + */ +struct private_tpm_rng_t { + + /** + * Public interface. + */ + tpm_rng_t public; + + /** + * Trusted Platform Module + */ + tpm_tss_t *tpm; + +}; + +METHOD(rng_t, get_bytes, bool, + private_tpm_rng_t *this, size_t bytes, uint8_t *buffer) +{ + return this->tpm->get_random(this->tpm, bytes, buffer); +} + +METHOD(rng_t, allocate_bytes, bool, + private_tpm_rng_t *this, size_t bytes, chunk_t *chunk) +{ + *chunk = chunk_alloc(bytes); + if (!get_bytes(this, chunk->len, chunk->ptr)) + { + chunk_clear(chunk); + return FALSE; + } + return TRUE; +} + +METHOD(rng_t, destroy, void, + private_tpm_rng_t *this) +{ + this->tpm->destroy(this->tpm); + free(this); +} + +/* + * Described in header. + */ +tpm_rng_t *tpm_rng_create(rng_quality_t quality) +{ + private_tpm_rng_t *this; + tpm_tss_t *tpm; + + /* 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 = { + .rng = { + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .destroy = _destroy, + }, + }, + .tpm = tpm, + ); + + return &this->public; +} + diff --git a/src/libtpmtss/plugins/tpm/tpm_rng.h b/src/libtpmtss/plugins/tpm/tpm_rng.h new file mode 100644 index 000000000..de96816ac --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_rng.h @@ -0,0 +1,47 @@ +/* + * 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_rng tpm_rng + * @{ @ingroup tpm + */ + +#ifndef TPM_RNG_H_ +#define TPM_RNG_H_ + +typedef struct tpm_rng_t tpm_rng_t; + +#include <library.h> + +/** + * rng_t implementation via TSS 2.0 + */ +struct tpm_rng_t { + + /** + * Implements rng_t. + */ + rng_t rng; +}; + +/** + * Creates a tpm_rng_t instance. + * + * @param quality required quality of randomness + * @return created tpm_rng_t + */ +tpm_rng_t *tpm_rng_create(rng_quality_t quality); + +#endif /** TPM_RNG_H_ @} */ diff --git a/src/libtpmtss/tpm_tss.h b/src/libtpmtss/tpm_tss.h index 270e7dfcf..f408d0440 100644 --- a/src/libtpmtss/tpm_tss.h +++ b/src/libtpmtss/tpm_tss.h @@ -135,6 +135,15 @@ struct tpm_tss_t { chunk_t *signature); /** + * Get random bytes from the TPM + * + * @param bytes number of random bytes requested + * @param buffer buffer where the random bytes are written into + * @return TRUE if random bytes could be delivered + */ + bool (*get_random)(tpm_tss_t *this, size_t bytes, uint8_t *buffer); + + /** * Destroy a tpm_tss_t. */ void (*destroy)(tpm_tss_t *this); diff --git a/src/libtpmtss/tpm_tss_trousers.c b/src/libtpmtss/tpm_tss_trousers.c index 550e6218a..d5bc2b84f 100644 --- a/src/libtpmtss/tpm_tss_trousers.c +++ b/src/libtpmtss/tpm_tss_trousers.c @@ -589,6 +589,12 @@ METHOD(tpm_tss_t, sign, bool, return FALSE; } +METHOD(tpm_tss_t, get_random, bool, + private_tpm_tss_trousers_t *this, size_t bytes, uint8_t *buffer) +{ + return FALSE; +} + METHOD(tpm_tss_t, destroy, void, private_tpm_tss_trousers_t *this) { @@ -632,6 +638,7 @@ tpm_tss_t *tpm_tss_trousers_create() .extend_pcr = _extend_pcr, .quote = _quote, .sign = _sign, + .get_random = _get_random, .destroy = _destroy, }, .load_aik = _load_aik, diff --git a/src/libtpmtss/tpm_tss_tss2.c b/src/libtpmtss/tpm_tss_tss2.c index 358961745..9a4b9a40c 100644 --- a/src/libtpmtss/tpm_tss_tss2.c +++ b/src/libtpmtss/tpm_tss_tss2.c @@ -829,6 +829,32 @@ METHOD(tpm_tss_t, sign, bool, 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.t.buffer, random.t.size); + pos += random.t.size; + bytes -= random.t.size; + } + + return TRUE; +} + METHOD(tpm_tss_t, destroy, void, private_tpm_tss_tss2_t *this) { @@ -854,6 +880,7 @@ tpm_tss_t *tpm_tss_tss2_create() .extend_pcr = _extend_pcr, .quote = _quote, .sign = _sign, + .get_random = _get_random, .destroy = _destroy, }, ); |