From: Andreas Steffen Date: Wed, 16 Sep 2020 15:15:05 +0000 (+0200) Subject: pts: Parse TPM 2.0 BIOS/EFI event log X-Git-Tag: 5.9.1dr1~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d647a8f91deff9ca73b51480a068222cc4db8a4e;p=thirdparty%2Fstrongswan.git pts: Parse TPM 2.0 BIOS/EFI event log --- diff --git a/src/libimcv/pts/components/ita/ita_comp_ima.c b/src/libimcv/pts/components/ita/ita_comp_ima.c index 9ba72d01d0..a2820b3422 100644 --- a/src/libimcv/pts/components/ita/ita_comp_ima.c +++ b/src/libimcv/pts/components/ita/ita_comp_ima.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Andreas Steffen + * Copyright (C) 2011-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -350,6 +350,10 @@ METHOD(pts_component_t, measure, status_t, status_t status; pcrs = pts->get_pcrs(pts); + if (!pcrs) + { + return FAILED; + } if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL | PTS_ITA_QUALIFIER_TYPE_TRUSTED)) @@ -357,8 +361,8 @@ METHOD(pts_component_t, measure, status_t, switch (this->state) { case IMA_STATE_INIT: - this->bios_list = pts_ima_bios_list_create( - IMA_BIOS_MEASUREMENTS); + this->bios_list = pts_ima_bios_list_create(pts->get_tpm(pts), + IMA_BIOS_MEASUREMENTS); if (!this->bios_list) { return FAILED; @@ -534,6 +538,10 @@ METHOD(pts_component_t, verify, status_t, this->aik_id = pts->get_aik_id(pts); pcrs = pts->get_pcrs(pts); + if (!pcrs) + { + return FAILED; + } measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform, &creation_time); diff --git a/src/libimcv/pts/components/ita/ita_comp_tboot.c b/src/libimcv/pts/components/ita/ita_comp_tboot.c index 324c41f127..5452142833 100644 --- a/src/libimcv/pts/components/ita/ita_comp_tboot.c +++ b/src/libimcv/pts/components/ita/ita_comp_tboot.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2015 Andreas Steffen + * Copyright (C) 2011-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -173,6 +173,10 @@ METHOD(pts_component_t, measure, status_t, } pcrs = pts->get_pcrs(pts); + if (!pcrs) + { + return FAILED; + } pcrs->set(pcrs, extended_pcr, pcr_after); evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name), this->depth, extended_pcr, hash_algo, pcr_transform, @@ -198,6 +202,10 @@ METHOD(pts_component_t, verify, status_t, this->aik_id = pts->get_aik_id(pts); pcrs = pts->get_pcrs(pts); + if (!pcrs) + { + return FAILED; + } measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); diff --git a/src/libimcv/pts/components/ita/ita_comp_tgrub.c b/src/libimcv/pts/components/ita/ita_comp_tgrub.c index a5a1a9b964..6a1ec6cb34 100644 --- a/src/libimcv/pts/components/ita/ita_comp_tgrub.c +++ b/src/libimcv/pts/components/ita/ita_comp_tgrub.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -129,6 +129,10 @@ METHOD(pts_component_t, verify, status_t, chunk_t measurement __attribute__((unused)); pcrs = pts->get_pcrs(pts); + if (!pcrs) + { + return FAILED; + } measurement = evidence->get_measurement(evidence, &extended_pcr, &algo, &transform, &measurement_time); if (extended_pcr != PCR_DEBUG) diff --git a/src/libimcv/pts/pts.c b/src/libimcv/pts/pts.c index 7321d6708b..2df30369d1 100644 --- a/src/libimcv/pts/pts.c +++ b/src/libimcv/pts/pts.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2011-2012 Sansar Choinyambuu - * Copyright (C) 2012-2016 Andreas Steffen + * Copyright (C) 2012-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -96,12 +95,17 @@ struct private_pts_t { bool is_imc; /** - * Active TPM + * IMC-PTS: own TPM / IMV-PTS: unused */ tpm_tss_t *tpm; /** - * Contains a TPM_CAP_VERSION_INFO struct + * IMC-PTS: own TPM version / IMV-PTS: peer TPM version + */ + tpm_version_t tpm_version; + + /** + * Contains a TPM Version Info struct */ chunk_t tpm_version_info; @@ -311,6 +315,12 @@ METHOD(pts_t, set_platform_id, void, this->platform_id = pid; } +METHOD(pts_t, get_tpm, tpm_tss_t*, + private_pts_t *this) +{ + return this->tpm; +} + METHOD(pts_t, get_tpm_version_info, bool, private_pts_t *this, chunk_t *info) { @@ -319,9 +329,68 @@ METHOD(pts_t, get_tpm_version_info, bool, return info->len > 0; } +#define TPM_VERSION_INFO_TAG_1_2 0x0030 +#define TPM_VERSION_INFO_TAG_2_0 0x0200 +#define TPM_VERSION_INFO_LABEL "Version Information: TPM" + METHOD(pts_t, set_tpm_version_info, void, private_pts_t *this, chunk_t info) { + bio_reader_t *reader; + uint16_t tpm_version_info_tag; + chunk_t vendor; + + reader = bio_reader_create(info); + reader->read_uint16(reader, &tpm_version_info_tag); + + if (tpm_version_info_tag == TPM_VERSION_INFO_TAG_1_2) + { + uint8_t major, minor, rev_major, rev_minor, errata_rev; + uint16_t spec_level; + + this->tpm_version = TPM_VERSION_1_2; + + if (reader->read_uint8 (reader, &major) && + reader->read_uint8 (reader, &minor) && + reader->read_uint8 (reader, &rev_major) && + reader->read_uint8 (reader, &rev_minor) && + reader->read_uint16(reader, &spec_level) && + reader->read_uint8 (reader, &errata_rev) && + reader->read_data (reader, 4, &vendor)) + { + DBG2(DBG_PTS, "%s 1.2 rev. %u.%u.%u.%u %.*s", TPM_VERSION_INFO_LABEL, + (uint32_t)major, (uint32_t)minor, (uint32_t)rev_major, + (uint32_t)rev_minor, vendor.len, vendor.ptr); + } + else + { + DBG2(DBG_PTS, "%s 1.2", TPM_VERSION_INFO_LABEL); + } + + } + else if (tpm_version_info_tag == TPM_VERSION_INFO_TAG_2_0) + { + uint32_t revision, year; + uint8_t reserved, locality; + + this->tpm_version = TPM_VERSION_2_0; + + if (reader->read_uint16(reader, &reserved) && + reader->read_uint32(reader, &revision) && + reader->read_uint32(reader, &year) && + reader->read_data (reader, 4, &vendor)) + { + DBG2(DBG_PTS, "%s 2.0 rev. %4.2f %u %.*s - startup locality: %u", + TPM_VERSION_INFO_LABEL, revision/100.0, year, + vendor.len, vendor.ptr, (uint32_t)locality); + } + else + { + DBG2(DBG_PTS, "%s 2.0", TPM_VERSION_INFO_LABEL); + } + } + reader->destroy(reader); + this->tpm_version_info = chunk_clone(info); } @@ -775,6 +844,10 @@ METHOD(pts_t, verify_quote_signature, bool, METHOD(pts_t, get_pcrs, pts_pcr_t*, private_pts_t *this) { + if (!this->pcrs) + { + this->pcrs = pts_pcr_create(this->tpm_version); + } return this->pcrs; } @@ -798,14 +871,6 @@ METHOD(pts_t, destroy, void, pts_t *pts_create(bool is_imc) { private_pts_t *this; - pts_pcr_t *pcrs; - - pcrs = pts_pcr_create(); - if (!pcrs) - { - DBG1(DBG_PTS, "shadow PCR set could not be created"); - return NULL; - } INIT(this, .public = { @@ -821,6 +886,7 @@ pts_t *pts_create(bool is_imc) .calculate_secret = _calculate_secret, .get_platform_id = _get_platform_id, .set_platform_id = _set_platform_id, + .get_tpm = _get_tpm, .get_tpm_version_info = _get_tpm_version_info, .set_tpm_version_info = _set_tpm_version_info, .get_aik = _get_aik, @@ -840,7 +906,6 @@ pts_t *pts_create(bool is_imc) .proto_caps = PTS_PROTO_CAPS_V, .algorithm = PTS_MEAS_ALGO_SHA256, .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256, - .pcrs = pcrs, ); if (is_imc) @@ -849,12 +914,14 @@ pts_t *pts_create(bool is_imc) if (this->tpm) { this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D; + this->tpm_version = this->tpm->get_version(this->tpm); load_aik(this); } } else { this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D; + this->tpm_version = TPM_VERSION_2_0; } return &this->public; diff --git a/src/libimcv/pts/pts.h b/src/libimcv/pts/pts.h index f3da659dc8..b9fac0a6e5 100644 --- a/src/libimcv/pts/pts.h +++ b/src/libimcv/pts/pts.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2011 Sansar Choinyambuu - * Copyright (C) 2012-2016 Andreas Steffen + * Copyright (C) 2012-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ typedef struct pts_t pts_t; #include "components/pts_comp_func_name.h" #include +#include #include #include @@ -174,18 +175,25 @@ struct pts_t { */ void (*set_platform_id)(pts_t *this, int pid); + /** + * Get TPM object handle + * + * @return TPM object handle + */ + tpm_tss_t* (*get_tpm)(pts_t *this); + /** * Get TPM 1.2 Version Info * - * @param info chunk containing a TPM_CAP_VERSION_INFO struct - * @return TRUE if TPM Version Info available + * @param info chunk containing a TPM_Version Info struct + * @return TRUE if TPM Version_Info available */ bool (*get_tpm_version_info)(pts_t *this, chunk_t *info); /** * Set TPM 1.2 Version Info * - * @param info chunk containing a TPM_CAP_VERSION_INFO struct + * @param info chunk containing a TPM Version Info struct */ void (*set_tpm_version_info)(pts_t *this, chunk_t info); diff --git a/src/libimcv/pts/pts_ima_bios_list.c b/src/libimcv/pts/pts_ima_bios_list.c index 7caa514a58..8695ab153c 100644 --- a/src/libimcv/pts/pts_ima_bios_list.c +++ b/src/libimcv/pts/pts_ima_bios_list.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2014 Andreas Steffen + * Copyright (C) 2011-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ typedef struct private_pts_ima_bios_list_t private_pts_ima_bios_list_t; typedef struct bios_entry_t bios_entry_t; typedef enum event_type_t event_type_t; +/* BIOS Events (TCG PC Client Specification for Conventional BIOS 1.21) */ enum event_type_t { - /* BIOS Events (TCG PC Client Specification for Conventional BIOS 1.21) */ EV_PREBOOT_CERT = 0x00000000, EV_POST_CODE = 0x00000001, EV_UNUSED = 0x00000002, @@ -50,22 +50,25 @@ enum event_type_t { EV_OMIT_BOOT_DEVICE_EVENTS = 0x00000012, /* EFI Events (TCG EFI Platform Specification 1.22) */ - EV_EFI_EVENT_BASE = 0x80000000, - EV_EFI_VARIABLE_DRIVER_CONFIG = 0x80000001, - EV_EFI_VARIABLE_BOOT = 0x80000002, - EV_EFI_BOOT_SERVICES_APPLICATION = 0x80000003, - EV_EFI_BOOT_SERVICES_DRIVER = 0x80000004, - EV_EFI_RUNTIME_SERVICES_DRIVER = 0x80000005, - EV_EFI_GPT_EVENT = 0x80000006, - EV_EFI_ACTION = 0x80000007, - EV_EFI_PLATFORM_FIRMWARE_BLOB = 0x80000008, - EV_EFI_HANDOFF_TABLES = 0x80000009, - - EV_EFI_HCRTM_EVENT = 0x80000010, - - EV_EFI_VARIABLE_AUTHORITY = 0x800000E0 + EV_EFI_VARIABLE_DRIVER_CONFIG = 0x70000001, + EV_EFI_VARIABLE_BOOT = 0x70000002, + EV_EFI_BOOT_SERVICES_APPLICATION = 0x70000003, + EV_EFI_BOOT_SERVICES_DRIVER = 0x70000004, + EV_EFI_RUNTIME_SERVICES_DRIVER = 0x70000005, + EV_EFI_GPT_EVENT = 0x70000006, + EV_EFI_ACTION = 0x70000007, + EV_EFI_PLATFORM_FIRMWARE_BLOB = 0x70000008, + EV_EFI_HANDOFF_TABLES = 0x70000009, + + EV_EFI_HCRTM_EVENT = 0x70000010, + + EV_EFI_VARIABLE_AUTHORITY = 0x700000E0, }; +/* By subtracting an offset from EFI events the enum will always be positive */ +#define EV_EFI_EVENT_BASE 0x80000000 +#define EV_EFI_OFFSET 0x10000000 + ENUM_BEGIN(event_type_names, EV_PREBOOT_CERT, EV_OMIT_BOOT_DEVICE_EVENTS, "Preboot Cert", "POST Code", @@ -87,9 +90,8 @@ ENUM_BEGIN(event_type_names, EV_PREBOOT_CERT, EV_OMIT_BOOT_DEVICE_EVENTS, "Nonhost Info", "Omit Boot Device Events" ); -ENUM_NEXT(event_type_names, EV_EFI_EVENT_BASE, EV_EFI_HANDOFF_TABLES, +ENUM_NEXT(event_type_names, EV_EFI_VARIABLE_DRIVER_CONFIG, EV_EFI_HANDOFF_TABLES, EV_OMIT_BOOT_DEVICE_EVENTS, - "EFI Event Base", "EFI Variable Driver Config", "EFI Variable Boot", "EFI Boot Services Application", @@ -194,11 +196,11 @@ METHOD(pts_ima_bios_list_t, destroy, void, /** * See header */ -pts_ima_bios_list_t* pts_ima_bios_list_create(char *file) +pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file) { private_pts_ima_bios_list_t *this; - uint32_t pcr, event_type, event_len, seek_len; - uint32_t buf_len = 2048; + uint32_t pcr, ev_type, event_type, event_len, seek_len, count = 1; + uint32_t buf_len = 8192; uint8_t event_buf[buf_len]; chunk_t event; bios_entry_t *entry; @@ -206,6 +208,12 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(char *file) ssize_t res; int fd; + if (!tpm) + { + DBG1(DBG_PTS, "no TPM available"); + return NULL; + } + fd = open(file, O_RDONLY); if (fd == -1) { @@ -232,7 +240,7 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(char *file) .list = linked_list_create(), ); - DBG2(DBG_PTS, "PCR Event Type (Size)"); + DBG2(DBG_PTS, "No. PCR Event Type (Size)"); while (TRUE) { res = read(fd, &pcr, 4); @@ -246,7 +254,7 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(char *file) entry = malloc_thing(bios_entry_t); entry->pcr = pcr; - entry->measurement = chunk_alloc(HASH_SIZE_SHA1); + entry->measurement = chunk_empty; if (res != 4) { @@ -256,7 +264,7 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(char *file) { break; } - if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1) + if (!tpm->get_event_digest(tpm, fd, &entry->measurement)) { break; } @@ -264,9 +272,10 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(char *file) { break; } - DBG2(DBG_PTS, "%2u %N (%u bytes)", pcr, event_type_names, event_type, - event_len); - + ev_type = (event_type < EV_EFI_EVENT_BASE) ? + event_type : event_type - EV_EFI_OFFSET; + DBG2(DBG_PTS, "%3u %2u %N (%u bytes)", count, pcr, event_type_names, + ev_type, event_len); seek_len = (event_len > buf_len) ? event_len - buf_len : 0; event_len -= seek_len; @@ -274,23 +283,49 @@ pts_ima_bios_list_t* pts_ima_bios_list_create(char *file) { break; } - event = chunk_create(event_buf, event_len); - DBG3(DBG_PTS,"%B", &event); - if (event_type == EV_ACTION || event_type == EV_EFI_ACTION) + switch (event_type) { - DBG2(DBG_PTS, " '%.*s'", event_len, event_buf); + case EV_PREBOOT_CERT: + case EV_POST_CODE: + case EV_NO_ACTION: + case EV_ACTION: + case EV_EFI_ACTION: + case EV_S_CRTM_CONTENTS: + case EV_IPL: + if (event_type == EV_NO_ACTION && event_len == 17 && + streq(event_buf, "StartupLocality")) + { + DBG2(DBG_PTS, " 'StartupLocality' %x", event_buf[16]); + } + else + { + DBG2(DBG_PTS, " '%.*s'", event_len, event_buf); + } + break; + default: + break; } + event = chunk_create(event_buf, event_len); + DBG3(DBG_PTS,"%B", &event); if (seek_len > 0 && lseek(fd, seek_len, SEEK_CUR) == -1) { break; } - this->list->insert_last(this->list, entry); + if (event_type == EV_NO_ACTION || entry->measurement.len == 0) + { + free_bios_entry(entry); + DBG2(DBG_PTS, " Not extended into PCR!"); + } + else + { + this->list->insert_last(this->list, entry); + count++; + } } - DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file, - strerror(errno)); + DBG1(DBG_PTS, "loading bios measurements '%s' failed", file); free_bios_entry(entry); close(fd); destroy(this); diff --git a/src/libimcv/pts/pts_ima_bios_list.h b/src/libimcv/pts/pts_ima_bios_list.h index ad162e15a8..701a0876ae 100644 --- a/src/libimcv/pts/pts_ima_bios_list.h +++ b/src/libimcv/pts/pts_ima_bios_list.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Andreas Steffen + * Copyright (C) 2014-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include #include +#include typedef struct pts_ima_bios_list_t pts_ima_bios_list_t; @@ -67,8 +68,9 @@ struct pts_ima_bios_list_t { /** * Create a PTS IMA BIOS measurement object * + * @param tpm TPM object * @param file Pathname pointing to the BIOS measurements */ -pts_ima_bios_list_t* pts_ima_bios_list_create(char *file); +pts_ima_bios_list_t* pts_ima_bios_list_create(tpm_tss_t *tpm, char *file); #endif /** PTS_IMA_BIOS_LIST_H_ @}*/ diff --git a/src/libimcv/pts/pts_pcr.c b/src/libimcv/pts/pts_pcr.c index 9f098c08eb..28593a9b98 100644 --- a/src/libimcv/pts/pts_pcr.c +++ b/src/libimcv/pts/pts_pcr.c @@ -243,7 +243,7 @@ METHOD(pts_pcr_t, destroy, void, /** * See header */ -pts_pcr_t *pts_pcr_create(void) +pts_pcr_t *pts_pcr_create(tpm_version_t tpm_version) { private_pts_pcr_t *this; hasher_t *hasher; @@ -278,6 +278,16 @@ pts_pcr_t *pts_pcr_create(void) memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN); } + /* Set locality indicator in PCR[0] */ + if (tpm_version == TPM_VERSION_2_0) + { + const uint8_t locality = 3; + + DBG2(DBG_PTS, "TPM 2.0 - locality indicator set to %u", + (uint32_t)locality); + this->pcrs[0].ptr[PTS_PCR_LEN - 1] = locality; + } + return &this->public; } diff --git a/src/libimcv/pts/pts_pcr.h b/src/libimcv/pts/pts_pcr.h index 0658f1f98a..ad36705398 100644 --- a/src/libimcv/pts/pts_pcr.h +++ b/src/libimcv/pts/pts_pcr.h @@ -25,6 +25,7 @@ typedef struct pts_pcr_t pts_pcr_t; #include +#include #include /** @@ -114,7 +115,9 @@ struct pts_pcr_t { /** * Creates an pts_pcr_t object + * + * @param tpm_version TPM version */ -pts_pcr_t* pts_pcr_create(void); +pts_pcr_t* pts_pcr_create(tpm_version_t tpm_version); #endif /** PTS_PCR_H_ @}*/ diff --git a/src/libtpmtss/tpm_tss.h b/src/libtpmtss/tpm_tss.h index aab7a4d6c2..bf8cff3ea4 100644 --- a/src/libtpmtss/tpm_tss.h +++ b/src/libtpmtss/tpm_tss.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2018 Tobias Brunner - * Copyright (C) 2016-2018 Andreas Steffen + * Copyright (C) 2016-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -166,6 +166,15 @@ struct tpm_tss_t { bool (*get_data)(tpm_tss_t *this, uint32_t hierarchy, uint32_t handle, chunk_t pin, chunk_t *data); + /** + * Get an event digest from a TPM measurement log + * + * @param fd file descriptor of the measurement log + * @param digest allocated chunk_t containing event digest + * @return TRUE if event digest was successfully extracted + */ + bool (*get_event_digest)(tpm_tss_t *this, int fd, chunk_t *digest); + /** * Destroy a tpm_tss_t. */ diff --git a/src/libtpmtss/tpm_tss_trousers.c b/src/libtpmtss/tpm_tss_trousers.c index 9373733542..c84b04167b 100644 --- a/src/libtpmtss/tpm_tss_trousers.c +++ b/src/libtpmtss/tpm_tss_trousers.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Andreas Steffen + * Copyright (C) 2016-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * Copyright (c) 2008 Hal Finney @@ -35,6 +35,8 @@ #include #include +#include + #define LABEL "TPM 1.2 -" /* size in bytes of a TSS AIK public key blob */ @@ -609,6 +611,14 @@ METHOD(tpm_tss_t, get_data, bool, return FALSE; } +METHOD(tpm_tss_t, get_event_digest, bool, + private_tpm_tss_trousers_t *this, int fd, chunk_t *digest) +{ + *digest = chunk_alloc(HASH_SIZE_SHA1); + + return read(fd, digest->ptr, digest->len) == digest->len; +} + METHOD(tpm_tss_t, destroy, void, private_tpm_tss_trousers_t *this) { @@ -655,6 +665,7 @@ tpm_tss_t *tpm_tss_trousers_create() .sign = _sign, .get_random = _get_random, .get_data = _get_data, + .get_event_digest = _get_event_digest, .destroy = _destroy, }, .load_aik = _load_aik, diff --git a/src/libtpmtss/tpm_tss_tss2_v1.c b/src/libtpmtss/tpm_tss_tss2_v1.c index 31465da82b..03a178e65a 100644 --- a/src/libtpmtss/tpm_tss_tss2_v1.c +++ b/src/libtpmtss/tpm_tss_tss2_v1.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2018 Tobias Brunner - * Copyright (C) 2016-2019 Andreas Steffen + * Copyright (C) 2016-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -22,10 +22,13 @@ #include #include #include +#include #include #include +#include + #ifdef TSS2_TCTI_TABRMD #include #endif /* TSS2_TCTI_TABRMD */ @@ -66,6 +69,11 @@ struct private_tpm_tss_tss2_t { */ size_t supported_algs_count; + /** + * TPM version info + */ + chunk_t version_info; + /** * List of supported algorithms */ @@ -158,16 +166,34 @@ static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM_ALG_ID alg_id) } /** - * Get a list of supported algorithms + * Get the TPM version_info and a list of supported algorithms + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TPM 2.0 Version_Info Tag | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Revision | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Year | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Vendor | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +#define TPM2_VERSION_INFO_TAG 0x0200 +#define TPM2_VERSION_INFO_RESERVED 0x0000 +#define TPM2_VERSION_INFO_SIZE 16 + 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; + bio_writer_t *writer; bool fips_140_2 = FALSE; - uint32_t rval, i, offset, revision = 0, year = 0; + uint32_t rval, i, offset, revision = 0, year = 0, vendor = 0; size_t len = BUF_LEN; char buf[BUF_LEN], manufacturer[5], vendor_string[17]; char *pos = buf; @@ -200,6 +226,7 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this) year = tp.value; break; case TPM_PT_MANUFACTURER: + vendor = tp.value; htoun32(manufacturer, tp.value); break; case TPM_PT_VENDOR_STRING_1: @@ -229,6 +256,16 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this) manufacturer, vendor_string, (float)revision/100, year, fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : "")); + /* construct TPM 2.0 version_info object */ + writer = bio_writer_create( TPM2_VERSION_INFO_SIZE); + writer->write_uint16(writer, TPM2_VERSION_INFO_TAG); + writer->write_uint16(writer, TPM2_VERSION_INFO_RESERVED); + writer->write_uint32(writer, revision); + writer->write_uint32(writer, year); + writer->write_uint32(writer, vendor); + this->version_info = writer->extract_buf(writer); + writer->destroy(writer); + /* get supported algorithms */ this->mutex->lock(this->mutex); rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ALGS, @@ -429,7 +466,7 @@ METHOD(tpm_tss_t, get_version, tpm_version_t, METHOD(tpm_tss_t, get_version_info, chunk_t, private_tpm_tss_tss2_t *this) { - return chunk_empty; + return this->version_info; } /** @@ -1302,11 +1339,18 @@ METHOD(tpm_tss_t, get_data, bool, return TRUE; } +METHOD(tpm_tss_t, get_event_digest, bool, + private_tpm_tss_tss2_t *this, int fd, chunk_t *digest) +{ + return FALSE; +} + METHOD(tpm_tss_t, destroy, void, private_tpm_tss_tss2_t *this) { finalize_context(this); this->mutex->destroy(this->mutex); + free(this->version_info.ptr); free(this); } @@ -1331,6 +1375,7 @@ tpm_tss_t *tpm_tss_tss2_create() .sign = _sign, .get_random = _get_random, .get_data = _get_data, + .get_event_digest = _get_event_digest, .destroy = _destroy, }, .mutex = mutex_create(MUTEX_TYPE_DEFAULT), diff --git a/src/libtpmtss/tpm_tss_tss2_v2.c b/src/libtpmtss/tpm_tss_tss2_v2.c index 8fc4e56485..c4aa6e2041 100644 --- a/src/libtpmtss/tpm_tss_tss2_v2.c +++ b/src/libtpmtss/tpm_tss_tss2_v2.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2018 Tobias Brunner - * Copyright (C) 2018-2019 Andreas Steffen + * Copyright (C) 2018-2020 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,11 @@ struct private_tpm_tss_tss2_t { */ size_t supported_algs_count; + /** + * TPM version info + */ + chunk_t version_info; + /** * List of supported algorithms */ @@ -169,16 +175,34 @@ static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM2_ALG_ID alg_id) } /** - * Get a list of supported algorithms + * Get the TPM version_info and a list of supported algorithms + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TPM 2.0 Version_Info Tag | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Revision | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Year | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Vendor | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +#define TPM2_VERSION_INFO_TAG 0x0200 +#define TPM2_VERSION_INFO_RESERVED 0x0000 +#define TPM2_VERSION_INFO_SIZE 16 + 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; + bio_writer_t *writer; bool fips_140_2 = FALSE; - uint32_t rval, i, offset, revision = 0, year = 0; + uint32_t rval, i, offset, revision = 0, year = 0, vendor = 0; size_t len = BUF_LEN; char buf[BUF_LEN], manufacturer[5], vendor_string[17]; char *pos = buf; @@ -212,6 +236,7 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this) year = tp.value; break; case TPM2_PT_MANUFACTURER: + vendor = tp.value; htoun32(manufacturer, tp.value); break; case TPM2_PT_VENDOR_STRING_1: @@ -241,6 +266,16 @@ static bool get_algs_capability(private_tpm_tss_tss2_t *this) manufacturer, vendor_string, (float)revision/100, year, fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : "")); + /* construct TPM 2.0 version_info object */ + writer = bio_writer_create( TPM2_VERSION_INFO_SIZE); + writer->write_uint16(writer, TPM2_VERSION_INFO_TAG); + writer->write_uint16(writer, TPM2_VERSION_INFO_RESERVED); + writer->write_uint32(writer, revision); + writer->write_uint32(writer, year); + writer->write_uint32(writer, vendor); + this->version_info = writer->extract_buf(writer); + writer->destroy(writer); + /* get supported algorithms */ this->mutex->lock(this->mutex); rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ALGS, @@ -401,7 +436,7 @@ METHOD(tpm_tss_t, get_version, tpm_version_t, METHOD(tpm_tss_t, get_version_info, chunk_t, private_tpm_tss_tss2_t *this) { - return chunk_empty; + return this->version_info; } /** @@ -1204,11 +1239,72 @@ METHOD(tpm_tss_t, get_data, bool, return TRUE; } +METHOD(tpm_tss_t, get_event_digest, bool, + private_tpm_tss_tss2_t *this, int fd, chunk_t *digest) +{ + uint8_t digest_buf[HASH_SIZE_SHA512]; + uint32_t digest_count; + size_t digest_len = 0; + hash_algorithm_t hash_alg; + TPM2_ALG_ID alg_id; + + if (read(fd, &digest_count, 4) != 4) + { + return FALSE; + } + while (digest_count--) + { + if (read(fd, &alg_id, 2) != 2) + { + return FALSE; + } + hash_alg = hash_alg_from_tpm_alg_id(alg_id); + + switch (hash_alg) + { + case HASH_SHA1: + digest_len = HASH_SIZE_SHA1; + break; + case HASH_SHA256: + digest_len = HASH_SIZE_SHA256; + break; + case HASH_SHA384: + digest_len = HASH_SIZE_SHA384; + break; + case HASH_SHA512: + digest_len = HASH_SIZE_SHA512; + break; + default: + DBG2(DBG_PTS, "alg_id: 0x%04x", alg_id); + return FALSE; + } + if (hash_alg == HASH_SHA1) + { + *digest = chunk_alloc(digest_len); + if (read(fd, digest->ptr, digest_len) != digest_len) + { + return FALSE; + } + } + else + { + /* currently skip non-SHA1 digests */ + if (read(fd, digest_buf, digest_len) != digest_len) + { + return FALSE; + } + } + } + + return TRUE; +} + METHOD(tpm_tss_t, destroy, void, private_tpm_tss_tss2_t *this) { finalize_context(this); this->mutex->destroy(this->mutex); + free(this->version_info.ptr); free(this); } @@ -1233,6 +1329,7 @@ tpm_tss_t *tpm_tss_tss2_create() .sign = _sign, .get_random = _get_random, .get_data = _get_data, + .get_event_digest = _get_event_digest, .destroy = _destroy, }, .mutex = mutex_create(MUTEX_TYPE_DEFAULT),