Blame Add-ability-to-check-quotes-and-output-PCR-values-fo.patch

Javier Martinez Canillas af88e8
From 3f9c713d3bff4abf417edf0f74e0b049bfd1b31f Mon Sep 17 00:00:00 2001
Javier Martinez Canillas af88e8
From: jetwhiz <Charles.Munson@ll.mit.edu>
Javier Martinez Canillas af88e8
Date: Fri, 3 May 2019 08:03:45 -0400
Javier Martinez Canillas af88e8
Subject: [PATCH] Add ability to check quotes and output PCR values for
Javier Martinez Canillas af88e8
 quotes
Javier Martinez Canillas af88e8
Javier Martinez Canillas af88e8
Add new tpm2_checkquote tool for checking quotes
Javier Martinez Canillas af88e8
  Pull shared functionality from tpm2_pcrlist into pcr library
Javier Martinez Canillas af88e8
  is_pcr_select_bit_set moved into tpm2_util library
Javier Martinez Canillas af88e8
  Add new functionality to openssl, pcr and util libraries
Javier Martinez Canillas af88e8
The tpm2_quote tool can now output PCR hash lists
Javier Martinez Canillas af88e8
Javier Martinez Canillas af88e8
Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
Javier Martinez Canillas af88e8
---
Javier Martinez Canillas af88e8
 CHANGELOG.md                        |   2 +
Javier Martinez Canillas af88e8
 Makefile.am                         |   3 +
Javier Martinez Canillas af88e8
 lib/pcr.c                           | 232 ++++++++++++++++
Javier Martinez Canillas af88e8
 lib/pcr.h                           |  27 ++
Javier Martinez Canillas af88e8
 lib/tpm2_openssl.c                  | 163 +++++++++++
Javier Martinez Canillas af88e8
 lib/tpm2_openssl.h                  |  57 ++++
Javier Martinez Canillas af88e8
 lib/tpm2_util.c                     | 148 ++++++++++
Javier Martinez Canillas af88e8
 lib/tpm2_util.h                     |  33 +++
Javier Martinez Canillas af88e8
 man/tpm2_checkquote.1.md            |  95 +++++++
Javier Martinez Canillas af88e8
 man/tpm2_quote.1.md                 |   9 +-
Javier Martinez Canillas af88e8
 test/system/test_tpm2_checkquote.sh |  86 ++++++
Javier Martinez Canillas af88e8
 test/system/test_tpm2_quote.sh      |  12 +-
Javier Martinez Canillas af88e8
 tools/tpm2_checkquote.c             | 409 ++++++++++++++++++++++++++++
Javier Martinez Canillas af88e8
 tools/tpm2_pcrlist.c                | 205 +-------------
Javier Martinez Canillas af88e8
 tools/tpm2_quote.c                  | 124 ++++++++-
Javier Martinez Canillas af88e8
 15 files changed, 1398 insertions(+), 207 deletions(-)
Javier Martinez Canillas af88e8
 create mode 100644 man/tpm2_checkquote.1.md
Javier Martinez Canillas af88e8
 create mode 100755 test/system/test_tpm2_checkquote.sh
Javier Martinez Canillas af88e8
 create mode 100644 tools/tpm2_checkquote.c
Javier Martinez Canillas af88e8
Javier Martinez Canillas af88e8
diff --git a/CHANGELOG.md b/CHANGELOG.md
Javier Martinez Canillas af88e8
index a8e4f39afde..7e83c6b7e6f 100644
Javier Martinez Canillas af88e8
--- a/CHANGELOG.md
Javier Martinez Canillas af88e8
+++ b/CHANGELOG.md
Javier Martinez Canillas af88e8
@@ -1,5 +1,7 @@
Javier Martinez Canillas af88e8
 ## Changelog
Javier Martinez Canillas af88e8
 ### 3.2.0 - next
Javier Martinez Canillas af88e8
+* tpm2_checkquote: Introduce new tool for checking validity of quotes.
Javier Martinez Canillas af88e8
+* tpm2_quote: Add ability to output PCR values for quotes.
Javier Martinez Canillas af88e8
 * tpm2_makecredential: add support for executing tool off-TPM.
Javier Martinez Canillas af88e8
 * tpm2_pcrreset: introduce new tool for resetting PCRs.
Javier Martinez Canillas af88e8
 * tpm2_quote: Fix AK auth password not being used.
Javier Martinez Canillas af88e8
diff --git a/Makefile.am b/Makefile.am
Javier Martinez Canillas af88e8
index 2195537ce01..854c24a03e3 100644
Javier Martinez Canillas af88e8
--- a/Makefile.am
Javier Martinez Canillas af88e8
+++ b/Makefile.am
Javier Martinez Canillas af88e8
@@ -59,6 +59,7 @@ LDADD = \
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 # keep me sorted
Javier Martinez Canillas af88e8
 bin_PROGRAMS = \
Javier Martinez Canillas af88e8
+    tools/tpm2_checkquote \
Javier Martinez Canillas af88e8
     tools/tpm2_activatecredential \
Javier Martinez Canillas af88e8
     tools/tpm2_certify \
Javier Martinez Canillas af88e8
     tools/tpm2_create \
Javier Martinez Canillas af88e8
@@ -145,6 +146,7 @@ lib_libcommon_a_SOURCES = \
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 TOOL_SRC := tools/tpm2_tool.c tools/tpm2_tool.h
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+tools_tpm2_checkquote_SOURCES = tools/tpm2_checkquote.c $(TOOL_SRC)
Javier Martinez Canillas af88e8
 tools_tpm2_create_SOURCES = tools/tpm2_create.c $(TOOL_SRC)
Javier Martinez Canillas af88e8
 tools_tpm2_createprimary_SOURCES = tools/tpm2_createprimary.c $(TOOL_SRC)
Javier Martinez Canillas af88e8
 tools_tpm2_getcap_SOURCES = tools/tpm2_getcap.c $(TOOL_SRC)
Javier Martinez Canillas af88e8
@@ -259,6 +261,7 @@ if HAVE_MAN_PAGES
Javier Martinez Canillas af88e8
     man1_MANS := \
Javier Martinez Canillas af88e8
     man/man1/tpm2_activatecredential.1 \
Javier Martinez Canillas af88e8
     man/man1/tpm2_certify.1 \
Javier Martinez Canillas af88e8
+    man/man1/tpm2_checkquote.1 \
Javier Martinez Canillas af88e8
     man/man1/tpm2_create.1 \
Javier Martinez Canillas af88e8
     man/man1/tpm2_createpolicy.1 \
Javier Martinez Canillas af88e8
     man/man1/tpm2_createprimary.1 \
Javier Martinez Canillas af88e8
diff --git a/lib/pcr.c b/lib/pcr.c
Javier Martinez Canillas af88e8
index 5552b336f66..9b00dd6e0e3 100644
Javier Martinez Canillas af88e8
--- a/lib/pcr.c
Javier Martinez Canillas af88e8
+++ b/lib/pcr.c
Javier Martinez Canillas af88e8
@@ -33,13 +33,21 @@
Javier Martinez Canillas af88e8
 #include <string.h>
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 #include <tss2/tss2_sys.h>
Javier Martinez Canillas af88e8
+#include <inttypes.h>
Javier Martinez Canillas af88e8
 #include <stdbool.h>
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 #include "pcr.h"
Javier Martinez Canillas af88e8
 #include "log.h"
Javier Martinez Canillas af88e8
+#include "tpm2_tool.h"
Javier Martinez Canillas af88e8
 #include "tpm2_util.h"
