diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2018-02-19 18:17:21 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2018-02-19 18:17:21 +0100 |
commit | 7793611ee71b576dd9c66dee327349fa64e38740 (patch) | |
tree | f1379ec1aed52a3c772874d4ed690b90975b9623 /src/libtpmtss | |
parent | e1d78dc2faaa06e7c3f71ef674a71e4de2f0758e (diff) | |
download | vyos-strongswan-7793611ee71b576dd9c66dee327349fa64e38740.tar.gz vyos-strongswan-7793611ee71b576dd9c66dee327349fa64e38740.zip |
New upstream version 5.6.2
Diffstat (limited to 'src/libtpmtss')
-rw-r--r-- | src/libtpmtss/Makefile.am | 2 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/Makefile.am | 1 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/Makefile.in | 6 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_cert.c | 97 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_cert.h | 38 | ||||
-rw-r--r-- | src/libtpmtss/plugins/tpm/tpm_plugin.c | 11 | ||||
-rw-r--r-- | src/libtpmtss/tpm_tss.h | 12 | ||||
-rw-r--r-- | src/libtpmtss/tpm_tss_trousers.c | 8 | ||||
-rw-r--r-- | src/libtpmtss/tpm_tss_tss2.c | 209 |
9 files changed, 374 insertions, 10 deletions
diff --git a/src/libtpmtss/Makefile.am b/src/libtpmtss/Makefile.am index 5f3a97a99..1b3a9706f 100644 --- a/src/libtpmtss/Makefile.am +++ b/src/libtpmtss/Makefile.am @@ -48,5 +48,3 @@ 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 index 281281022..27db5cc01 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_cert.h tpm_cert.c \ tpm_private_key.h tpm_private_key.c \ tpm_rng.h tpm_rng.c diff --git a/src/libtpmtss/plugins/tpm/Makefile.in b/src/libtpmtss/plugins/tpm/Makefile.in index a12c18a35..e03e73656 100644 --- a/src/libtpmtss/plugins/tpm/Makefile.in +++ b/src/libtpmtss/plugins/tpm/Makefile.in @@ -138,8 +138,8 @@ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) @MONOLITHIC_FALSE@libstrongswan_tpm_la_DEPENDENCIES = \ @MONOLITHIC_FALSE@ $(top_builddir)/src/libtpmtss/libtpmtss.la -am_libstrongswan_tpm_la_OBJECTS = tpm_plugin.lo tpm_private_key.lo \ - tpm_rng.lo +am_libstrongswan_tpm_la_OBJECTS = tpm_plugin.lo tpm_cert.lo \ + tpm_private_key.lo tpm_rng.lo libstrongswan_tpm_la_OBJECTS = $(am_libstrongswan_tpm_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -465,6 +465,7 @@ AM_CFLAGS = \ libstrongswan_tpm_la_SOURCES = \ tpm_plugin.h tpm_plugin.c \ + tpm_cert.h tpm_cert.c \ tpm_private_key.h tpm_private_key.c \ tpm_rng.h tpm_rng.c @@ -558,6 +559,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_cert.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_private_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpm_rng.Plo@am__quote@ diff --git a/src/libtpmtss/plugins/tpm/tpm_cert.c b/src/libtpmtss/plugins/tpm/tpm_cert.c new file mode 100644 index 000000000..248da7e53 --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_cert.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2017 Andreas Steffen + * HSR Hochschule für 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_cert.h" + +#include <tpm_tss.h> + +#include <utils/debug.h> + + +/** + * See header. + */ +certificate_t *tpm_cert_load(certificate_type_t type, va_list args) +{ + tpm_tss_t *tpm; + chunk_t keyid = chunk_empty, pin = chunk_empty, data = chunk_empty; + certificate_t *cert; + char handle_str[4]; + size_t len; + uint32_t hierarchy = 0x40000001; /* TPM_RH_OWNER */ + uint32_t handle; + bool success; + + 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; + } + success = tpm->get_data(tpm, hierarchy, handle, pin, &data); + tpm->destroy(tpm); + + if (!success) + { + DBG1(DBG_LIB, "loading certificate from TPM NV index 0x%08x failed", + handle); + return NULL; + } + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, data, BUILD_END); + free(data.ptr); + + if (!cert) + { + DBG1(DBG_LIB, "parsing certificate from TPM NV index 0x%08x failed", + handle); + return NULL; + } + DBG1(DBG_LIB, "loaded certificate from TPM NV index 0x%08x", handle); + + return cert; +} diff --git a/src/libtpmtss/plugins/tpm/tpm_cert.h b/src/libtpmtss/plugins/tpm/tpm_cert.h new file mode 100644 index 000000000..a6cb34554 --- /dev/null +++ b/src/libtpmtss/plugins/tpm/tpm_cert.h @@ -0,0 +1,38 @@ +/* + * 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_cert tpm_cert + * @{ @ingroup tpm + */ + +#ifndef TPM_CERT_H_ +#define TPM_CERT_H_ + +#include <credentials/certificates/certificate.h> + +/** + * Load a specific certificate from a TPM + * + * Requires a BUILD_PKCS11_KEYID argument, and optionally a BUILD_PKCS11_SLOT + * to designate the NV storage hierarchy. + * + * @param type certificate type, must be CERT_X509 + * @param args variable argument list, containing BUILD_PKCS11_KEYID. + * @return loaded certificate, or NULL on failure + */ +certificate_t *tpm_cert_load(certificate_type_t type, va_list args); + +#endif /** TPM_CERT_H_ @}*/ diff --git a/src/libtpmtss/plugins/tpm/tpm_plugin.c b/src/libtpmtss/plugins/tpm/tpm_plugin.c index b9a4c12a8..e98899852 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_cert.h" #include "tpm_rng.h" #include <library.h> @@ -50,13 +51,19 @@ METHOD(plugin_t, get_features, int, 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 plugin_feature_t f_cert[] = { + PLUGIN_REGISTER(CERT_DECODE, tpm_cert_load, FALSE), + PLUGIN_PROVIDE(CERT_DECODE, CERT_X509), + PLUGIN_DEPENDS(CERT_DECODE, CERT_X509), + }; + static plugin_feature_t f[countof(f_rng) + countof(f_privkey) + + countof(f_cert)] = {}; static int count = 0; if (!count) { plugin_features_add(f, f_privkey, countof(f_privkey), &count); + plugin_features_add(f, f_cert, countof(f_cert), &count); if (lib->settings->get_bool(lib->settings, "%s.plugins.tpm.use_rng", FALSE, lib->ns)) diff --git a/src/libtpmtss/tpm_tss.h b/src/libtpmtss/tpm_tss.h index f408d0440..bcb7ab949 100644 --- a/src/libtpmtss/tpm_tss.h +++ b/src/libtpmtss/tpm_tss.h @@ -144,6 +144,18 @@ struct tpm_tss_t { bool (*get_random)(tpm_tss_t *this, size_t bytes, uint8_t *buffer); /** + * Get a data blob from TPM NV store using its object handle (TPM 2.0 only) + * + * @param handle object handle of TPM key to be used for signature + * @param hierarchy hierarchy the TPM key object is attached to + * @param pin PIN code or empty chunk + * @param data returns data blob + * @return TRUE if data retrieval succeeded + */ + bool (*get_data)(tpm_tss_t *this, uint32_t hierarchy, uint32_t handle, + chunk_t pin, chunk_t *data); + + /** * 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 d5bc2b84f..6ed57af9d 100644 --- a/src/libtpmtss/tpm_tss_trousers.c +++ b/src/libtpmtss/tpm_tss_trousers.c @@ -595,6 +595,13 @@ METHOD(tpm_tss_t, get_random, bool, return FALSE; } +METHOD(tpm_tss_t, get_data, bool, + private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle, + chunk_t pin, chunk_t *data) +{ + return FALSE; +} + METHOD(tpm_tss_t, destroy, void, private_tpm_tss_trousers_t *this) { @@ -639,6 +646,7 @@ tpm_tss_t *tpm_tss_trousers_create() .quote = _quote, .sign = _sign, .get_random = _get_random, + .get_data = _get_data, .destroy = _destroy, }, .load_aik = _load_aik, diff --git a/src/libtpmtss/tpm_tss_tss2.c b/src/libtpmtss/tpm_tss_tss2.c index 4c0d95fe5..8b91fb44a 100644 --- a/src/libtpmtss/tpm_tss_tss2.c +++ b/src/libtpmtss/tpm_tss_tss2.c @@ -150,14 +150,56 @@ static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM_ALG_ID alg_id) 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; TPM_ALG_ID alg; - uint32_t rval, i; + uint32_t rval, i, offset, revision = 0, year = 0; size_t len = BUF_LEN; - char buf[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, TPM_CAP_TPM_PROPERTIES, + PT_FIXED, MAX_TPM_PROPERTIES, &more_data, &cap_data, 0); + if (rval != TPM_RC_SUCCESS) + { + DBG1(DBG_PTS, "%s GetCapability failed for TPM_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 TPM_PT_REVISION: + revision = tp.value; + break; + case TPM_PT_YEAR: + year = tp.value; + break; + case TPM_PT_MANUFACTURER: + htoun32(manufacturer, tp.value); + break; + case TPM_PT_VENDOR_STRING_1: + case TPM_PT_VENDOR_STRING_2: + case TPM_PT_VENDOR_STRING_3: + case TPM_PT_VENDOR_STRING_4: + offset = 4 * (tp.property - TPM_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, TPM_CAP_ALGS, 0, TPM_PT_ALGORITHM_SET, &more_data, &cap_data, 0); @@ -433,6 +475,7 @@ METHOD(tpm_tss_t, get_public, chunk_t, { DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key " "failed", LABEL); + return chunk_empty; } break; } @@ -563,8 +606,93 @@ 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) { - /* TODO */ - return FALSE; + uint32_t rval; + TPM_ALG_ID alg_id; + TPML_DIGEST_VALUES digest_values; + TPMS_AUTH_COMMAND session_data_cmd; + TPMS_AUTH_RESPONSE session_data_rsp; + TSS2_SYS_CMD_AUTHS sessions_data_cmd; + TSS2_SYS_RSP_AUTHS sessions_data_rsp; + TPMS_AUTH_COMMAND *session_data_cmd_array[1]; + TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; + + session_data_cmd_array[0] = &session_data_cmd; + session_data_rsp_array[0] = &session_data_rsp; + + sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; + sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; + + sessions_data_cmd.cmdAuthsCount = 1; + sessions_data_rsp.rspAuthsCount = 1; + + session_data_cmd.sessionHandle = TPM_RS_PW; + session_data_cmd.hmac.t.size = 0; + session_data_cmd.nonce.t.size = 0; + + *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; + + /* 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, &sessions_data_cmd, + &digest_values, &sessions_data_rsp); + if (rval != TPM_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, @@ -913,6 +1041,78 @@ METHOD(tpm_tss_t, get_random, bool, 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 nv_size, nv_offset = 0; + uint32_t rval; + + 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, } }; + TPMS_AUTH_COMMAND session_data_cmd; + TPMS_AUTH_RESPONSE session_data_rsp; + TSS2_SYS_CMD_AUTHS sessions_data_cmd; + TSS2_SYS_RSP_AUTHS sessions_data_rsp; + TPMS_AUTH_COMMAND *session_data_cmd_array[1]; + TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; + + /* get size of NV object */ + rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public, + &nv_name, 0); + if (rval != TPM_RC_SUCCESS) + { + DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval); + return FALSE; + } + nv_size = nv_public.t.nvPublic.dataSize; + *data = chunk_alloc(nv_size); + + /*prepare NV read session */ + session_data_cmd_array[0] = &session_data_cmd; + session_data_rsp_array[0] = &session_data_rsp; + + sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; + sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; + + sessions_data_cmd.cmdAuthsCount = 1; + sessions_data_rsp.rspAuthsCount = 1; + + session_data_cmd.sessionHandle = TPM_RS_PW; + session_data_cmd.nonce.t.size = 0; + session_data_cmd.hmac.t.size = 0; + + if (pin.len > 0) + { + session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2, + pin.len); + memcpy(session_data_cmd.hmac.t.buffer, pin.ptr, + session_data_cmd.hmac.t.size); + } + *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; + + /* read NV data an NV buffer 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), + nv_offset, &nv_data, &sessions_data_rsp); + + if (rval != TPM_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.t.buffer, nv_data.t.size); + nv_offset += nv_data.t.size; + nv_size -= nv_data.t.size; + } + + return TRUE; +} + METHOD(tpm_tss_t, destroy, void, private_tpm_tss_tss2_t *this) { @@ -939,6 +1139,7 @@ tpm_tss_t *tpm_tss_tss2_create() .quote = _quote, .sign = _sign, .get_random = _get_random, + .get_data = _get_data, .destroy = _destroy, }, ); |