]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
pts: Parse TPM 2.0 BIOS/EFI event log
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 16 Sep 2020 15:15:05 +0000 (17:15 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 7 Oct 2020 14:54:32 +0000 (16:54 +0200)
13 files changed:
src/libimcv/pts/components/ita/ita_comp_ima.c
src/libimcv/pts/components/ita/ita_comp_tboot.c
src/libimcv/pts/components/ita/ita_comp_tgrub.c
src/libimcv/pts/pts.c
src/libimcv/pts/pts.h
src/libimcv/pts/pts_ima_bios_list.c
src/libimcv/pts/pts_ima_bios_list.h
src/libimcv/pts/pts_pcr.c
src/libimcv/pts/pts_pcr.h
src/libtpmtss/tpm_tss.h
src/libtpmtss/tpm_tss_trousers.c
src/libtpmtss/tpm_tss_tss2_v1.c
src/libtpmtss/tpm_tss_tss2_v2.c

index 9ba72d01d0632a600ea6290990e77605908c6a33..a2820b3422450b0a6d88a070a7a0903b7f1d72b3 100644 (file)
@@ -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);
 
index 324c41f127d1085303f6bb88d99655b752b371a0..5452142833013d06a2be439a93f847a9be0f493a 100644 (file)
@@ -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);
 
index a5a1a9b96402ebccf73a7b5ea1ee647975f6588a..6a1ec6cb344d6c29d142c82d843968e1129e6989 100644 (file)
@@ -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)
index 7321d6708b985b4401632e67fd4c8b1ca3018e9d..2df30369d141052564655e82fd7b6aee85033abb 100644 (file)
@@ -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 <bio/bio_writer.h>
 #include <bio/bio_reader.h>
 
-#include <tpm_tss.h>
 #include <tpm_tss_trousers.h>
 
 #include <sys/types.h>
@@ -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;
index f3da659dc8b713b1d240f2c56d0c84676da75b9a..b9fac0a6e5afa6b4d150efe576a346b98e74c778 100644 (file)
@@ -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 <tpm_tss_quote_info.h>
+#include <tpm_tss.h>
 
 #include <library.h>
 #include <collections/linked_list.h>
@@ -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);
 
index 7caa514a583be045fdbb852d94401a74b4ee7ec6..8695ab153cdae42a315b92830dbc5f40b7b7a337 100644 (file)
@@ -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);
index ad162e15a8554c21d9fd5355e9ec8b80377691c5..701a0876aede1a44cf01779cb07e9b1e21ed4450 100644 (file)
@@ -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 <time.h>
 
 #include <library.h>
+#include <tpm_tss.h>
 
 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_ @}*/
index 9f098c08eb0b19ada9810c0295ffb78e13cd9ed0..28593a9b988643deefade21ef30233f2613a058f 100644 (file)
@@ -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;
 }
 
index 0658f1f98a038b40661c46bd8ebb30e878a2a2e7..ad3670539877d3413b1122794491d98d874c5259 100644 (file)
@@ -25,6 +25,7 @@ typedef struct pts_pcr_t pts_pcr_t;
 
 #include <library.h>
 
+#include <tpm_tss.h>
 #include <tpm_tss_quote_info.h>
 
 /**
@@ -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_ @}*/
index aab7a4d6c22b49d1627a39027a0d7e7e7f68bc54..bf8cff3ea4735911ce08db99dbeb3943d7071513 100644 (file)
@@ -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.
         */
index 9373733542ba8e0eb75b670a3ebf2a380cc42c77..c84b04167b0f70f3f06c05ecf1ca6ae918742789 100644 (file)
@@ -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 <trousers/tss.h>
 #include <trousers/trousers.h>
 
+#include <unistd.h>
+
 #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,
index 31465da82bc92bab1d01b93cbb0f7fc9c2d14390..03a178e65a12f2974f8573e600896235a6c17e91 100644 (file)
@@ -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
 #include <asn1/asn1.h>
 #include <asn1/oid.h>
 #include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
 #include <threading/mutex.h>
 
 #include <tpm20.h>
 
+#include <unistd.h>
+
 #ifdef TSS2_TCTI_TABRMD
 #include <tcti/tcti-tabrmd.h>
 #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),
index 8fc4e5648564e01840cf85d84d84c0a32af9f7ff..c4aa6e204194c2598672476937672d00fbe8424d 100644 (file)
@@ -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 <asn1/asn1.h>
 #include <asn1/oid.h>
 #include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
 #include <threading/mutex.h>
 
 #include <tss2/tss2_sys.h>
@@ -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),