Javier Martinez Canillas af88e8
 #include "tpm2_alg_util.h"
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+static inline void set_pcr_select_size(TPMS_PCR_SELECTION *pcr_selection,
Javier Martinez Canillas af88e8
+        UINT8 size) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    pcr_selection->sizeofSelect = size;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 static int pcr_get_id(const char *arg, UINT32 *pcrId)
Javier Martinez Canillas af88e8
 {
Javier Martinez Canillas af88e8
     UINT32 n = 0;
Javier Martinez Canillas af88e8
@@ -96,6 +104,111 @@ static bool pcr_parse_selection(const char *str, size_t len, TPMS_PCR_SELECTION
Javier Martinez Canillas af88e8
     return true;
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+static void shrink_pcr_selection(TPML_PCR_SELECTION *s) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT32 i, j;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    //seek for the first empty item
Javier Martinez Canillas af88e8
+    for (i = 0; i < s->count; i++)
Javier Martinez Canillas af88e8
+        if (!s->pcrSelections[i].hash)
Javier Martinez Canillas af88e8
+            break;
Javier Martinez Canillas af88e8
+    j = i + 1;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    for (; i < s->count; i++) {
Javier Martinez Canillas af88e8
+        if (!s->pcrSelections[i].hash) {
Javier Martinez Canillas af88e8
+            for (; j < s->count; j++)
Javier Martinez Canillas af88e8
+                if (s->pcrSelections[j].hash)
Javier Martinez Canillas af88e8
+                    break;
Javier Martinez Canillas af88e8
+            if (j >= s->count)
Javier Martinez Canillas af88e8
+                break;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            memcpy(&s->pcrSelections[i], &s->pcrSelections[j], sizeof(s->pcrSelections[i]));
Javier Martinez Canillas af88e8
+            s->pcrSelections[j].hash = 0;
Javier Martinez Canillas af88e8
+            j++;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    s->count = i;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+static void pcr_update_pcr_selections(TPML_PCR_SELECTION *s1, TPML_PCR_SELECTION *s2) {
Javier Martinez Canillas af88e8
+    UINT32 i1, i2, j;
Javier Martinez Canillas af88e8
+    for (i2 = 0; i2 < s2->count; i2++) {
Javier Martinez Canillas af88e8
+        for (i1 = 0; i1 < s1->count; i1++) {
Javier Martinez Canillas af88e8
+            if (s2->pcrSelections[i2].hash != s1->pcrSelections[i1].hash)
Javier Martinez Canillas af88e8
+                continue;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            for (j = 0; j < s1->pcrSelections[i1].sizeofSelect; j++)
Javier Martinez Canillas af88e8
+                s1->pcrSelections[i1].pcrSelect[j] &=
Javier Martinez Canillas af88e8
+                        ~s2->pcrSelections[i2].pcrSelect[j];
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+static bool pcr_unset_pcr_sections(TPML_PCR_SELECTION *s) {
Javier Martinez Canillas af88e8
+    UINT32 i, j;
Javier Martinez Canillas af88e8
+    for (i = 0; i < s->count; i++) {
Javier Martinez Canillas af88e8
+        for (j = 0; j < s->pcrSelections[i].sizeofSelect; j++) {
Javier Martinez Canillas af88e8
+            if (s->pcrSelections[i].pcrSelect[j]) {
Javier Martinez Canillas af88e8
+                return false;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+bool pcr_print_pcr_struct(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT32 vi = 0, di = 0, i;
Javier Martinez Canillas af88e8
+    bool result = true;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    tpm2_tool_output("pcrs:\n");
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Loop through all PCR/hash banks 
Javier Martinez Canillas af88e8
+    for (i = 0; i < pcrSelect->count; i++) {
Javier Martinez Canillas af88e8
+        const char *alg_name = tpm2_alg_util_algtostr(pcrSelect->pcrSelections[i].hash);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        tpm2_tool_output("  %s:\n", alg_name);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // Loop through all PCRs in this bank
Javier Martinez Canillas af88e8
+        UINT8 pcr_id;
Javier Martinez Canillas af88e8
+        for (pcr_id = 0; pcr_id < pcrSelect->pcrSelections[i].sizeofSelect * 8; pcr_id++) {
Javier Martinez Canillas af88e8
+            if (!tpm2_util_is_pcr_select_bit_set(&pcrSelect->pcrSelections[i],
Javier Martinez Canillas af88e8
+                    pcr_id)) {
Javier Martinez Canillas af88e8
+                // skip non-selected banks
Javier Martinez Canillas af88e8
+                continue;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+            if (vi >= pcrs->count || di >= pcrs->pcr_values[vi].count) {
Javier Martinez Canillas af88e8
+                LOG_ERR("Something wrong, trying to print but nothing more");
Javier Martinez Canillas af88e8
+                return false;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            // Print out PCR ID
Javier Martinez Canillas af88e8
+            tpm2_tool_output("    %-2d: 0x", pcr_id);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            // Print out current PCR digest value
Javier Martinez Canillas af88e8
+            TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di];
Javier Martinez Canillas af88e8
+            int k;
Javier Martinez Canillas af88e8
+            for (k = 0; k < b->size; k++) {
Javier Martinez Canillas af88e8
+                tpm2_tool_output("%02X", b->buffer[k]);
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+            tpm2_tool_output("\n");
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            if (++di < pcrs->pcr_values[vi].count) {
Javier Martinez Canillas af88e8
+                continue;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            di = 0;
Javier Martinez Canillas af88e8
+            if (++vi < pcrs->count) {
Javier Martinez Canillas af88e8
+                continue;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return result;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 bool pcr_parse_selections(const char *arg, TPML_PCR_SELECTION *pcrSels) {
Javier Martinez Canillas af88e8
     const char *strLeft = arg;
Javier Martinez Canillas af88e8
@@ -194,3 +307,122 @@ TSS2_RC get_max_supported_pcrs(TSS2_SYS_CONTEXT *sapi_context, UINT32 *max_pcrs)
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     return TPM2_RC_SUCCESS;
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+bool pcr_get_banks(TSS2_SYS_CONTEXT *sapi_context, TPMS_CAPABILITY_DATA *capability_data, tpm2_algorithm *algs) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    TPMI_YES_NO more_data;
Javier Martinez Canillas af88e8
+    UINT32 rval;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    rval = TSS2_RETRY_EXP(Tss2_Sys_GetCapability(sapi_context, no_argument, TPM2_CAP_PCRS, no_argument, required_argument,
Javier Martinez Canillas af88e8
+            &more_data, capability_data, 0));
Javier Martinez Canillas af88e8
+    if (rval != TPM2_RC_SUCCESS) {
Javier Martinez Canillas af88e8
+        LOG_ERR(
Javier Martinez Canillas af88e8
+                "GetCapability: Get PCR allocation status Error. TPM Error:0x%x......",
Javier Martinez Canillas af88e8
+                rval);
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    unsigned i;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // If the TPM support more bank algorithm that we currently
Javier Martinez Canillas af88e8
+    // able to manage, throw an error
Javier Martinez Canillas af88e8
+    if (capability_data->data.assignedPCR.count > sizeof(algs->alg)) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Current implementation does not support more than %zu banks, "
Javier Martinez Canillas af88e8
+                "got %" PRIu32 " banks supported by TPM", 
Javier Martinez Canillas af88e8
+                sizeof(algs->alg), 
Javier Martinez Canillas af88e8
+                capability_data->data.assignedPCR.count);
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    for (i = 0; i < capability_data->data.assignedPCR.count; i++) {
Javier Martinez Canillas af88e8
+        algs->alg[i] =
Javier Martinez Canillas af88e8
+                capability_data->data.assignedPCR.pcrSelections[i].hash;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    algs->count = capability_data->data.assignedPCR.count;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+bool pcr_init_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel, TPMI_ALG_HASH alg_id) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT32 i, j;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    pcr_sel->count = 0;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    for (i = 0; i < cap_data->data.assignedPCR.count; i++) {
Javier Martinez Canillas af88e8
+        if (alg_id && (cap_data->data.assignedPCR.pcrSelections[i].hash != alg_id))
Javier Martinez Canillas af88e8
+            continue;
Javier Martinez Canillas af88e8
+        pcr_sel->pcrSelections[pcr_sel->count].hash = cap_data->data.assignedPCR.pcrSelections[i].hash;
Javier Martinez Canillas af88e8
+        set_pcr_select_size(&pcr_sel->pcrSelections[pcr_sel->count], cap_data->data.assignedPCR.pcrSelections[i].sizeofSelect);
Javier Martinez Canillas af88e8
+        for (j = 0; j < pcr_sel->pcrSelections[pcr_sel->count].sizeofSelect; j++)
Javier Martinez Canillas af88e8
+            pcr_sel->pcrSelections[pcr_sel->count].pcrSelect[j] = cap_data->data.assignedPCR.pcrSelections[i].pcrSelect[j];
Javier Martinez Canillas af88e8
+        pcr_sel->count++;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (pcr_sel->count == 0)
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+bool pcr_check_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT32 i, j, k;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    for (i = 0; i < pcr_sel->count; i++) {
Javier Martinez Canillas af88e8
+        for (j = 0; j < cap_data->data.assignedPCR.count; j++) {
Javier Martinez Canillas af88e8
+            if (pcr_sel->pcrSelections[i].hash == cap_data->data.assignedPCR.pcrSelections[j].hash) {
Javier Martinez Canillas af88e8
+                for (k = 0; k < pcr_sel->pcrSelections[i].sizeofSelect; k++)
Javier Martinez Canillas af88e8
+                    pcr_sel->pcrSelections[i].pcrSelect[k] &= cap_data->data.assignedPCR.pcrSelections[j].pcrSelect[k];
Javier Martinez Canillas af88e8
+                break;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        if (j >= cap_data->data.assignedPCR.count) {
Javier Martinez Canillas af88e8
+            const char *alg_name = tpm2_alg_util_algtostr(pcr_sel->pcrSelections[i].hash);
Javier Martinez Canillas af88e8
+            LOG_WARN("Ignore unsupported bank/algorithm: %s(0x%04x)", alg_name, pcr_sel->pcrSelections[i].hash);
Javier Martinez Canillas af88e8
+            pcr_sel->pcrSelections[i].hash = 0; //mark it as to be removed
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    shrink_pcr_selection(pcr_sel);
Javier Martinez Canillas af88e8
+    if (pcr_sel->count == 0)
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+bool pcr_read_pcr_values(TSS2_SYS_CONTEXT *sapi_context, TPML_PCR_SELECTION *pcrSelections, tpm2_pcrs *pcrs) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    TPML_PCR_SELECTION pcr_selection_tmp;
Javier Martinez Canillas af88e8
+    TPML_PCR_SELECTION pcr_selection_out;
Javier Martinez Canillas af88e8
+    UINT32 pcr_update_counter;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    //1. prepare pcrSelectionIn with g_pcrSelections
Javier Martinez Canillas af88e8
+    memcpy(&pcr_selection_tmp, pcrSelections, sizeof(pcr_selection_tmp));
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    //2. call pcr_read
Javier Martinez Canillas af88e8
+    pcrs->count = 0;
Javier Martinez Canillas af88e8
+    do {
Javier Martinez Canillas af88e8
+        UINT32 rval = TSS2_RETRY_EXP(Tss2_Sys_PCR_Read(sapi_context, no_argument, &pcr_selection_tmp,
Javier Martinez Canillas af88e8
+                &pcr_update_counter, &pcr_selection_out,
Javier Martinez Canillas af88e8
+                &pcrs->pcr_values[pcrs->count], 0));
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        if (rval != TPM2_RC_SUCCESS) {
Javier Martinez Canillas af88e8
+            LOG_ERR("read pcr failed. tpm error 0x%0x", rval);
Javier Martinez Canillas af88e8
+            return -1;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        //3. unmask pcrSelectionOut bits from pcrSelectionIn
Javier Martinez Canillas af88e8
+        pcr_update_pcr_selections(&pcr_selection_tmp, &pcr_selection_out);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        //4. goto step 2 if pcrSelctionIn still has bits set
Javier Martinez Canillas af88e8
+    } while (++pcrs->count < sizeof(pcrs->pcr_values) && !pcr_unset_pcr_sections(&pcr_selection_tmp));
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (pcrs->count >= sizeof(pcrs->pcr_values) && !pcr_unset_pcr_sections(&pcr_selection_tmp)) {
Javier Martinez Canillas af88e8
+        LOG_ERR("too much pcrs to get! try to split into multiple calls...");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
diff --git a/lib/pcr.h b/lib/pcr.h
Javier Martinez Canillas af88e8
index ad6946b3c04..82d5dd696d4 100644
Javier Martinez Canillas af88e8
--- a/lib/pcr.h
Javier Martinez Canillas af88e8
+++ b/lib/pcr.h
Javier Martinez Canillas af88e8
@@ -35,8 +35,35 @@
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 #include <tss2/tss2_sys.h>
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+typedef struct tpm2_algorithm tpm2_algorithm;
Javier Martinez Canillas af88e8
+struct tpm2_algorithm {
Javier Martinez Canillas af88e8
+    int count;
Javier Martinez Canillas af88e8
+    TPMI_ALG_HASH alg[TPM2_NUM_PCR_BANKS];
Javier Martinez Canillas af88e8
+};
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+typedef struct tpm2_pcrs tpm2_pcrs;
Javier Martinez Canillas af88e8
+struct tpm2_pcrs {
Javier Martinez Canillas af88e8
+    size_t count;
Javier Martinez Canillas af88e8
+    TPML_DIGEST pcr_values[TPM2_MAX_PCRS];
Javier Martinez Canillas af88e8
+};
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+ * Echo out all PCR banks according to g_pcrSelection & g_pcrs->.
Javier Martinez Canillas af88e8
+ * @param pcrSelect
Javier Martinez Canillas af88e8
+ *  Description of which PCR registers are selected.
Javier Martinez Canillas af88e8
+ * @param pcrs
Javier Martinez Canillas af88e8
+ *  Struct containing PCR digests.
Javier Martinez Canillas af88e8
+ * @return
Javier Martinez Canillas af88e8
+ *  True on success, false otherwise.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+bool pcr_print_pcr_struct(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 bool pcr_parse_selections(const char *arg, TPML_PCR_SELECTION *pcrSels);
Javier Martinez Canillas af88e8
 bool pcr_parse_list(const char *str, size_t len, TPMS_PCR_SELECTION *pcrSel);
Javier Martinez Canillas af88e8
 TSS2_RC get_max_supported_pcrs(TSS2_SYS_CONTEXT *sapi_context, UINT32 *max_pcrs);
Javier Martinez Canillas af88e8
+bool pcr_get_banks(TSS2_SYS_CONTEXT *sapi_context, TPMS_CAPABILITY_DATA *capability_data, tpm2_algorithm *algs);
Javier Martinez Canillas af88e8
+bool pcr_init_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel, TPMI_ALG_HASH alg_id);
Javier Martinez Canillas af88e8
+bool pcr_check_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel);
Javier Martinez Canillas af88e8
+bool pcr_read_pcr_values(TSS2_SYS_CONTEXT *sapi_context, TPML_PCR_SELECTION *pcrSelections, tpm2_pcrs *pcrs);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 #endif /* SRC_PCR_H_ */
Javier Martinez Canillas af88e8
diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c
Javier Martinez Canillas af88e8
index 0bfc95bd1ef..8d7314cba8e 100644
Javier Martinez Canillas af88e8
--- a/lib/tpm2_openssl.c
Javier Martinez Canillas af88e8
+++ b/lib/tpm2_openssl.c
Javier Martinez Canillas af88e8
@@ -44,9 +44,26 @@
Javier Martinez Canillas af88e8
 #include "files.h"
Javier Martinez Canillas af88e8
 #include "log.h"
Javier Martinez Canillas af88e8
 #include "tpm2_alg_util.h"
Javier Martinez Canillas af88e8
+#include "tpm_kdfa.h"
Javier Martinez Canillas af88e8
 #include "tpm2_openssl.h"
Javier Martinez Canillas af88e8
 #include "tpm2_util.h"
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    switch (algorithm) {
Javier Martinez Canillas af88e8
+    case TPM2_ALG_SHA1:
Javier Martinez Canillas af88e8
+        return NID_sha1;
Javier Martinez Canillas af88e8
+    case TPM2_ALG_SHA256:
Javier Martinez Canillas af88e8
+        return NID_sha256;
Javier Martinez Canillas af88e8
+    case TPM2_ALG_SHA384:
Javier Martinez Canillas af88e8
+        return NID_sha384;
Javier Martinez Canillas af88e8
+    case TPM2_ALG_SHA512:
Javier Martinez Canillas af88e8
+        return NID_sha512;
Javier Martinez Canillas af88e8
+    default:
Javier Martinez Canillas af88e8
+        return NID_sha256;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    /* no return, not possible */
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
@@ -122,6 +139,127 @@ void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx) {
Javier Martinez Canillas af88e8
 #endif
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg,
Javier Martinez Canillas af88e8
+        BYTE *buffer, UINT16 length, TPM2B_DIGEST *digest) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    bool result = false;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg);
Javier Martinez Canillas af88e8
+    if (!md) {
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
Javier Martinez Canillas af88e8
+    if (!mdctx) {
Javier Martinez Canillas af88e8
+        LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    int rc = EVP_DigestInit_ex(mdctx, md, NULL);
Javier Martinez Canillas af88e8
+    if (!rc) {
Javier Martinez Canillas af88e8
+        LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    rc = EVP_DigestUpdate(mdctx, buffer, length);
Javier Martinez Canillas af88e8
+    if (!rc) {
Javier Martinez Canillas af88e8
+        LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    unsigned size = EVP_MD_size(md);
Javier Martinez Canillas af88e8
+    rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size);
Javier Martinez Canillas af88e8
+    if (!rc) {
Javier Martinez Canillas af88e8
+        LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    digest->size = size;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    result = true;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+out:
Javier Martinez Canillas af88e8
+    EVP_MD_CTX_destroy(mdctx);
Javier Martinez Canillas af88e8
+    return result;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+// show all PCR banks according to g_pcrSelection & g_pcrs->
Javier Martinez Canillas af88e8
+bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg, 
Javier Martinez Canillas af88e8
+                TPML_PCR_SELECTION *pcrSelect, 
Javier Martinez Canillas af88e8
+                tpm2_pcrs *pcrs, TPM2B_DIGEST *digest) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT32 vi = 0, di = 0, i;
Javier Martinez Canillas af88e8
+    bool result = false;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hashAlg);
Javier Martinez Canillas af88e8
+    if (!md) {
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
Javier Martinez Canillas af88e8
+    if (!mdctx) {
Javier Martinez Canillas af88e8
+        LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    int rc = EVP_DigestInit_ex(mdctx, md, NULL);
Javier Martinez Canillas af88e8
+    if (!rc) {
Javier Martinez Canillas af88e8
+        LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Loop through all PCR/hash banks 
Javier Martinez Canillas af88e8
+    for (i = 0; i < pcrSelect->count; i++) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // Loop through all PCRs in this bank
Javier Martinez Canillas af88e8
+        UINT8 pcr_id;
Javier Martinez Canillas af88e8
+        for (pcr_id = 0; pcr_id < pcrSelect->pcrSelections[i].sizeofSelect * 8; pcr_id++) {
Javier Martinez Canillas af88e8
+            if (!tpm2_util_is_pcr_select_bit_set(&pcrSelect->pcrSelections[i],
Javier Martinez Canillas af88e8
+                    pcr_id)) {
Javier Martinez Canillas af88e8
+                // skip non-selected banks
Javier Martinez Canillas af88e8
+                continue;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+            if (vi >= pcrs->count || di >= pcrs->pcr_values[vi].count) {
Javier Martinez Canillas af88e8
+                LOG_ERR("Something wrong, trying to print but nothing more");
Javier Martinez Canillas af88e8
+                goto out;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            // Update running digest (to compare with quote)
Javier Martinez Canillas af88e8
+            TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di];
Javier Martinez Canillas af88e8
+            rc = EVP_DigestUpdate(mdctx, b->buffer, b->size);
Javier Martinez Canillas af88e8
+            if (!rc) {
Javier Martinez Canillas af88e8
+                LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+                goto out;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            if (++di < pcrs->pcr_values[vi].count) {
Javier Martinez Canillas af88e8
+                continue;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+            di = 0;
Javier Martinez Canillas af88e8
+            if (++vi < pcrs->count) {
Javier Martinez Canillas af88e8
+                continue;
Javier Martinez Canillas af88e8
+            }
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Finalize running digest
Javier Martinez Canillas af88e8
+    unsigned size = EVP_MD_size(md);
Javier Martinez Canillas af88e8
+    rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size);
Javier Martinez Canillas af88e8
+    if (!rc) {
Javier Martinez Canillas af88e8
+        LOG_ERR("%s", get_openssl_err());
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    digest->size = size;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    result = true;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+out:
Javier Martinez Canillas af88e8
+    EVP_MD_CTX_destroy(mdctx);
Javier Martinez Canillas af88e8
+    return result;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     switch(halg) {
Javier Martinez Canillas af88e8
@@ -160,3 +298,28 @@ digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) {
Javier Martinez Canillas af88e8
  */
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 typedef bool (*pfn_ossl_pw_handler)(const char *passin, char **pass);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+RSA *tpm2_openssl_get_public_RSA_from_pem(FILE *f, const char *path) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    /*
Javier Martinez Canillas af88e8
+     * Public PEM files appear in two formats:
Javier Martinez Canillas af88e8
+     * 1. PEM format, read with PEM_read_RSA_PUBKEY
Javier Martinez Canillas af88e8
+     * 2. PKCS#1 format, read with PEM_read_RSAPublicKey
Javier Martinez Canillas af88e8
+     *
Javier Martinez Canillas af88e8
+     * See:
Javier Martinez Canillas af88e8
+     *  - https://stackoverflow.com/questions/7818117/why-i-cant-read-openssl-generated-rsa-pub-key-with-pem-read-rsapublickey
Javier Martinez Canillas af88e8
+     */
Javier Martinez Canillas af88e8
+    RSA *pub = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL);
Javier Martinez Canillas af88e8
+    if (!pub) {
Javier Martinez Canillas af88e8
+        pub = PEM_read_RSAPublicKey(f, NULL, NULL, NULL);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (!pub) {
Javier Martinez Canillas af88e8
+         ERR_print_errors_fp (stderr);
Javier Martinez Canillas af88e8
+         LOG_ERR("Reading public PEM file \"%s\" failed", path);
Javier Martinez Canillas af88e8
+         return NULL;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return pub;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h
Javier Martinez Canillas af88e8
index d749cb350ac..d3f4a0d7a32 100644
Javier Martinez Canillas af88e8
--- a/lib/tpm2_openssl.h
Javier Martinez Canillas af88e8
+++ b/lib/tpm2_openssl.h
Javier Martinez Canillas af88e8
@@ -34,6 +34,8 @@
Javier Martinez Canillas af88e8
 #include <openssl/hmac.h>
Javier Martinez Canillas af88e8
 #include <openssl/rsa.h>
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+#include "pcr.h"
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 #if (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) /* OpenSSL 1.1.0 */
Javier Martinez Canillas af88e8
 #define LIB_TPM2_OPENSSL_OPENSSL_PRE11
Javier Martinez Canillas af88e8
 #endif
Javier Martinez Canillas af88e8
@@ -60,6 +62,16 @@ int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
Javier Martinez Canillas af88e8
  */
Javier Martinez Canillas af88e8
 typedef unsigned char *(*digester)(const unsigned char *d, size_t n, unsigned char *md);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+ * Get an openssl hash algorithm ID from a tpm hashing algorithm ID.
Javier Martinez Canillas af88e8
+ * @param algorithm
Javier Martinez Canillas af88e8
+ *  The tpm algorithm to get the corresponding openssl version of.
Javier Martinez Canillas af88e8
+ * @return
Javier Martinez Canillas af88e8
+ *  The openssl hash algorithm id.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 /**
Javier Martinez Canillas af88e8
  * Get an openssl message digest from a tpm hashing algorithm.
Javier Martinez Canillas af88e8
  * @param algorithm
Javier Martinez Canillas af88e8
@@ -86,6 +98,39 @@ EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void);
Javier Martinez Canillas af88e8
  */
Javier Martinez Canillas af88e8
 void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+ * Hash a byte buffer.
Javier Martinez Canillas af88e8
+ * @param halg
Javier Martinez Canillas af88e8
+ *  The hashing algorithm to use.
Javier Martinez Canillas af88e8
+ * @param buffer
Javier Martinez Canillas af88e8
+ *  The byte buffer to be hashed.
Javier Martinez Canillas af88e8
+ * @param length
Javier Martinez Canillas af88e8
+ *  The length of the byte buffer to hash.
Javier Martinez Canillas af88e8
+^ * @param digest
Javier Martinez Canillas af88e8
+^ *  The result of hashing digests with halg.
Javier Martinez Canillas af88e8
+ * @return
Javier Martinez Canillas af88e8
+ *  true on success, false on error.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg,
Javier Martinez Canillas af88e8
+        BYTE *buffer, UINT16 length, TPM2B_DIGEST *digest);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+ * Hash a list of PCR digests, supporting multiple banks.
Javier Martinez Canillas af88e8
+ * @param halg
Javier Martinez Canillas af88e8
+ *  The hashing algorithm to use.
Javier Martinez Canillas af88e8
+ * @param pcrSelect
Javier Martinez Canillas af88e8
+ *  The list that specifies which PCRs are selected.
Javier Martinez Canillas af88e8
+ * @param pcrs
Javier Martinez Canillas af88e8
+ *  The list of PCR banks, each containing a list of PCR digests to hash.
Javier Martinez Canillas af88e8
+^ * @param digest
Javier Martinez Canillas af88e8
+^ *  The result of hashing digests with halg.
Javier Martinez Canillas af88e8
+ * @return
Javier Martinez Canillas af88e8
+ *  true on success, false on error.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg, 
Javier Martinez Canillas af88e8
+        TPML_PCR_SELECTION *pcrSelect, 
Javier Martinez Canillas af88e8
+        tpm2_pcrs *pcrs, TPM2B_DIGEST *digest);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 /**
Javier Martinez Canillas af88e8
  * Returns a function pointer capable of performing the
Javier Martinez Canillas af88e8
  * given digest from a TPMI_HASH_ALG.
Javier Martinez Canillas af88e8
@@ -105,4 +150,16 @@ enum tpm2_openssl_load_rc {
Javier Martinez Canillas af88e8
 };
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+ * Retrieves a public portion of an RSA key from a PEM file.
Javier Martinez Canillas af88e8
+ *
Javier Martinez Canillas af88e8
+ * @param f
Javier Martinez Canillas af88e8
+ *  The FILE object that is open for reading the path.
Javier Martinez Canillas af88e8
+ * @param path
Javier Martinez Canillas af88e8
+ *  The path to load from.
Javier Martinez Canillas af88e8
+ * @return
Javier Martinez Canillas af88e8
+ *  The public structure.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+RSA* tpm2_openssl_get_public_RSA_from_pem(FILE *f, const char *path);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 #endif /* LIB_TPM2_OPENSSL_H_ */
Javier Martinez Canillas af88e8
diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
Javier Martinez Canillas af88e8
index 57d6c762a70..edfda4a8b0b 100644
Javier Martinez Canillas af88e8
--- a/lib/tpm2_util.c
Javier Martinez Canillas af88e8
+++ b/lib/tpm2_util.c
Javier Martinez Canillas af88e8
@@ -41,6 +41,154 @@
Javier Martinez Canillas af88e8
 #include "tpm2_tool.h"
Javier Martinez Canillas af88e8
 #include "tpm2_util.h"
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+bool tpm2_util_get_digest_from_quote(TPM2B_ATTEST *quoted, TPM2B_DIGEST *digest, TPM2B_DATA *extraData) {
Javier Martinez Canillas af88e8
+    TPM2_GENERATED magic;
Javier Martinez Canillas af88e8
+    TPMI_ST_ATTEST type;
Javier Martinez Canillas af88e8
+    UINT16 nameSize = 0;
Javier Martinez Canillas af88e8
+    UINT32 i = 0;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Ensure required headers are at least there
Javier Martinez Canillas af88e8
+    if (quoted->size < 6) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPM2B_ATTEST headers");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    memcpy(&magic, &quoted->attestationData[i], 4);i += 4;
Javier Martinez Canillas af88e8
+    memcpy(&type, &quoted->attestationData[i], 2);i += 2;
Javier Martinez Canillas af88e8
+    if (!tpm2_util_is_big_endian()) {
Javier Martinez Canillas af88e8
+        magic = tpm2_util_endian_swap_32(magic);
Javier Martinez Canillas af88e8
+        type = tpm2_util_endian_swap_16(type);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (magic != TPM2_GENERATED_VALUE) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPM2_GENERATED magic value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (type != TPM2_ST_ATTEST_QUOTE) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPMI_ST_ATTEST quote value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Qualified signer name (skip)
Javier Martinez Canillas af88e8
+    if (i+2 >= quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPM2B_NAME value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    memcpy(&nameSize, &quoted->attestationData[i], 2);i += 2;
Javier Martinez Canillas af88e8
+    if (!tpm2_util_is_big_endian()) {
Javier Martinez Canillas af88e8
+        nameSize = tpm2_util_endian_swap_16(nameSize);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    i += nameSize;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Extra data (skip)
Javier Martinez Canillas af88e8
+    if (i+2 >= quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPM2B_DATA value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    memcpy(&extraData->size, &quoted->attestationData[i], 2);i += 2;
Javier Martinez Canillas af88e8
+    if (!tpm2_util_is_big_endian()) {
Javier Martinez Canillas af88e8
+        extraData->size = tpm2_util_endian_swap_16(extraData->size);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    if (extraData->size+i > quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed extraData TPM2B_DATA value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    memcpy(&extraData->buffer, &quoted->attestationData[i], extraData->size);i += extraData->size;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Clock info (skip)
Javier Martinez Canillas af88e8
+    i += 17;
Javier Martinez Canillas af88e8
+    if (i >= quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPMS_CLOCK_INFO value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Firmware info (skip)
Javier Martinez Canillas af88e8
+    i += 8;
Javier Martinez Canillas af88e8
+    if (i >= quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed firmware version value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // PCR select info
Javier Martinez Canillas af88e8
+    UINT8 sos;
Javier Martinez Canillas af88e8
+    TPMI_ALG_HASH hashAlg;
Javier Martinez Canillas af88e8
+    UINT32 pcrSelCount = 0, j = 0;
Javier Martinez Canillas af88e8
+    if (i+4 >= quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPML_PCR_SELECTION value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    memcpy(&pcrSelCount, &quoted->attestationData[i], 4);i += 4;
Javier Martinez Canillas af88e8
+    if (!tpm2_util_is_big_endian()) {
Javier Martinez Canillas af88e8
+        pcrSelCount = tpm2_util_endian_swap_32(pcrSelCount);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    for (j = 0; j < pcrSelCount; j++) {
Javier Martinez Canillas af88e8
+        // Hash 
Javier Martinez Canillas af88e8
+        if (i+2 >= quoted->size) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Malformed TPMS_PCR_SELECTION value");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+        memcpy(&hashAlg, &quoted->attestationData[i], 2);i += 2;
Javier Martinez Canillas af88e8
+        if (!tpm2_util_is_big_endian()) {
Javier Martinez Canillas af88e8
+            hashAlg = tpm2_util_endian_swap_16(hashAlg);
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // SizeOfSelected
Javier Martinez Canillas af88e8
+        if (i+1 >= quoted->size) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Malformed TPMS_PCR_SELECTION value");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+        memcpy(&sos, &quoted->attestationData[i], 1);i += 1;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // PCR Select (skip)
Javier Martinez Canillas af88e8
+        i += sos;
Javier Martinez Canillas af88e8
+        if (i >= quoted->size) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Malformed TPMS_PCR_SELECTION value");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Digest
Javier Martinez Canillas af88e8
+    if (i+2 >= quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPM2B_DIGEST value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    memcpy(&digest->size, &quoted->attestationData[i], 2);i += 2;
Javier Martinez Canillas af88e8
+    if (!tpm2_util_is_big_endian()) {
Javier Martinez Canillas af88e8
+        digest->size = tpm2_util_endian_swap_16(digest->size);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (digest->size+i > quoted->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Malformed TPM2B_DIGEST value");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    memcpy(&digest->buffer, &quoted->attestationData[i], digest->size);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+// verify that the quote digest equals the digest we calculated
Javier Martinez Canillas af88e8
+bool tpm2_util_verify_digests(TPM2B_DIGEST *quoteDigest, TPM2B_DIGEST *pcrDigest) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Sanity check -- they should at least be same size!
Javier Martinez Canillas af88e8
+    if (quoteDigest->size != pcrDigest->size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Compare running digest with quote's digest
Javier Martinez Canillas af88e8
+    int k;
Javier Martinez Canillas af88e8
+    for (k = 0; k < quoteDigest->size; k++) {
Javier Martinez Canillas af88e8
+        if (quoteDigest->buffer[k] != pcrDigest->buffer[k]) {
Javier Martinez Canillas af88e8
+            LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     if (!result || !append) {
Javier Martinez Canillas af88e8
diff --git a/lib/tpm2_util.h b/lib/tpm2_util.h
Javier Martinez Canillas af88e8
index e803dc1c30e..8b77c9e5374 100644
Javier Martinez Canillas af88e8
--- a/lib/tpm2_util.h
Javier Martinez Canillas af88e8
+++ b/lib/tpm2_util.h
Javier Martinez Canillas af88e8
@@ -111,6 +111,30 @@ struct TPM2B {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 int tpm2_util_hex_to_byte_structure(const char *inStr, UINT16 *byteLenth, BYTE *byteBuffer);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+ * Pulls the TPM2B_DIGEST out of a TPM2B_ATTEST quote.
Javier Martinez Canillas af88e8
+ * @param quoted
Javier Martinez Canillas af88e8
+ *  The attestation quote structure.
Javier Martinez Canillas af88e8
+^ * @param digest
Javier Martinez Canillas af88e8
+^ *  The digest from the quote.
Javier Martinez Canillas af88e8
+^ * @param extraData
Javier Martinez Canillas af88e8
+^ *  The extraData from the quote.
Javier Martinez Canillas af88e8
+ * @return
Javier Martinez Canillas af88e8
+ *  True on success, false otherwise.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+bool tpm2_util_get_digest_from_quote(TPM2B_ATTEST *quoted, TPM2B_DIGEST *digest, TPM2B_DATA *extraData);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+ * Compares two digests to ensure they are equal (for validation).
Javier Martinez Canillas af88e8
+ * @param quoteDigest
Javier Martinez Canillas af88e8
+ *  The digest from the quote.
Javier Martinez Canillas af88e8
+ * @param pcrDigest
Javier Martinez Canillas af88e8
+ *  The digest calculated off-TMP from the PCRs.
Javier Martinez Canillas af88e8
+ * @return
Javier Martinez Canillas af88e8
+ *  True on success, false otherwise.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+bool tpm2_util_verify_digests(TPM2B_DIGEST *quoteDigest, TPM2B_DIGEST *pcrDigest);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 /**
Javier Martinez Canillas af88e8
  * Appends a TPM2B_DIGEST buffer to a TPM2B_MAX buffer.
Javier Martinez Canillas af88e8
  * @param result
Javier Martinez Canillas af88e8
@@ -170,6 +194,15 @@ static inline void tpm2_util_print_tpm2b(TPM2B *buffer) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 void tpm2_util_print_tpm2b(TPM2B *buffer);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+/**
Javier Martinez Canillas af88e8
+ * Determines if given PCR value is selected in TPMS_PCR_SELECTION structure.
Javier Martinez Canillas af88e8
+ * @param pcr_selection the TPMS_PCR_SELECTION structure to check pcr against.
Javier Martinez Canillas af88e8
+ * @param pcr the PCR ID to check selection status of.
Javier Martinez Canillas af88e8
+ */
Javier Martinez Canillas af88e8
+static inline bool tpm2_util_is_pcr_select_bit_set(TPMS_PCR_SELECTION *pcr_selection, UINT32 pcr) {
Javier Martinez Canillas af88e8
+    return (pcr_selection->pcrSelect[((pcr) / 8)] & (1 << ((pcr) % 8)));
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 /**
Javier Martinez Canillas af88e8
  * Copies a tpm2b from dest to src and clears dest if src is NULL.
Javier Martinez Canillas af88e8
  * If src is NULL, it is a NOP.
Javier Martinez Canillas af88e8
diff --git a/man/tpm2_checkquote.1.md b/man/tpm2_checkquote.1.md
Javier Martinez Canillas af88e8
new file mode 100644
Javier Martinez Canillas af88e8
index 00000000000..00bb4bee9a7
Javier Martinez Canillas af88e8
--- /dev/null
Javier Martinez Canillas af88e8
+++ b/man/tpm2_checkquote.1.md
Javier Martinez Canillas af88e8
@@ -0,0 +1,95 @@
Javier Martinez Canillas af88e8
+% tpm2_checkquote(1) tpm2-tools | General Commands Manual
Javier Martinez Canillas af88e8
+%
Javier Martinez Canillas af88e8
+% JANUARY 2019
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# NAME
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+**tpm2_checkquote**(1) - Validates a quote provided by a TPM.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# SYNOPSIS
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+**tpm2_checkquote** [*OPTIONS*]
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# DESCRIPTION
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+**tpm2_checkquote**(1) - Uses the public portion of the provided key to validate a quote 
Javier Martinez Canillas af88e8
+generated by a TPM. This will validate the signature against the quote message and, if 
Javier Martinez Canillas af88e8
+provided, verify that the qualifying data and PCR values match those in the quote.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# OPTIONS
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+  * **-c**, **--key-context**=_KEY\_CONTEXT\_OBJECT_:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    Context object for the key context used for the operation. Either a file
Javier Martinez Canillas af88e8
+    or a handle number. See section "Context Object Format".
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+  * **-G**, **--halg**=_HASH\_ALGORITHM_:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    The hash algorithm used to digest the message.
Javier Martinez Canillas af88e8
+    Algorithms should follow the "formatting standards", see section
Javier Martinez Canillas af88e8
+    "Algorithm Specifiers".
Javier Martinez Canillas af88e8
+    Also, see section "Supported Hash Algorithms" for a list of supported hash
Javier Martinez Canillas af88e8
+    algorithms.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+  * **-m**, **--message**=_MSG\_FILE_:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    The quote message that makes up the data that is signed by the TPM.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+  * **-s**, **--sig**=_SIG\_FILE_:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    The input signature file of the signature to be validated.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+  * **-f**, **--format**:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    Set the input signature file to a specified format. The default is the TPM2.0 **TPMT_SIGNATURE**
Javier Martinez Canillas af88e8
+    data format, however different schemes can be selected if the data came from an external
Javier Martinez Canillas af88e8
+    source like OpenSSL. The tool currently only supports rsassa.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    Algorithms should follow the "formatting standards", see section
Javier Martinez Canillas af88e8
+    "Algorithm Specifiers".
Javier Martinez Canillas af88e8
+    Also, see section "Supported Signing Schemes" for a list of supported hash
Javier Martinez Canillas af88e8
+    algorithms.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+  * **-p**, **--pcrs**:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    PCR output file, optional, records the list of PCR values that were included 
Javier Martinez Canillas af88e8
+    in the quote. 
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+  * **-q**, **--qualify-data**:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    Data given as a hex string that was used to qualify the quote. This is typically
Javier Martinez Canillas af88e8
+    used to add a nonce against replay attacks.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[common options](common/options.md)
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[common tcti options](common/tcti.md)
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[context object format](common/ctxobj.md)
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[authorization formatting](common/password.md)
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[supported hash algorithms](common/hash.md)
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[supported signing schemes](common/signschemes.md)
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[algorithm specifiers](common/alg.md)
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# EXAMPLES
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+## Generate a quote with a TPM, then verify it
Javier Martinez Canillas af88e8
+```
Javier Martinez Canillas af88e8
+tpm2_createprimary -H e -g sha256 -G rsa -C primary.ctx
Javier Martinez Canillas af88e8
+tpm2_create -g sha256 -G rsa -u ak.pub -r ak.priv -c primary.ctx
Javier Martinez Canillas af88e8
+tpm2_load -c primary.ctx  -u ak.pub -r ak.priv -n ak.name -C ak.ctx
Javier Martinez Canillas af88e8
+tpm2_readpublic -c ak.ctx -o akpub.pem -f pem
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+tpm2_quote -c ak.ctx -L sha256:15,16,22 -q abc123 -m quote.out -s sig.out -p pcrs.out -G sha256
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+tpm2_checkquote -c akpub.pem -m quote.out -s sig.out -p pcrs.out -G sha256 -q abc123
Javier Martinez Canillas af88e8
+```
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# RETURNS
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+0 on success or 1 on failure.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+[footer](common/footer.md)
Javier Martinez Canillas af88e8
diff --git a/man/tpm2_quote.1.md b/man/tpm2_quote.1.md
Javier Martinez Canillas af88e8
index 88c37e040c1..491848201d9 100644
Javier Martinez Canillas af88e8
--- a/man/tpm2_quote.1.md
Javier Martinez Canillas af88e8
+++ b/man/tpm2_quote.1.md
Javier Martinez Canillas af88e8
@@ -53,6 +53,13 @@
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     Format selection for the signature output file. See section "Signature Format Specifiers".
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+  * **-p**, **--pcrs**:
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    PCR output file, optional, records the list of PCR values as defined
Javier Martinez Canillas af88e8
+    by **-l** or **-L**.  Note that only the digest of these values is stored in the
Javier Martinez Canillas af88e8
+    signed quote message -- these values themselves are not signed or
Javier Martinez Canillas af88e8
+    stored in the message.
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
   * **-q**, **--qualify-data**:
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     Data given as a Hex string to qualify the  quote, optional. This is typically
Javier Martinez Canillas af88e8
@@ -63,7 +70,7 @@
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
   * **-G**, **--sig-hash-algorithm**:
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-    Hash algorithm for signature.
Javier Martinez Canillas af88e8
+    Hash algorithm for signature. Required if **-p** is given.
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 [common options](common/options.md)
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
diff --git a/test/system/test_tpm2_checkquote.sh b/test/system/test_tpm2_checkquote.sh
Javier Martinez Canillas af88e8
new file mode 100755
Javier Martinez Canillas af88e8
index 00000000000..670e3a737d1
Javier Martinez Canillas af88e8
--- /dev/null
Javier Martinez Canillas af88e8
+++ b/test/system/test_tpm2_checkquote.sh
Javier Martinez Canillas af88e8
@@ -0,0 +1,86 @@
Javier Martinez Canillas af88e8
+#!/bin/bash
Javier Martinez Canillas af88e8
+#;**********************************************************************;
Javier Martinez Canillas af88e8
+#
Javier Martinez Canillas af88e8
+# Copyright (c) 2019 Massachusetts Institute of Technology.
Javier Martinez Canillas af88e8
+# All rights reserved.
Javier Martinez Canillas af88e8
+#
Javier Martinez Canillas af88e8
+# Redistribution and use in source and binary forms, with or without
Javier Martinez Canillas af88e8
+# modification, are permitted provided that the following conditions are met:
Javier Martinez Canillas af88e8
+#
Javier Martinez Canillas af88e8
+# 1. Redistributions of source code must retain the above copyright notice,
Javier Martinez Canillas af88e8
+# this list of conditions and the following disclaimer.
Javier Martinez Canillas af88e8
+#
Javier Martinez Canillas af88e8
+# 2. Redistributions in binary form must reproduce the above copyright notice,
Javier Martinez Canillas af88e8
+# this list of conditions and the following disclaimer in the documentation
Javier Martinez Canillas af88e8
+# and/or other materials provided with the distribution.
Javier Martinez Canillas af88e8
+#
Javier Martinez Canillas af88e8
+# 3. Neither the name of Intel Corporation nor the names of its contributors
Javier Martinez Canillas af88e8
+# may be used to endorse or promote products derived from this software without
Javier Martinez Canillas af88e8
+# specific prior written permission.
Javier Martinez Canillas af88e8
+#
Javier Martinez Canillas af88e8
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Javier Martinez Canillas af88e8
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Javier Martinez Canillas af88e8
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Javier Martinez Canillas af88e8
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
Javier Martinez Canillas af88e8
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Javier Martinez Canillas af88e8
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Javier Martinez Canillas af88e8
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Javier Martinez Canillas af88e8
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Javier Martinez Canillas af88e8
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Javier Martinez Canillas af88e8
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
Javier Martinez Canillas af88e8
+# THE POSSIBILITY OF SUCH DAMAGE.
Javier Martinez Canillas af88e8
+#;**********************************************************************;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+source test_helpers.sh
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+alg_primary_obj=sha256
Javier Martinez Canillas af88e8
+alg_primary_key=rsa
Javier Martinez Canillas af88e8
+alg_create_obj=sha256
Javier Martinez Canillas af88e8
+alg_create_key=rsa
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key"
Javier Martinez Canillas af88e8
+file_quote_key_pub=opu_"$alg_create_obj"_"$alg_create_key"
Javier Martinez Canillas af88e8
+file_quote_key_priv=opr_"$alg_create_obj"_"$alg_create_key"
Javier Martinez Canillas af88e8
+file_quote_key_name=name.load_"$alg_primary_obj"_"$alg_primary_key"-"$alg_create_obj"_"$alg_create_key"
Javier Martinez Canillas af88e8
+file_quote_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-"$alg_create_obj"_"$alg_create_key"
Javier Martinez Canillas af88e8
+output_ak_pub_pem=akpub.pem
Javier Martinez Canillas af88e8
+output_quote=quote.out
Javier Martinez Canillas af88e8
+output_quotesig=quotesig.out
Javier Martinez Canillas af88e8
+output_quotepcr=quotepcr.out
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+maxdigest=$(tpm2_getcap -c properties-fixed | grep TPM_PT_MAX_DIGEST | sed -r -e 's/.*(0x[0-9a-f]+)/\1/g')
Javier Martinez Canillas af88e8
+if ! [[ "$maxdigest" =~ ^(0x)*[0-9]+$ ]] ; then
Javier Martinez Canillas af88e8
+ echo "error: not a number, got: \"$maxdigest\"" >&2
Javier Martinez Canillas af88e8
+ exit 1
Javier Martinez Canillas af88e8
+fi
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+nonce=12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde
Javier Martinez Canillas af88e8
+nonce=${nonce:0:2*$maxdigest}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+cleanup() {
Javier Martinez Canillas af88e8
+  rm -f $file_primary_key_ctx $file_quote_key_pub $file_quote_key_priv \
Javier Martinez Canillas af88e8
+        $file_quote_key_name $file_quote_key_ctx $output_ak_pub_pem \
Javier Martinez Canillas af88e8
+        $output_quote $output_quotesig $output_quotepcr
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+trap cleanup EXIT
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+cleanup
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+tpm2_takeownership -c
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# Key generation
Javier Martinez Canillas af88e8
+tpm2_createprimary -Q -H e -g $alg_primary_obj -G $alg_primary_key -C $file_primary_key_ctx
Javier Martinez Canillas af88e8
+tpm2_create -Q -g $alg_create_obj -G $alg_create_key -u $file_quote_key_pub -r $file_quote_key_priv  -c $file_primary_key_ctx
Javier Martinez Canillas af88e8
+tpm2_load -Q -c $file_primary_key_ctx  -u $file_quote_key_pub  -r $file_quote_key_priv -n $file_quote_key_name -C $file_quote_key_ctx
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# Get the PEM version of pub ak cert
Javier Martinez Canillas af88e8
+tpm2_readpublic -Q -c $file_quote_key_ctx -o $output_ak_pub_pem -f pem
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# Quoting
Javier Martinez Canillas af88e8
+tpm2_quote -Q -c $file_quote_key_ctx  -L sha256:15,16,22 -q $nonce -m $output_quote -s $output_quotesig -p $output_quotepcr -G $alg_primary_obj
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+# Verify quote
Javier Martinez Canillas af88e8
+tpm2_checkquote -Q -c $output_ak_pub_pem -m $output_quote -s $output_quotesig -p $output_quotepcr -G $alg_primary_obj -q $nonce
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+exit 0
Javier Martinez Canillas af88e8
diff --git a/test/system/test_tpm2_quote.sh b/test/system/test_tpm2_quote.sh
Javier Martinez Canillas af88e8
index 231bed326ec..aa06a3d7040 100755
Javier Martinez Canillas af88e8
--- a/test/system/test_tpm2_quote.sh
Javier Martinez Canillas af88e8
+++ b/test/system/test_tpm2_quote.sh
Javier Martinez Canillas af88e8
@@ -52,6 +52,8 @@ Handle_ek_quote=0x81010017
Javier Martinez Canillas af88e8
 Handle_ak_quote2=0x81010018
Javier Martinez Canillas af88e8
 Handle_ak_quote3=0x81010019
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+toss_out=junk.out
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 maxdigest=$(tpm2_getcap -c properties-fixed | grep TPM_PT_MAX_DIGEST | sed -r -e 's/.*(0x[0-9a-f]+)/\1/g')
Javier Martinez Canillas af88e8
 if ! [[ "$maxdigest" =~ ^(0x)*[0-9]+$ ]] ; then
Javier Martinez Canillas af88e8
  echo "error: not a number, got: \"$maxdigest\"" >&2
Javier Martinez Canillas af88e8
@@ -69,7 +71,7 @@ trap onerror ERR
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 cleanup() {
Javier Martinez Canillas af88e8
     rm -f $file_primary_key_ctx $file_quote_key_pub $file_quote_key_priv \
Javier Martinez Canillas af88e8
-    $file_quote_key_name $file_quote_key_ctx ek.pub2 ak.pub2 ak.name_2 \
Javier Martinez Canillas af88e8
+    $file_quote_key_name $file_quote_key_ctx $toss_out ek.pub2 ak.pub2 ak.name_2 \
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     tpm2_evictcontrol -Q -Ao -H $Handle_ek_quote 2>/dev/null || true
Javier Martinez Canillas af88e8
     tpm2_evictcontrol -Q -Ao -H $Handle_ak_quote 2>/dev/null || true
Javier Martinez Canillas af88e8
@@ -90,21 +92,21 @@ tpm2_load -Q -c $file_primary_key_ctx  -u $file_quote_key_pub  -r $file_quote_ke
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 tpm2_quote -Q -c $file_quote_key_ctx  -g $alg_quote -l 16,17,18 -q $nonce
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-tpm2_quote -Q -c $file_quote_key_ctx  -L $alg_quote:16,17,18+$alg_quote1:16,17,18 -q $nonce
Javier Martinez Canillas af88e8
+tpm2_quote -Q -c $file_quote_key_ctx  -L $alg_quote:16,17,18+$alg_quote1:16,17,18 -q $nonce -m $toss_out -s $toss_out -p $toss_out -G $alg_primary_obj
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 #####handle testing
Javier Martinez Canillas af88e8
 tpm2_evictcontrol -Q -A o -c $file_quote_key_ctx -S $Handle_ak_quote
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-tpm2_quote -Q -k $Handle_ak_quote  -g $alg_quote -l 16,17,18 -q $nonce
Javier Martinez Canillas af88e8
+tpm2_quote -Q -k $Handle_ak_quote  -g $alg_quote -l 16,17,18 -q $nonce -m $toss_out -s $toss_out -p $toss_out -G $alg_primary_obj
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-tpm2_quote -Q -k $Handle_ak_quote  -L $alg_quote:16,17,18+$alg_quote1:16,17,18 -q $nonce
Javier Martinez Canillas af88e8
+tpm2_quote -Q -k $Handle_ak_quote  -L $alg_quote:16,17,18+$alg_quote1:16,17,18 -q $nonce -m $toss_out -s $toss_out -p $toss_out -G $alg_primary_obj
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 #####AK
Javier Martinez Canillas af88e8
 tpm2_getpubek -Q -H  $Handle_ek_quote -g 0x01 -f ek.pub2
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 tpm2_getpubak -Q -E  $Handle_ek_quote -k  $Handle_ak_quote2 -f ak.pub2 -n ak.name_2
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-tpm2_quote -Q -k $Handle_ak_quote -g $alg_quote -l 16,17,18 -q $nonce
Javier Martinez Canillas af88e8
+tpm2_quote -Q -k $Handle_ak_quote -g $alg_quote -l 16,17,18 -q $nonce -m $toss_out -s $toss_out -p $toss_out -G $alg_primary_obj
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 #####AK with password
Javier Martinez Canillas af88e8
 tpm2_getpubak -Q -E  $Handle_ek_quote -k  $Handle_ak_quote3 -f ak.pub2 -n ak.name_2 -P abc123
Javier Martinez Canillas af88e8
diff --git a/tools/tpm2_checkquote.c b/tools/tpm2_checkquote.c
Javier Martinez Canillas af88e8
new file mode 100644
Javier Martinez Canillas af88e8
index 00000000000..0efd7f3ca88
Javier Martinez Canillas af88e8
--- /dev/null
Javier Martinez Canillas af88e8
+++ b/tools/tpm2_checkquote.c
Javier Martinez Canillas af88e8
@@ -0,0 +1,409 @@
Javier Martinez Canillas af88e8
+//**********************************************************************;
Javier Martinez Canillas af88e8
+// Copyright (c) 2019 Massachusetts Institute of Technology.
Javier Martinez Canillas af88e8
+// All rights reserved.
Javier Martinez Canillas af88e8
+//
Javier Martinez Canillas af88e8
+// Redistribution and use in source and binary forms, with or without
Javier Martinez Canillas af88e8
+// modification, are permitted provided that the following conditions are met:
Javier Martinez Canillas af88e8
+//
Javier Martinez Canillas af88e8
+// 1. Redistributions of source code must retain the above copyright notice,
Javier Martinez Canillas af88e8
+// this list of conditions and the following disclaimer.
Javier Martinez Canillas af88e8
+//
Javier Martinez Canillas af88e8
+// 2. Redistributions in binary form must reproduce the above copyright notice,
Javier Martinez Canillas af88e8
+// this list of conditions and the following disclaimer in the documentation
Javier Martinez Canillas af88e8
+// and/or other materials provided with the distribution.
Javier Martinez Canillas af88e8
+//
Javier Martinez Canillas af88e8
+// 3. Neither the name of Intel Corporation nor the names of its contributors
Javier Martinez Canillas af88e8
+// may be used to endorse or promote products derived from this software without
Javier Martinez Canillas af88e8
+// specific prior written permission.
Javier Martinez Canillas af88e8
+//
Javier Martinez Canillas af88e8
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Javier Martinez Canillas af88e8
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Javier Martinez Canillas af88e8
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Javier Martinez Canillas af88e8
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
Javier Martinez Canillas af88e8
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Javier Martinez Canillas af88e8
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Javier Martinez Canillas af88e8
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Javier Martinez Canillas af88e8
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Javier Martinez Canillas af88e8
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Javier Martinez Canillas af88e8
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
Javier Martinez Canillas af88e8
+// THE POSSIBILITY OF SUCH DAMAGE.
Javier Martinez Canillas af88e8
+//**********************************************************************;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+#include <stdlib.h>
Javier Martinez Canillas af88e8
+#include <stdio.h>
Javier Martinez Canillas af88e8
+#include <string.h>
Javier Martinez Canillas af88e8
+#include <errno.h>
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+#include <tss2/tss2_esys.h>
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+#include <openssl/rsa.h>
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+#include "files.h"
Javier Martinez Canillas af88e8
+#include "log.h"
Javier Martinez Canillas af88e8
+#include "pcr.h"
Javier Martinez Canillas af88e8
+#include "tpm2_alg_util.h"
Javier Martinez Canillas af88e8
+#include "conversion.h"
Javier Martinez Canillas af88e8
+#include "tpm_hash.h"
Javier Martinez Canillas af88e8
+#include "tpm2_openssl.h"
Javier Martinez Canillas af88e8
+#include "tpm2_options.h"
Javier Martinez Canillas af88e8
+#include "tpm2_tool.h"
Javier Martinez Canillas af88e8
+#include "tpm2_util.h"
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+typedef struct tpm2_verifysig_ctx tpm2_verifysig_ctx;
Javier Martinez Canillas af88e8
+struct tpm2_verifysig_ctx {
Javier Martinez Canillas af88e8
+    union {
Javier Martinez Canillas af88e8
+        struct {
Javier Martinez Canillas af88e8
+            UINT8 halg :1;
Javier Martinez Canillas af88e8
+            UINT8 msg :1;
Javier Martinez Canillas af88e8
+            UINT8 sig :1;
Javier Martinez Canillas af88e8
+            UINT8 pcr :1;
Javier Martinez Canillas af88e8
+            UINT8 extra :1;
Javier Martinez Canillas af88e8
+            UINT8 key_context :1;
Javier Martinez Canillas af88e8
+            UINT8 fmt;
Javier Martinez Canillas af88e8
+        };
Javier Martinez Canillas af88e8
+        UINT8 all;
Javier Martinez Canillas af88e8
+    } flags;
Javier Martinez Canillas af88e8
+    TPMI_ALG_SIG_SCHEME format;
Javier Martinez Canillas af88e8
+    TPMI_ALG_HASH halg;
Javier Martinez Canillas af88e8
+    TPM2B_DIGEST msgHash;
Javier Martinez Canillas af88e8
+    TPM2B_DIGEST pcrHash;
Javier Martinez Canillas af88e8
+    TPM2B_DIGEST quoteHash;
Javier Martinez Canillas af88e8
+    TPM2B_DATA quoteExtraData;
Javier Martinez Canillas af88e8
+    TPM2B_DATA extraData;
Javier Martinez Canillas af88e8
+    TPMT_SIGNATURE signature;
Javier Martinez Canillas af88e8
+    char *msg_file_path;
Javier Martinez Canillas af88e8
+    char *sig_file_path;
Javier Martinez Canillas af88e8
+    char *out_file_path;
Javier Martinez Canillas af88e8
+    char *pcr_file_path;
Javier Martinez Canillas af88e8
+    const char *pubkey_file_path;
Javier Martinez Canillas af88e8
+};
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+tpm2_verifysig_ctx ctx = {
Javier Martinez Canillas af88e8
+        .format = TPM2_ALG_ERROR,
Javier Martinez Canillas af88e8
+        .halg = TPM2_ALG_SHA1,
Javier Martinez Canillas af88e8
+        .msgHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
Javier Martinez Canillas af88e8
+        .pcrHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
Javier Martinez Canillas af88e8
+        .quoteHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
Javier Martinez Canillas af88e8
+        .quoteExtraData = TPM2B_TYPE_INIT(TPM2B_DATA, buffer),
Javier Martinez Canillas af88e8
+        .extraData = TPM2B_TYPE_INIT(TPM2B_DATA, buffer),
Javier Martinez Canillas af88e8
+};
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+static bool verify_signature() {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    bool result = false;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Read in the AKpub they provided as an RSA object
Javier Martinez Canillas af88e8
+    FILE *pubkey_input = fopen(ctx.pubkey_file_path, "rb");
Javier Martinez Canillas af88e8
+    if (!pubkey_input) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Could not open RSA pubkey input file \"%s\" error: \"%s\"",
Javier Martinez Canillas af88e8
+                ctx.pubkey_file_path, strerror(errno));
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    RSA *pubKey = tpm2_openssl_get_public_RSA_from_pem(pubkey_input, ctx.pubkey_file_path);
Javier Martinez Canillas af88e8
+    if (pubKey == NULL) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Failed to load RSA public key from file");
Javier Martinez Canillas af88e8
+        goto err;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Get the signature ready
Javier Martinez Canillas af88e8
+    if (ctx.signature.sigAlg != TPM2_ALG_RSASSA) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Only RSASSA is supported for signatures");
Javier Martinez Canillas af88e8
+        goto err;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    TPM2B_PUBLIC_KEY_RSA sig = ctx.signature.signature.rsassa.sig;
Javier Martinez Canillas af88e8
+    tpm2_tool_output("sigBuffer: ");
Javier Martinez Canillas af88e8
+    tpm2_util_hexdump(sig.buffer, sig.size, true);
Javier Martinez Canillas af88e8
+    tpm2_tool_output("\n");
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Verify the signature matches message digest
Javier Martinez Canillas af88e8
+    int opensslHash = tpm2_openssl_halgid_from_tpmhalg(ctx.signature.signature.rsassa.hash);
Javier Martinez Canillas af88e8
+    if (!RSA_verify(opensslHash, ctx.msgHash.buffer, ctx.msgHash.size, 
Javier Martinez Canillas af88e8
+            sig.buffer, sig.size, pubKey)) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Error validating signed message with public key provided");
Javier Martinez Canillas af88e8
+        goto err;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Ensure nonce is the same as given
Javier Martinez Canillas af88e8
+    if (ctx.flags.extra) {
Javier Martinez Canillas af88e8
+        if (
Javier Martinez Canillas af88e8
+            ctx.quoteExtraData.size != ctx.extraData.size 
Javier Martinez Canillas af88e8
+            || memcmp(ctx.quoteExtraData.buffer, ctx.extraData.buffer, ctx.extraData.size) != 0
Javier Martinez Canillas af88e8
+        ) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Error validating nonce from quote");
Javier Martinez Canillas af88e8
+            goto err;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Also ensure digest from quote matches PCR digest
Javier Martinez Canillas af88e8
+    if (ctx.flags.pcr) {
Javier Martinez Canillas af88e8
+        if (!tpm2_util_verify_digests(&ctx.quoteHash, &ctx.pcrHash)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Error validating PCR composite against signed message");
Javier Martinez Canillas af88e8
+            goto err;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    result = true;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+err: 
Javier Martinez Canillas af88e8
+    if (pubkey_input) {
Javier Martinez Canillas af88e8
+        fclose(pubkey_input);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    RSA_free(pubKey);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return result;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+static TPM2B_ATTEST *message_from_file(const char *msg_file_path) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    unsigned long size;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    bool result = files_get_file_size_path(msg_file_path, &size);
Javier Martinez Canillas af88e8
+    if (!result) {
Javier Martinez Canillas af88e8
+        return NULL;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (!size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("The msg file \"%s\" is empty", msg_file_path);
Javier Martinez Canillas af88e8
+        return NULL;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    TPM2B_ATTEST *msg = (TPM2B_ATTEST *) calloc(1, sizeof(TPM2B_ATTEST) + size);
Javier Martinez Canillas af88e8
+    if (!msg) {
Javier Martinez Canillas af88e8
+        LOG_ERR("OOM");
Javier Martinez Canillas af88e8
+        return NULL;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT16 tmp = msg->size = size;
Javier Martinez Canillas af88e8
+    if (!files_load_bytes_from_path(msg_file_path, msg->attestationData, &tmp)) {
Javier Martinez Canillas af88e8
+        free(msg);
Javier Martinez Canillas af88e8
+        return NULL;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    return msg;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+static bool pcrs_from_file(const char *pcr_file_path, 
Javier Martinez Canillas af88e8
+        TPML_PCR_SELECTION *pcrSel, tpm2_pcrs *pcrs) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    bool result = false;
Javier Martinez Canillas af88e8
+    unsigned long size;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (!files_get_file_size_path(pcr_file_path, &size)) {
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (!size) {
Javier Martinez Canillas af88e8
+        LOG_ERR("The pcr file \"%s\" is empty", pcr_file_path);
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    FILE *pcr_input = fopen(pcr_file_path, "rb");
Javier Martinez Canillas af88e8
+    if (!pcr_input) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Could not open PCRs input file \"%s\" error: \"%s\"",
Javier Martinez Canillas af88e8
+                pcr_file_path, strerror(errno));
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Import TPML_PCR_SELECTION structure to pcr outfile
Javier Martinez Canillas af88e8
+    if (fread(pcrSel, sizeof(TPML_PCR_SELECTION), 1, pcr_input) != 1) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Failed to read PCR selection from file");
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Import PCR digests to pcr outfile
Javier Martinez Canillas af88e8
+    if (fread(&pcrs->count, sizeof(UINT32), 1, pcr_input) != 1) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Failed to read PCR digests header from file");
Javier Martinez Canillas af88e8
+        goto out;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT32 j;
Javier Martinez Canillas af88e8
+    for (j = 0; j < pcrs->count; j++) {
Javier Martinez Canillas af88e8
+        if (fread(&pcrs->pcr_values[j], sizeof(TPML_DIGEST), 1, pcr_input) != 1) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to read PCR digest from file");
Javier Martinez Canillas af88e8
+            goto out;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    result = true;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+out:
Javier Martinez Canillas af88e8
+    if (pcr_input) {
Javier Martinez Canillas af88e8
+        fclose(pcr_input);
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return result;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+static bool init() {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    /* check flags for mismatches */
Javier Martinez Canillas af88e8
+    if (!(ctx.pubkey_file_path && ctx.flags.sig && ctx.flags.msg && ctx.flags.halg)) {
Javier Martinez Canillas af88e8
+        LOG_ERR(
Javier Martinez Canillas af88e8
+                "--pubkey (-c), --msg (-m), --halg (-g) and --sig (-s) are required");
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    TPM2B_ATTEST *msg = NULL;
Javier Martinez Canillas af88e8
+    TPML_PCR_SELECTION pcrSel;
Javier Martinez Canillas af88e8
+    tpm2_pcrs pcrs;
Javier Martinez Canillas af88e8
+    bool return_value = false;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (ctx.flags.msg) {
Javier Martinez Canillas af88e8
+        msg = message_from_file(ctx.msg_file_path);
Javier Martinez Canillas af88e8
+        if (!msg) {
Javier Martinez Canillas af88e8
+            /* message_from_file() logs specific error no need to here */
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (ctx.flags.sig) {
Javier Martinez Canillas af88e8
+        bool res =  files_load_signature(ctx.sig_file_path, &ctx.signature);
Javier Martinez Canillas af88e8
+        if (!res) {
Javier Martinez Canillas af88e8
+            goto err;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    /* If no digest is specified, compute it */
Javier Martinez Canillas af88e8
+    if (!ctx.flags.msg) {
Javier Martinez Canillas af88e8
+        /*
Javier Martinez Canillas af88e8
+         * This is a redundant check since main() checks this case, but we'll add it here to silence any
Javier Martinez Canillas af88e8
+         * complainers.
Javier Martinez Canillas af88e8
+         */
Javier Martinez Canillas af88e8
+        LOG_ERR("No digest set and no message file to compute from, cannot compute message hash!");
Javier Martinez Canillas af88e8
+        goto err;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (ctx.flags.pcr) {
Javier Martinez Canillas af88e8
+        if (!pcrs_from_file(ctx.pcr_file_path, &pcrSel, &pcrs)) {
Javier Martinez Canillas af88e8
+            /* pcrs_from_file() logs specific error no need to here */
Javier Martinez Canillas af88e8
+            goto err;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        if (!tpm2_openssl_hash_pcr_banks(ctx.halg, &pcrSel, &pcrs, &ctx.pcrHash)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to hash PCR values related to quote!");
Javier Martinez Canillas af88e8
+            goto err;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+        if (!pcr_print_pcr_struct(&pcrSel, &pcrs)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to print PCR values related to quote!");
Javier Martinez Canillas af88e8
+            goto err;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+        tpm2_tool_output("calcDigest: ");
Javier Martinez Canillas af88e8
+        tpm2_util_hexdump(ctx.pcrHash.buffer, ctx.pcrHash.size, true);
Javier Martinez Canillas af88e8
+        tpm2_tool_output("\n");
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Figure out the extra data (nonce) from this message
Javier Martinez Canillas af88e8
+    if (!tpm2_util_get_digest_from_quote(msg, &ctx.quoteHash, &ctx.quoteExtraData)) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Failed to get digest from quote!");
Javier Martinez Canillas af88e8
+        goto err;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Figure out the digest for this message
Javier Martinez Canillas af88e8
+    bool res = tpm2_openssl_hash_compute_data(ctx.halg, msg->attestationData, 
Javier Martinez Canillas af88e8
+        msg->size, &ctx.msgHash);
Javier Martinez Canillas af88e8
+    if (!res) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Compute message hash failed!");
Javier Martinez Canillas af88e8
+        goto err;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+    tpm2_tool_output("msgDigest: ");
Javier Martinez Canillas af88e8
+    tpm2_util_hexdump(ctx.msgHash.buffer, ctx.msgHash.size, true);
Javier Martinez Canillas af88e8
+    tpm2_tool_output("\n");
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return_value = true;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+err:
Javier Martinez Canillas af88e8
+    free(msg);
Javier Martinez Canillas af88e8
+    return return_value;
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+static bool on_option(char key, char *value) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+	switch (key) {
Javier Martinez Canillas af88e8
+	case 'c':
Javier Martinez Canillas af88e8
+	    ctx.pubkey_file_path = value;
Javier Martinez Canillas af88e8
+	    break;
Javier Martinez Canillas af88e8
+	case 'G': {
Javier Martinez Canillas af88e8
+		ctx.halg = tpm2_alg_util_from_optarg(value);
Javier Martinez Canillas af88e8
+		if (ctx.halg == TPM2_ALG_ERROR) {
Javier Martinez Canillas af88e8
+			LOG_ERR("Unable to convert algorithm, got: \"%s\"", value);
Javier Martinez Canillas af88e8
+			return false;
Javier Martinez Canillas af88e8
+		}
Javier Martinez Canillas af88e8
+		ctx.flags.halg = 1;
Javier Martinez Canillas af88e8
+	}
Javier Martinez Canillas af88e8
+		break;
Javier Martinez Canillas af88e8
+	case 'm': {
Javier Martinez Canillas af88e8
+		ctx.msg_file_path = value;
Javier Martinez Canillas af88e8
+		ctx.flags.msg = 1;
Javier Martinez Canillas af88e8
+	}
Javier Martinez Canillas af88e8
+		break;
Javier Martinez Canillas af88e8
+	case 'f': {
Javier Martinez Canillas af88e8
+		ctx.format = tpm2_alg_util_from_optarg(value);
Javier Martinez Canillas af88e8
+		if (ctx.format == TPM2_ALG_ERROR) {
Javier Martinez Canillas af88e8
+		    LOG_ERR("Unknown signing scheme, got: \"%s\"", value);
Javier Martinez Canillas af88e8
+		    return false;
Javier Martinez Canillas af88e8
+		}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+		ctx.flags.fmt = 1;
Javier Martinez Canillas af88e8
+	} break;
Javier Martinez Canillas af88e8
+	case 'q':
Javier Martinez Canillas af88e8
+		ctx.extraData.size = sizeof(ctx.extraData) - 2;
Javier Martinez Canillas af88e8
+		if(tpm2_util_hex_to_byte_structure(value, &ctx.extraData.size, ctx.extraData.buffer) != 0)
Javier Martinez Canillas af88e8
+		{
Javier Martinez Canillas af88e8
+			LOG_ERR("Could not convert \"%s\" from a hex string to byte array!", value);
Javier Martinez Canillas af88e8
+			return false;
Javier Martinez Canillas af88e8
+		}
Javier Martinez Canillas af88e8
+		ctx.flags.extra = 1;
Javier Martinez Canillas af88e8
+		break;
Javier Martinez Canillas af88e8
+	case 's':
Javier Martinez Canillas af88e8
+		ctx.sig_file_path = value;
Javier Martinez Canillas af88e8
+		ctx.flags.sig = 1;
Javier Martinez Canillas af88e8
+		break;
Javier Martinez Canillas af88e8
+	case 'p':
Javier Martinez Canillas af88e8
+		ctx.pcr_file_path = value;
Javier Martinez Canillas af88e8
+		ctx.flags.pcr = 1;
Javier Martinez Canillas af88e8
+		break;
Javier Martinez Canillas af88e8
+		/* no default */
Javier Martinez Canillas af88e8
+	}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+bool tpm2_tool_onstart(tpm2_options **opts) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    const struct option topts[] = {
Javier Martinez Canillas af88e8
+            { "halg",         required_argument, NULL, 'G' },
Javier Martinez Canillas af88e8
+            { "message",      required_argument, NULL, 'm' },
Javier Martinez Canillas af88e8
+            { "format",       required_argument, NULL, 'f' },
Javier Martinez Canillas af88e8
+            { "sig",          required_argument, NULL, 's' },
Javier Martinez Canillas af88e8
+            { "pcrs",         required_argument, NULL, 'p' },
Javier Martinez Canillas af88e8
+            { "pubkey",       required_argument, NULL, 'c' },
Javier Martinez Canillas af88e8
+            { "qualify-data",         required_argument, NULL, 'q' },
Javier Martinez Canillas af88e8
+    };
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    *opts = tpm2_options_new("G:m:f:s:t:c:p:q:", ARRAY_LEN(topts), topts,
Javier Martinez Canillas af88e8
+                             on_option, NULL, TPM2_OPTIONS_NO_SAPI);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return *opts != NULL;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+	UNUSED(sapi_context);
Javier Martinez Canillas af88e8
+	UNUSED(flags);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    /* initialize and process */
Javier Martinez Canillas af88e8
+    bool res = init();
Javier Martinez Canillas af88e8
+    if (!res) {
Javier Martinez Canillas af88e8
+        return 1;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    res = verify_signature();
Javier Martinez Canillas af88e8
+    if (!res) {
Javier Martinez Canillas af88e8
+        LOG_ERR("Verify signature failed!");
Javier Martinez Canillas af88e8
+        return 1;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return 0;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
diff --git a/tools/tpm2_pcrlist.c b/tools/tpm2_pcrlist.c
Javier Martinez Canillas af88e8
index 581bcecbd63..9a1ee457ce1 100644
Javier Martinez Canillas af88e8
--- a/tools/tpm2_pcrlist.c
Javier Martinez Canillas af88e8
+++ b/tools/tpm2_pcrlist.c
Javier Martinez Canillas af88e8
@@ -44,17 +44,6 @@
Javier Martinez Canillas af88e8
 #include "tpm2_alg_util.h"
Javier Martinez Canillas af88e8
 #include "tpm2_tool.h"
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-typedef struct tpm2_algorithm tpm2_algorithm;
Javier Martinez Canillas af88e8
-struct tpm2_algorithm {
Javier Martinez Canillas af88e8
-    int count;
Javier Martinez Canillas af88e8
-    TPMI_ALG_HASH alg[8]; //XXX Why 8?
Javier Martinez Canillas af88e8
-};
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-typedef struct tpm2_pcrs tpm2_pcrs;
Javier Martinez Canillas af88e8
-struct tpm2_pcrs {
Javier Martinez Canillas af88e8
-    size_t count;
Javier Martinez Canillas af88e8
-    TPML_DIGEST pcr_values[24]; //XXX Why 24?
Javier Martinez Canillas af88e8
-};
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 typedef struct listpcr_context listpcr_context;
Javier Martinez Canillas af88e8
 struct listpcr_context {
Javier Martinez Canillas af88e8
@@ -85,163 +74,6 @@ static listpcr_context ctx = {
Javier Martinez Canillas af88e8
     },
Javier Martinez Canillas af88e8
 };
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-static inline void set_pcr_select_size(TPMS_PCR_SELECTION *pcr_selection,
Javier Martinez Canillas af88e8
-        UINT8 size) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    pcr_selection->sizeofSelect = size;
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-static bool is_pcr_select_bit_set(TPMS_PCR_SELECTION *pcr_selection, UINT32 pcr) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    return (pcr_selection->pcrSelect[((pcr) / 8)] & (1 << ((pcr) % 8)));
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-static void update_pcr_selections(TPML_PCR_SELECTION *s1, TPML_PCR_SELECTION *s2) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    UINT32 i1, i2, j;
Javier Martinez Canillas af88e8
-    for (i2 = 0; i2 < s2->count; i2++) {
Javier Martinez Canillas af88e8
-        for (i1 = 0; i1 < s1->count; i1++) {
Javier Martinez Canillas af88e8
-            if (s2->pcrSelections[i2].hash != s1->pcrSelections[i1].hash)
Javier Martinez Canillas af88e8
-                continue;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-            for (j = 0; j < s1->pcrSelections[i1].sizeofSelect; j++)
Javier Martinez Canillas af88e8
-                s1->pcrSelections[i1].pcrSelect[j] &=
Javier Martinez Canillas af88e8
-                        ~s2->pcrSelections[i2].pcrSelect[j];
Javier Martinez Canillas af88e8
-        }
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-static bool unset_pcr_sections(TPML_PCR_SELECTION *s) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    UINT32 i, j;
Javier Martinez Canillas af88e8
-    for (i = 0; i < s->count; i++) {
Javier Martinez Canillas af88e8
-        for (j = 0; j < s->pcrSelections[i].sizeofSelect; j++) {
Javier Martinez Canillas af88e8
-            if (s->pcrSelections[i].pcrSelect[j]) {
Javier Martinez Canillas af88e8
-                return false;
Javier Martinez Canillas af88e8
-            }
Javier Martinez Canillas af88e8
-        }
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    return true;
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-static bool read_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    TPML_PCR_SELECTION pcr_selection_tmp;
Javier Martinez Canillas af88e8
-    TPML_PCR_SELECTION pcr_selection_out;
Javier Martinez Canillas af88e8
-    UINT32 pcr_update_counter;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    //1. prepare pcrSelectionIn with g_pcrSelections
Javier Martinez Canillas af88e8
-    memcpy(&pcr_selection_tmp, &ctx.pcr_selections, sizeof(pcr_selection_tmp));
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    //2. call pcr_read
Javier Martinez Canillas af88e8
-    ctx.pcrs.count = 0;
Javier Martinez Canillas af88e8
-    do {
Javier Martinez Canillas af88e8
-        UINT32 rval = TSS2_RETRY_EXP(Tss2_Sys_PCR_Read(sapi_context, no_argument, &pcr_selection_tmp,
Javier Martinez Canillas af88e8
-                &pcr_update_counter, &pcr_selection_out,
Javier Martinez Canillas af88e8
-                &ctx.pcrs.pcr_values[ctx.pcrs.count], 0));
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-        if (rval != TPM2_RC_SUCCESS) {
Javier Martinez Canillas af88e8
-            LOG_ERR("read pcr failed. tpm error 0x%0x", rval);
Javier Martinez Canillas af88e8
-            return -1;
Javier Martinez Canillas af88e8
-        }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-        //3. unmask pcrSelectionOut bits from pcrSelectionIn
Javier Martinez Canillas af88e8
-        update_pcr_selections(&pcr_selection_tmp, &pcr_selection_out);
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-        //4. goto step 2 if pcrSelctionIn still has bits set
Javier Martinez Canillas af88e8
-    } while (++ctx.pcrs.count < 24 && !unset_pcr_sections(&pcr_selection_tmp));
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    if (ctx.pcrs.count >= 24 && !unset_pcr_sections(&pcr_selection_tmp)) {
Javier Martinez Canillas af88e8
-        LOG_ERR("too much pcrs to get! try to split into multiple calls...");
Javier Martinez Canillas af88e8
-        return false;
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    return true;
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-static bool init_pcr_selection(void) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    TPMS_CAPABILITY_DATA *cap_data = &ctx.cap_data;
Javier Martinez Canillas af88e8
-    TPML_PCR_SELECTION *pcr_sel = &ctx.pcr_selections;
Javier Martinez Canillas af88e8
-    UINT32 i, j;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    TPMI_ALG_HASH alg_id = ctx.selected_algorithm;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    pcr_sel->count = 0;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    for (i = 0; i < cap_data->data.assignedPCR.count; i++) {
Javier Martinez Canillas af88e8
-        if (alg_id && (cap_data->data.assignedPCR.pcrSelections[i].hash != alg_id))
Javier Martinez Canillas af88e8
-            continue;
Javier Martinez Canillas af88e8
-        pcr_sel->pcrSelections[pcr_sel->count].hash = cap_data->data.assignedPCR.pcrSelections[i].hash;
Javier Martinez Canillas af88e8
-        set_pcr_select_size(&pcr_sel->pcrSelections[pcr_sel->count], cap_data->data.assignedPCR.pcrSelections[i].sizeofSelect);
Javier Martinez Canillas af88e8
-        for (j = 0; j < pcr_sel->pcrSelections[pcr_sel->count].sizeofSelect; j++)
Javier Martinez Canillas af88e8
-            pcr_sel->pcrSelections[pcr_sel->count].pcrSelect[j] = cap_data->data.assignedPCR.pcrSelections[i].pcrSelect[j];
Javier Martinez Canillas af88e8
-        pcr_sel->count++;
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    if (pcr_sel->count == 0)
Javier Martinez Canillas af88e8
-        return false;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    return true;
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-static void shrink_pcr_selection(TPML_PCR_SELECTION *s) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    UINT32 i, j;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    //seek for the first empty item
Javier Martinez Canillas af88e8
-    for (i = 0; i < s->count; i++)
Javier Martinez Canillas af88e8
-        if (!s->pcrSelections[i].hash)
Javier Martinez Canillas af88e8
-            break;
Javier Martinez Canillas af88e8
-    j = i + 1;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    for (; i < s->count; i++) {
Javier Martinez Canillas af88e8
-        if (!s->pcrSelections[i].hash) {
Javier Martinez Canillas af88e8
-            for (; j < s->count; j++)
Javier Martinez Canillas af88e8
-                if (s->pcrSelections[j].hash)
Javier Martinez Canillas af88e8
-                    break;
Javier Martinez Canillas af88e8
-            if (j >= s->count)
Javier Martinez Canillas af88e8
-                break;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-            memcpy(&s->pcrSelections[i], &s->pcrSelections[j], sizeof(s->pcrSelections[i]));
Javier Martinez Canillas af88e8
-            s->pcrSelections[j].hash = 0;
Javier Martinez Canillas af88e8
-            j++;
Javier Martinez Canillas af88e8
-        }
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    s->count = i;
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-static bool check_pcr_selection(void) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    TPMS_CAPABILITY_DATA *cap_data = &ctx.cap_data;
Javier Martinez Canillas af88e8
-    TPML_PCR_SELECTION *pcr_sel = &ctx.pcr_selections;
Javier Martinez Canillas af88e8
-    UINT32 i, j, k;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    for (i = 0; i < pcr_sel->count; i++) {
Javier Martinez Canillas af88e8
-        for (j = 0; j < cap_data->data.assignedPCR.count; j++) {
Javier Martinez Canillas af88e8
-            if (pcr_sel->pcrSelections[i].hash == cap_data->data.assignedPCR.pcrSelections[j].hash) {
Javier Martinez Canillas af88e8
-                for (k = 0; k < pcr_sel->pcrSelections[i].sizeofSelect; k++)
Javier Martinez Canillas af88e8
-                    pcr_sel->pcrSelections[i].pcrSelect[k] &= cap_data->data.assignedPCR.pcrSelections[j].pcrSelect[k];
Javier Martinez Canillas af88e8
-                break;
Javier Martinez Canillas af88e8
-            }
Javier Martinez Canillas af88e8
-        }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-        if (j >= cap_data->data.assignedPCR.count) {
Javier Martinez Canillas af88e8
-            const char *alg_name = tpm2_alg_util_algtostr(pcr_sel->pcrSelections[i].hash);
Javier Martinez Canillas af88e8
-            LOG_WARN("Ignore unsupported bank/algorithm: %s(0x%04x)", alg_name, pcr_sel->pcrSelections[i].hash);
Javier Martinez Canillas af88e8
-            pcr_sel->pcrSelections[i].hash = 0; //mark it as to be removed
Javier Martinez Canillas af88e8
-        }
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    shrink_pcr_selection(pcr_sel);
Javier Martinez Canillas af88e8
-    if (pcr_sel->count == 0)
Javier Martinez Canillas af88e8
-        return false;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    return true;
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
 // show all PCR banks according to g_pcrSelection & g_pcrs->
Javier Martinez Canillas af88e8
 static bool show_pcr_values(void) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
@@ -255,7 +87,7 @@ static bool show_pcr_values(void) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
         UINT32 pcr_id;
Javier Martinez Canillas af88e8
         for (pcr_id = 0; pcr_id < ctx.pcr_selections.pcrSelections[i].sizeofSelect * 8; pcr_id++) {
Javier Martinez Canillas af88e8
-            if (!is_pcr_select_bit_set(&ctx.pcr_selections.pcrSelections[i],
Javier Martinez Canillas af88e8
+            if (!tpm2_util_is_pcr_select_bit_set(&ctx.pcr_selections.pcrSelections[i],
Javier Martinez Canillas af88e8
                     pcr_id)) {
Javier Martinez Canillas af88e8
                 continue;
Javier Martinez Canillas af88e8
             }
Javier Martinez Canillas af88e8
@@ -296,10 +128,10 @@ static bool show_pcr_values(void) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 static bool show_selected_pcr_values(TSS2_SYS_CONTEXT *sapi_context, bool check) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-    if (check && !check_pcr_selection())
Javier Martinez Canillas af88e8
+    if (check && !pcr_check_pcr_selection(&ctx.cap_data, &ctx.pcr_selections))
Javier Martinez Canillas af88e8
         return false;
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-    if (!read_pcr_values(sapi_context))
Javier Martinez Canillas af88e8
+    if (!pcr_read_pcr_values(sapi_context, &ctx.pcr_selections, &ctx.pcrs))
Javier Martinez Canillas af88e8
         return false;
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     if (!show_pcr_values())
Javier Martinez Canillas af88e8
@@ -310,7 +142,7 @@ static bool show_selected_pcr_values(TSS2_SYS_CONTEXT *sapi_context, bool check)
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 static bool show_all_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-    if (!init_pcr_selection())
Javier Martinez Canillas af88e8
+    if (!pcr_init_pcr_selection(&ctx.cap_data, &ctx.pcr_selections, ctx.selected_algorithm))
Javier Martinez Canillas af88e8
         return false;
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     return show_selected_pcr_values(sapi_context, false);
Javier Martinez Canillas af88e8
@@ -318,37 +150,12 @@ static bool show_all_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 static bool show_alg_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-    if (!init_pcr_selection())
Javier Martinez Canillas af88e8
+    if (!pcr_init_pcr_selection(&ctx.cap_data, &ctx.pcr_selections, ctx.selected_algorithm))
Javier Martinez Canillas af88e8
         return false;
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     return show_selected_pcr_values(sapi_context, false);
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-static bool get_banks(TSS2_SYS_CONTEXT *sapi_context) {
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    TPMI_YES_NO more_data;
Javier Martinez Canillas af88e8
-    TPMS_CAPABILITY_DATA *capability_data = &ctx.cap_data;
Javier Martinez Canillas af88e8
-    UINT32 rval;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    rval = TSS2_RETRY_EXP(Tss2_Sys_GetCapability(sapi_context, no_argument, TPM2_CAP_PCRS, no_argument, required_argument,
Javier Martinez Canillas af88e8
-            &more_data, capability_data, 0));
Javier Martinez Canillas af88e8
-    if (rval != TPM2_RC_SUCCESS) {
Javier Martinez Canillas af88e8
-        LOG_ERR(
Javier Martinez Canillas af88e8
-                "GetCapability: Get PCR allocation status Error. TPM Error:0x%x......",
Javier Martinez Canillas af88e8
-                rval);
Javier Martinez Canillas af88e8
-        return false;
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    unsigned i;
Javier Martinez Canillas af88e8
-    for (i = 0; i < capability_data->data.assignedPCR.count; i++) {
Javier Martinez Canillas af88e8
-        ctx.algs.alg[i] =
Javier Martinez Canillas af88e8
-                capability_data->data.assignedPCR.pcrSelections[i].hash;
Javier Martinez Canillas af88e8
-    }
Javier Martinez Canillas af88e8
-    ctx.algs.count = capability_data->data.assignedPCR.count;
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
-    return true;
Javier Martinez Canillas af88e8
-}
Javier Martinez Canillas af88e8
-
Javier Martinez Canillas af88e8
 static void show_banks(tpm2_algorithm *g_banks) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     tpm2_tool_output("Supported Bank/Algorithm:");
Javier Martinez Canillas af88e8
@@ -432,7 +239,7 @@ int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
Javier Martinez Canillas af88e8
         }
Javier Martinez Canillas af88e8
     }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-    success = get_banks(sapi_context);
Javier Martinez Canillas af88e8
+    success = pcr_get_banks(sapi_context, &ctx.cap_data, &ctx.algs);
Javier Martinez Canillas af88e8
     if (!success) {
Javier Martinez Canillas af88e8
         goto error;
Javier Martinez Canillas af88e8
     }
Javier Martinez Canillas af88e8
diff --git a/tools/tpm2_quote.c b/tools/tpm2_quote.c
Javier Martinez Canillas af88e8
index 05b6d641656..2efba240340 100644
Javier Martinez Canillas af88e8
--- a/tools/tpm2_quote.c
Javier Martinez Canillas af88e8
+++ b/tools/tpm2_quote.c
Javier Martinez Canillas af88e8
@@ -42,6 +42,7 @@
Javier Martinez Canillas af88e8
 #include "conversion.h"
Javier Martinez Canillas af88e8
 #include "tpm2_alg_util.h"
Javier Martinez Canillas af88e8
 #include "tpm2_password_util.h"
Javier Martinez Canillas af88e8
+#include "tpm2_openssl.h"
Javier Martinez Canillas af88e8
 #include "tpm2_tool.h"
Javier Martinez Canillas af88e8
 #include "tpm2_util.h"
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
@@ -54,15 +55,27 @@ static TPMS_AUTH_COMMAND sessionData = TPMS_AUTH_COMMAND_INIT(TPM2_RS_PW);
Javier Martinez Canillas af88e8
 static char *outFilePath;
Javier Martinez Canillas af88e8
 static char *signature_path;
Javier Martinez Canillas af88e8
 static char *message_path;
Javier Martinez Canillas af88e8
+static char *pcr_path;
Javier Martinez Canillas af88e8
+static FILE *pcr_output;
Javier Martinez Canillas af88e8
+static TPMS_CAPABILITY_DATA cap_data;
Javier Martinez Canillas af88e8
 static signature_format sig_format;
Javier Martinez Canillas af88e8
 static TPMI_ALG_HASH sig_hash_algorithm;
Javier Martinez Canillas af88e8
+static tpm2_algorithm algs = {
Javier Martinez Canillas af88e8
+    .count = 3,
Javier Martinez Canillas af88e8
+    .alg = {
Javier Martinez Canillas af88e8
+        TPM2_ALG_SHA1,
Javier Martinez Canillas af88e8
+        TPM2_ALG_SHA256,
Javier Martinez Canillas af88e8
+        TPM2_ALG_SHA384
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+};
Javier Martinez Canillas af88e8
 static TPM2B_DATA qualifyingData = TPM2B_EMPTY_INIT;
Javier Martinez Canillas af88e8
 static TPML_PCR_SELECTION  pcrSelections;
Javier Martinez Canillas af88e8
 static bool is_auth_session;
Javier Martinez Canillas af88e8
 static TPMI_SH_AUTH_SESSION auth_session_handle;
Javier Martinez Canillas af88e8
-static int k_flag, c_flag, l_flag, g_flag, L_flag, o_flag, G_flag, P_flag;
Javier Martinez Canillas af88e8
+static int k_flag, c_flag, l_flag, g_flag, L_flag, o_flag, G_flag, P_flag, p_flag;
Javier Martinez Canillas af88e8
 static char *contextFilePath;
Javier Martinez Canillas af88e8
 static TPM2_HANDLE akHandle;
Javier Martinez Canillas af88e8
+static tpm2_pcrs pcrs;
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
 static void PrintBuffer( UINT8 *buffer, UINT32 size )
Javier Martinez Canillas af88e8
 {
Javier Martinez Canillas af88e8
@@ -74,6 +87,40 @@ static void PrintBuffer( UINT8 *buffer, UINT32 size )
Javier Martinez Canillas af88e8
     tpm2_tool_output("\n");
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+// write all PCR banks according to g_pcrSelection & g_pcrs->
Javier Martinez Canillas af88e8
+static bool write_pcr_values() {
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // PCR output to file wasn't requested
Javier Martinez Canillas af88e8
+    if (pcr_output == NULL) {
Javier Martinez Canillas af88e8
+        return true;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Export TPML_PCR_SELECTION structure to pcr outfile
Javier Martinez Canillas af88e8
+    if (fwrite(&pcrSelections,
Javier Martinez Canillas af88e8
+            sizeof(TPML_PCR_SELECTION), 1,
Javier Martinez Canillas af88e8
+            pcr_output) != 1) {
Javier Martinez Canillas af88e8
+        LOG_ERR("write to output file failed: %s", strerror(errno));
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Export PCR digests to pcr outfile
Javier Martinez Canillas af88e8
+    if (fwrite(&pcrs.count, sizeof(UINT32), 1, pcr_output) != 1) {
Javier Martinez Canillas af88e8
+        LOG_ERR("write to output file failed: %s", strerror(errno));
Javier Martinez Canillas af88e8
+        return false;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    UINT32 j;
Javier Martinez Canillas af88e8
+    for (j = 0; j < pcrs.count; j++) {
Javier Martinez Canillas af88e8
+        if (fwrite(&pcrs.pcr_values[j], sizeof(TPML_DIGEST), 1, pcr_output) != 1) {
Javier Martinez Canillas af88e8
+            LOG_ERR("write to output file failed: %s", strerror(errno));
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    return true;
Javier Martinez Canillas af88e8
+}
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
 static bool write_output_files(TPM2B_ATTEST *quoted, TPMT_SIGNATURE *signature) {
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     bool res = true;
Javier Martinez Canillas af88e8
@@ -87,6 +134,8 @@ static bool write_output_files(TPM2B_ATTEST *quoted, TPMT_SIGNATURE *signature)
Javier Martinez Canillas af88e8
                 quoted->size);
Javier Martinez Canillas af88e8
     }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+    res &= write_pcr_values();
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
     return res;
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
@@ -125,7 +174,53 @@ static int quote(TSS2_SYS_CONTEXT *sapi_context, TPM2_HANDLE akHandle, TPML_PCR_
Javier Martinez Canillas af88e8
     PrintBuffer( (UINT8 *)&signature, sizeof(signature) );
Javier Martinez Canillas af88e8
     //PrintTPMT_SIGNATURE(&signature);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+    if (pcr_output) {
Javier Martinez Canillas af88e8
+        // Filter out invalid/unavailable PCR selections
Javier Martinez Canillas af88e8
+        if (!pcr_check_pcr_selection(&cap_data, &pcrSelections)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to filter unavailable PCR values for quote!");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // Gather PCR values from the TPM (the quote doesn't have them!)
Javier Martinez Canillas af88e8
+        if (!pcr_read_pcr_values(sapi_context, &pcrSelections, &pcrs)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to retrieve PCR values related to quote!");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // Grab the digest from the quote
Javier Martinez Canillas af88e8
+        TPM2B_DIGEST quoteDigest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
Javier Martinez Canillas af88e8
+        TPM2B_DATA extraData = TPM2B_TYPE_INIT(TPM2B_DATA, buffer);
Javier Martinez Canillas af88e8
+        if (!tpm2_util_get_digest_from_quote(&quoted, &quoteDigest, &extraData)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to get digest from quote!");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // Print out PCR values as output
Javier Martinez Canillas af88e8
+        if (!pcr_print_pcr_struct(&pcrSelections, &pcrs)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to print PCR values related to quote!");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // Calculate the digest from our selected PCR values (to ensure correctness)
Javier Martinez Canillas af88e8
+        TPM2B_DIGEST pcr_digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
Javier Martinez Canillas af88e8
+        if (!tpm2_openssl_hash_pcr_banks(sig_hash_algorithm, &pcrSelections, &pcrs, &pcr_digest)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Failed to hash PCR values related to quote!");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+        tpm2_tool_output("calcDigest: ");
Javier Martinez Canillas af88e8
+        tpm2_util_hexdump(pcr_digest.buffer, pcr_digest.size, true);
Javier Martinez Canillas af88e8
+        tpm2_tool_output("\n");
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+        // Make sure digest from quote matches calculated PCR digest
Javier Martinez Canillas af88e8
+        if (!tpm2_util_verify_digests(&quoteDigest, &pcr_digest)) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Error validating calculated PCR composite with quote");
Javier Martinez Canillas af88e8
+            return false;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    // Write everything out
Javier Martinez Canillas af88e8
     bool res = write_output_files(&quoted, &signature);
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
     return res == true ? 0 : 1;
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
@@ -206,6 +301,10 @@ static bool on_option(char key, char *value) {
Javier Martinez Canillas af88e8
     case 'm':
Javier Martinez Canillas af88e8
          message_path = optarg;
Javier Martinez Canillas af88e8
          break;
Javier Martinez Canillas af88e8
+    case 'p':
Javier Martinez Canillas af88e8
+         pcr_path = optarg;
Javier Martinez Canillas af88e8
+         p_flag = 1;
Javier Martinez Canillas af88e8
+         break;
Javier Martinez Canillas af88e8
     case 'f':
Javier Martinez Canillas af88e8
          sig_format = tpm2_parse_signature_format(optarg);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
@@ -239,11 +338,12 @@ bool tpm2_tool_onstart(tpm2_options **opts) {
Javier Martinez Canillas af88e8
         { "input-session-handle", required_argument, NULL, 'S' },
Javier Martinez Canillas af88e8
         { "signature",            required_argument, NULL, 's' },
Javier Martinez Canillas af88e8
         { "message",              required_argument, NULL, 'm' },
Javier Martinez Canillas af88e8
+        { "pcrs",                 required_argument, NULL, 'p' },
Javier Martinez Canillas af88e8
         { "format",               required_argument, NULL, 'f' },
Javier Martinez Canillas af88e8
         { "sig-hash-algorithm",   required_argument, NULL, 'G' }
Javier Martinez Canillas af88e8
     };
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
-    *opts = tpm2_options_new("k:c:P:l:g:L:S:q:s:m:f:G:", ARRAY_LEN(topts), topts,
Javier Martinez Canillas af88e8
+    *opts = tpm2_options_new("k:c:P:l:g:L:S:q:s:m:p:f:G:", ARRAY_LEN(topts), topts,
Javier Martinez Canillas af88e8
             on_option, NULL, TPM2_OPTIONS_SHOW_USAGE);
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
     return *opts != NULL;
Javier Martinez Canillas af88e8
@@ -270,5 +370,25 @@ int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
Javier Martinez Canillas af88e8
         sessionData.hmac.size = 0;
Javier Martinez Canillas af88e8
     }
Javier Martinez Canillas af88e8
 
Javier Martinez Canillas af88e8
+    if (p_flag) {
Javier Martinez Canillas af88e8
+        if (!G_flag) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Must specify -G if -p is requested.");
Javier Martinez Canillas af88e8
+            return -1;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+        pcr_output = fopen(pcr_path, "wb+");
Javier Martinez Canillas af88e8
+        if (!pcr_output) {
Javier Martinez Canillas af88e8
+            LOG_ERR("Could not open PCR output file \"%s\" error: \"%s\"",
Javier Martinez Canillas af88e8
+                    pcr_path, strerror(errno));
Javier Martinez Canillas af88e8
+            return 1;
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
+    if (!pcr_get_banks(sapi_context, &cap_data, &algs)) {
Javier Martinez Canillas af88e8
+        if (pcr_output) {
Javier Martinez Canillas af88e8
+            fclose(pcr_output);
Javier Martinez Canillas af88e8
+        }
Javier Martinez Canillas af88e8
+        return 1;
Javier Martinez Canillas af88e8
+    }
Javier Martinez Canillas af88e8
+
Javier Martinez Canillas af88e8
     return quote(sapi_context, akHandle, &pcrSelections);
Javier Martinez Canillas af88e8
 }
Javier Martinez Canillas af88e8
-- 
Javier Martinez Canillas af88e8
2.21.0
Javier Martinez Canillas af88e8