diff --git a/Add-ability-to-check-quotes-and-output-PCR-values-fo.patch b/Add-ability-to-check-quotes-and-output-PCR-values-fo.patch
deleted file mode 100644
index 5c6cd2a..0000000
--- a/Add-ability-to-check-quotes-and-output-PCR-values-fo.patch
+++ /dev/null
@@ -1,2007 +0,0 @@
-From 3f9c713d3bff4abf417edf0f74e0b049bfd1b31f Mon Sep 17 00:00:00 2001
-From: jetwhiz <Charles.Munson@ll.mit.edu>
-Date: Fri, 3 May 2019 08:03:45 -0400
-Subject: [PATCH] Add ability to check quotes and output PCR values for
- quotes
-
-Add new tpm2_checkquote tool for checking quotes
-  Pull shared functionality from tpm2_pcrlist into pcr library
-  is_pcr_select_bit_set moved into tpm2_util library
-  Add new functionality to openssl, pcr and util libraries
-The tpm2_quote tool can now output PCR hash lists
-
-Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
----
- CHANGELOG.md                        |   2 +
- Makefile.am                         |   3 +
- lib/pcr.c                           | 232 ++++++++++++++++
- lib/pcr.h                           |  27 ++
- lib/tpm2_openssl.c                  | 163 +++++++++++
- lib/tpm2_openssl.h                  |  57 ++++
- lib/tpm2_util.c                     | 148 ++++++++++
- lib/tpm2_util.h                     |  33 +++
- man/tpm2_checkquote.1.md            |  95 +++++++
- man/tpm2_quote.1.md                 |   9 +-
- test/system/test_tpm2_checkquote.sh |  86 ++++++
- test/system/test_tpm2_quote.sh      |  12 +-
- tools/tpm2_checkquote.c             | 409 ++++++++++++++++++++++++++++
- tools/tpm2_pcrlist.c                | 205 +-------------
- tools/tpm2_quote.c                  | 124 ++++++++-
- 15 files changed, 1398 insertions(+), 207 deletions(-)
- create mode 100644 man/tpm2_checkquote.1.md
- create mode 100755 test/system/test_tpm2_checkquote.sh
- create mode 100644 tools/tpm2_checkquote.c
-
-diff --git a/CHANGELOG.md b/CHANGELOG.md
-index a8e4f39afde..7e83c6b7e6f 100644
---- a/CHANGELOG.md
-+++ b/CHANGELOG.md
-@@ -1,5 +1,7 @@
- ## Changelog
- ### 3.2.0 - next
-+* tpm2_checkquote: Introduce new tool for checking validity of quotes.
-+* tpm2_quote: Add ability to output PCR values for quotes.
- * tpm2_makecredential: add support for executing tool off-TPM.
- * tpm2_pcrreset: introduce new tool for resetting PCRs.
- * tpm2_quote: Fix AK auth password not being used.
-diff --git a/Makefile.am b/Makefile.am
-index 2195537ce01..854c24a03e3 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -59,6 +59,7 @@ LDADD = \
- 
- # keep me sorted
- bin_PROGRAMS = \
-+    tools/tpm2_checkquote \
-     tools/tpm2_activatecredential \
-     tools/tpm2_certify \
-     tools/tpm2_create \
-@@ -145,6 +146,7 @@ lib_libcommon_a_SOURCES = \
- 
- TOOL_SRC := tools/tpm2_tool.c tools/tpm2_tool.h
- 
-+tools_tpm2_checkquote_SOURCES = tools/tpm2_checkquote.c $(TOOL_SRC)
- tools_tpm2_create_SOURCES = tools/tpm2_create.c $(TOOL_SRC)
- tools_tpm2_createprimary_SOURCES = tools/tpm2_createprimary.c $(TOOL_SRC)
- tools_tpm2_getcap_SOURCES = tools/tpm2_getcap.c $(TOOL_SRC)
-@@ -259,6 +261,7 @@ if HAVE_MAN_PAGES
-     man1_MANS := \
-     man/man1/tpm2_activatecredential.1 \
-     man/man1/tpm2_certify.1 \
-+    man/man1/tpm2_checkquote.1 \
-     man/man1/tpm2_create.1 \
-     man/man1/tpm2_createpolicy.1 \
-     man/man1/tpm2_createprimary.1 \
-diff --git a/lib/pcr.c b/lib/pcr.c
-index 5552b336f66..9b00dd6e0e3 100644
---- a/lib/pcr.c
-+++ b/lib/pcr.c
-@@ -33,13 +33,21 @@
- #include <string.h>
- 
- #include <tss2/tss2_sys.h>
-+#include <inttypes.h>
- #include <stdbool.h>
- 
- #include "pcr.h"
- #include "log.h"
-+#include "tpm2_tool.h"
- #include "tpm2_util.h"
- #include "tpm2_alg_util.h"
- 
-+static inline void set_pcr_select_size(TPMS_PCR_SELECTION *pcr_selection,
-+        UINT8 size) {
-+
-+    pcr_selection->sizeofSelect = size;
-+}
-+
- static int pcr_get_id(const char *arg, UINT32 *pcrId)
- {
-     UINT32 n = 0;
-@@ -96,6 +104,111 @@ static bool pcr_parse_selection(const char *str, size_t len, TPMS_PCR_SELECTION
-     return true;
- }
- 
-+static void shrink_pcr_selection(TPML_PCR_SELECTION *s) {
-+
-+    UINT32 i, j;
-+
-+    //seek for the first empty item
-+    for (i = 0; i < s->count; i++)
-+        if (!s->pcrSelections[i].hash)
-+            break;
-+    j = i + 1;
-+
-+    for (; i < s->count; i++) {
-+        if (!s->pcrSelections[i].hash) {
-+            for (; j < s->count; j++)
-+                if (s->pcrSelections[j].hash)
-+                    break;
-+            if (j >= s->count)
-+                break;
-+
-+            memcpy(&s->pcrSelections[i], &s->pcrSelections[j], sizeof(s->pcrSelections[i]));
-+            s->pcrSelections[j].hash = 0;
-+            j++;
-+        }
-+    }
-+
-+    s->count = i;
-+}
-+
-+static void pcr_update_pcr_selections(TPML_PCR_SELECTION *s1, TPML_PCR_SELECTION *s2) {
-+    UINT32 i1, i2, j;
-+    for (i2 = 0; i2 < s2->count; i2++) {
-+        for (i1 = 0; i1 < s1->count; i1++) {
-+            if (s2->pcrSelections[i2].hash != s1->pcrSelections[i1].hash)
-+                continue;
-+
-+            for (j = 0; j < s1->pcrSelections[i1].sizeofSelect; j++)
-+                s1->pcrSelections[i1].pcrSelect[j] &=
-+                        ~s2->pcrSelections[i2].pcrSelect[j];
-+        }
-+    }
-+}
-+
-+static bool pcr_unset_pcr_sections(TPML_PCR_SELECTION *s) {
-+    UINT32 i, j;
-+    for (i = 0; i < s->count; i++) {
-+        for (j = 0; j < s->pcrSelections[i].sizeofSelect; j++) {
-+            if (s->pcrSelections[i].pcrSelect[j]) {
-+                return false;
-+            }
-+        }
-+    }
-+
-+    return true;
-+}
-+
-+bool pcr_print_pcr_struct(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs) {
-+
-+    UINT32 vi = 0, di = 0, i;
-+    bool result = true;
-+
-+    tpm2_tool_output("pcrs:\n");
-+
-+    // Loop through all PCR/hash banks 
-+    for (i = 0; i < pcrSelect->count; i++) {
-+        const char *alg_name = tpm2_alg_util_algtostr(pcrSelect->pcrSelections[i].hash);
-+
-+        tpm2_tool_output("  %s:\n", alg_name);
-+
-+        // Loop through all PCRs in this bank
-+        UINT8 pcr_id;
-+        for (pcr_id = 0; pcr_id < pcrSelect->pcrSelections[i].sizeofSelect * 8; pcr_id++) {
-+            if (!tpm2_util_is_pcr_select_bit_set(&pcrSelect->pcrSelections[i],
-+                    pcr_id)) {
-+                // skip non-selected banks
-+                continue;
-+            }
-+            if (vi >= pcrs->count || di >= pcrs->pcr_values[vi].count) {
-+                LOG_ERR("Something wrong, trying to print but nothing more");
-+                return false;
-+            }
-+
-+            // Print out PCR ID
-+            tpm2_tool_output("    %-2d: 0x", pcr_id);
-+
-+            // Print out current PCR digest value
-+            TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di];
-+            int k;
-+            for (k = 0; k < b->size; k++) {
-+                tpm2_tool_output("%02X", b->buffer[k]);
-+            }
-+            tpm2_tool_output("\n");
-+
-+            if (++di < pcrs->pcr_values[vi].count) {
-+                continue;
-+            }
-+
-+            di = 0;
-+            if (++vi < pcrs->count) {
-+                continue;
-+            }
-+        }
-+    }
-+
-+    return result;
-+}
-+
- 
- bool pcr_parse_selections(const char *arg, TPML_PCR_SELECTION *pcrSels) {
-     const char *strLeft = arg;
-@@ -194,3 +307,122 @@ TSS2_RC get_max_supported_pcrs(TSS2_SYS_CONTEXT *sapi_context, UINT32 *max_pcrs)
- 
-     return TPM2_RC_SUCCESS;
- }
-+
-+bool pcr_get_banks(TSS2_SYS_CONTEXT *sapi_context, TPMS_CAPABILITY_DATA *capability_data, tpm2_algorithm *algs) {
-+
-+    TPMI_YES_NO more_data;
-+    UINT32 rval;
-+
-+    rval = TSS2_RETRY_EXP(Tss2_Sys_GetCapability(sapi_context, no_argument, TPM2_CAP_PCRS, no_argument, required_argument,
-+            &more_data, capability_data, 0));
-+    if (rval != TPM2_RC_SUCCESS) {
-+        LOG_ERR(
-+                "GetCapability: Get PCR allocation status Error. TPM Error:0x%x......",
-+                rval);
-+        return false;
-+    }
-+
-+    unsigned i;
-+
-+    // If the TPM support more bank algorithm that we currently
-+    // able to manage, throw an error
-+    if (capability_data->data.assignedPCR.count > sizeof(algs->alg)) {
-+        LOG_ERR("Current implementation does not support more than %zu banks, "
-+                "got %" PRIu32 " banks supported by TPM", 
-+                sizeof(algs->alg), 
-+                capability_data->data.assignedPCR.count);
-+        return false;
-+    }
-+
-+    for (i = 0; i < capability_data->data.assignedPCR.count; i++) {
-+        algs->alg[i] =
-+                capability_data->data.assignedPCR.pcrSelections[i].hash;
-+    }
-+    algs->count = capability_data->data.assignedPCR.count;
-+
-+    return true;
-+}
-+
-+bool pcr_init_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel, TPMI_ALG_HASH alg_id) {
-+
-+    UINT32 i, j;
-+
-+    pcr_sel->count = 0;
-+
-+    for (i = 0; i < cap_data->data.assignedPCR.count; i++) {
-+        if (alg_id && (cap_data->data.assignedPCR.pcrSelections[i].hash != alg_id))
-+            continue;
-+        pcr_sel->pcrSelections[pcr_sel->count].hash = cap_data->data.assignedPCR.pcrSelections[i].hash;
-+        set_pcr_select_size(&pcr_sel->pcrSelections[pcr_sel->count], cap_data->data.assignedPCR.pcrSelections[i].sizeofSelect);
-+        for (j = 0; j < pcr_sel->pcrSelections[pcr_sel->count].sizeofSelect; j++)
-+            pcr_sel->pcrSelections[pcr_sel->count].pcrSelect[j] = cap_data->data.assignedPCR.pcrSelections[i].pcrSelect[j];
-+        pcr_sel->count++;
-+    }
-+
-+    if (pcr_sel->count == 0)
-+        return false;
-+
-+    return true;
-+}
-+
-+bool pcr_check_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel) {
-+
-+    UINT32 i, j, k;
-+
-+    for (i = 0; i < pcr_sel->count; i++) {
-+        for (j = 0; j < cap_data->data.assignedPCR.count; j++) {
-+            if (pcr_sel->pcrSelections[i].hash == cap_data->data.assignedPCR.pcrSelections[j].hash) {
-+                for (k = 0; k < pcr_sel->pcrSelections[i].sizeofSelect; k++)
-+                    pcr_sel->pcrSelections[i].pcrSelect[k] &= cap_data->data.assignedPCR.pcrSelections[j].pcrSelect[k];
-+                break;
-+            }
-+        }
-+
-+        if (j >= cap_data->data.assignedPCR.count) {
-+            const char *alg_name = tpm2_alg_util_algtostr(pcr_sel->pcrSelections[i].hash);
-+            LOG_WARN("Ignore unsupported bank/algorithm: %s(0x%04x)", alg_name, pcr_sel->pcrSelections[i].hash);
-+            pcr_sel->pcrSelections[i].hash = 0; //mark it as to be removed
-+        }
-+    }
-+
-+    shrink_pcr_selection(pcr_sel);
-+    if (pcr_sel->count == 0)
-+        return false;
-+
-+    return true;
-+}
-+
-+bool pcr_read_pcr_values(TSS2_SYS_CONTEXT *sapi_context, TPML_PCR_SELECTION *pcrSelections, tpm2_pcrs *pcrs) {
-+
-+    TPML_PCR_SELECTION pcr_selection_tmp;
-+    TPML_PCR_SELECTION pcr_selection_out;
-+    UINT32 pcr_update_counter;
-+
-+    //1. prepare pcrSelectionIn with g_pcrSelections
-+    memcpy(&pcr_selection_tmp, pcrSelections, sizeof(pcr_selection_tmp));
-+
-+    //2. call pcr_read
-+    pcrs->count = 0;
-+    do {
-+        UINT32 rval = TSS2_RETRY_EXP(Tss2_Sys_PCR_Read(sapi_context, no_argument, &pcr_selection_tmp,
-+                &pcr_update_counter, &pcr_selection_out,
-+                &pcrs->pcr_values[pcrs->count], 0));
-+
-+        if (rval != TPM2_RC_SUCCESS) {
-+            LOG_ERR("read pcr failed. tpm error 0x%0x", rval);
-+            return -1;
-+        }
-+
-+        //3. unmask pcrSelectionOut bits from pcrSelectionIn
-+        pcr_update_pcr_selections(&pcr_selection_tmp, &pcr_selection_out);
-+
-+        //4. goto step 2 if pcrSelctionIn still has bits set
-+    } while (++pcrs->count < sizeof(pcrs->pcr_values) && !pcr_unset_pcr_sections(&pcr_selection_tmp));
-+
-+    if (pcrs->count >= sizeof(pcrs->pcr_values) && !pcr_unset_pcr_sections(&pcr_selection_tmp)) {
-+        LOG_ERR("too much pcrs to get! try to split into multiple calls...");
-+        return false;
-+    }
-+
-+    return true;
-+}
-diff --git a/lib/pcr.h b/lib/pcr.h
-index ad6946b3c04..82d5dd696d4 100644
---- a/lib/pcr.h
-+++ b/lib/pcr.h
-@@ -35,8 +35,35 @@
- 
- #include <tss2/tss2_sys.h>
- 
-+typedef struct tpm2_algorithm tpm2_algorithm;
-+struct tpm2_algorithm {
-+    int count;
-+    TPMI_ALG_HASH alg[TPM2_NUM_PCR_BANKS];
-+};
-+
-+typedef struct tpm2_pcrs tpm2_pcrs;
-+struct tpm2_pcrs {
-+    size_t count;
-+    TPML_DIGEST pcr_values[TPM2_MAX_PCRS];
-+};
-+
-+/**
-+ * Echo out all PCR banks according to g_pcrSelection & g_pcrs->.
-+ * @param pcrSelect
-+ *  Description of which PCR registers are selected.
-+ * @param pcrs
-+ *  Struct containing PCR digests.
-+ * @return
-+ *  True on success, false otherwise.
-+ */
-+bool pcr_print_pcr_struct(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs);
-+
- bool pcr_parse_selections(const char *arg, TPML_PCR_SELECTION *pcrSels);
- bool pcr_parse_list(const char *str, size_t len, TPMS_PCR_SELECTION *pcrSel);
- TSS2_RC get_max_supported_pcrs(TSS2_SYS_CONTEXT *sapi_context, UINT32 *max_pcrs);
-+bool pcr_get_banks(TSS2_SYS_CONTEXT *sapi_context, TPMS_CAPABILITY_DATA *capability_data, tpm2_algorithm *algs);
-+bool pcr_init_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel, TPMI_ALG_HASH alg_id);
-+bool pcr_check_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel);
-+bool pcr_read_pcr_values(TSS2_SYS_CONTEXT *sapi_context, TPML_PCR_SELECTION *pcrSelections, tpm2_pcrs *pcrs);
- 
- #endif /* SRC_PCR_H_ */
-diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c
-index 0bfc95bd1ef..8d7314cba8e 100644
---- a/lib/tpm2_openssl.c
-+++ b/lib/tpm2_openssl.c
-@@ -44,9 +44,26 @@
- #include "files.h"
- #include "log.h"
- #include "tpm2_alg_util.h"
-+#include "tpm_kdfa.h"
- #include "tpm2_openssl.h"
- #include "tpm2_util.h"
- 
-+int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm) {
-+
-+    switch (algorithm) {
-+    case TPM2_ALG_SHA1:
-+        return NID_sha1;
-+    case TPM2_ALG_SHA256:
-+        return NID_sha256;
-+    case TPM2_ALG_SHA384:
-+        return NID_sha384;
-+    case TPM2_ALG_SHA512:
-+        return NID_sha512;
-+    default:
-+        return NID_sha256;
-+    }
-+    /* no return, not possible */
-+}
- 
- const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm) {
- 
-@@ -122,6 +139,127 @@ void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx) {
- #endif
- }
- 
-+bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg,
-+        BYTE *buffer, UINT16 length, TPM2B_DIGEST *digest) {
-+
-+    bool result = false;
-+
-+    const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg);
-+    if (!md) {
-+        return false;
-+    }
-+
-+    EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
-+    if (!mdctx) {
-+        LOG_ERR("%s", get_openssl_err());
-+        return false;
-+    }
-+
-+    int rc = EVP_DigestInit_ex(mdctx, md, NULL);
-+    if (!rc) {
-+        LOG_ERR("%s", get_openssl_err());
-+        goto out;
-+    }
-+
-+    rc = EVP_DigestUpdate(mdctx, buffer, length);
-+    if (!rc) {
-+        LOG_ERR("%s", get_openssl_err());
-+        goto out;
-+    }
-+
-+    unsigned size = EVP_MD_size(md);
-+    rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size);
-+    if (!rc) {
-+        LOG_ERR("%s", get_openssl_err());
-+        goto out;
-+    }
-+
-+    digest->size = size;
-+
-+    result = true;
-+
-+out:
-+    EVP_MD_CTX_destroy(mdctx);
-+    return result;
-+}
-+
-+// show all PCR banks according to g_pcrSelection & g_pcrs->
-+bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg, 
-+                TPML_PCR_SELECTION *pcrSelect, 
-+                tpm2_pcrs *pcrs, TPM2B_DIGEST *digest) {
-+
-+    UINT32 vi = 0, di = 0, i;
-+    bool result = false;
-+
-+    const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(hashAlg);
-+    if (!md) {
-+        return false;
-+    }
-+
-+    EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
-+    if (!mdctx) {
-+        LOG_ERR("%s", get_openssl_err());
-+        return false;
-+    }
-+
-+    int rc = EVP_DigestInit_ex(mdctx, md, NULL);
-+    if (!rc) {
-+        LOG_ERR("%s", get_openssl_err());
-+        goto out;
-+    }
-+
-+    // Loop through all PCR/hash banks 
-+    for (i = 0; i < pcrSelect->count; i++) {
-+
-+        // Loop through all PCRs in this bank
-+        UINT8 pcr_id;
-+        for (pcr_id = 0; pcr_id < pcrSelect->pcrSelections[i].sizeofSelect * 8; pcr_id++) {
-+            if (!tpm2_util_is_pcr_select_bit_set(&pcrSelect->pcrSelections[i],
-+                    pcr_id)) {
-+                // skip non-selected banks
-+                continue;
-+            }
-+            if (vi >= pcrs->count || di >= pcrs->pcr_values[vi].count) {
-+                LOG_ERR("Something wrong, trying to print but nothing more");
-+                goto out;
-+            }
-+
-+            // Update running digest (to compare with quote)
-+            TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di];
-+            rc = EVP_DigestUpdate(mdctx, b->buffer, b->size);
-+            if (!rc) {
-+                LOG_ERR("%s", get_openssl_err());
-+                goto out;
-+            }
-+
-+            if (++di < pcrs->pcr_values[vi].count) {
-+                continue;
-+            }
-+
-+            di = 0;
-+            if (++vi < pcrs->count) {
-+                continue;
-+            }
-+        }
-+    }
-+
-+    // Finalize running digest
-+    unsigned size = EVP_MD_size(md);
-+    rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size);
-+    if (!rc) {
-+        LOG_ERR("%s", get_openssl_err());
-+        goto out;
-+    }
-+
-+    digest->size = size;
-+
-+    result = true;
-+
-+out:
-+    EVP_MD_CTX_destroy(mdctx);
-+    return result;
-+}
-+
- digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) {
- 
-     switch(halg) {
-@@ -160,3 +298,28 @@ digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) {
-  */
- 
- typedef bool (*pfn_ossl_pw_handler)(const char *passin, char **pass);
-+
-+
-+RSA *tpm2_openssl_get_public_RSA_from_pem(FILE *f, const char *path) {
-+
-+    /*
-+     * Public PEM files appear in two formats:
-+     * 1. PEM format, read with PEM_read_RSA_PUBKEY
-+     * 2. PKCS#1 format, read with PEM_read_RSAPublicKey
-+     *
-+     * See:
-+     *  - https://stackoverflow.com/questions/7818117/why-i-cant-read-openssl-generated-rsa-pub-key-with-pem-read-rsapublickey
-+     */
-+    RSA *pub = PEM_read_RSA_PUBKEY(f, NULL, NULL, NULL);
-+    if (!pub) {
-+        pub = PEM_read_RSAPublicKey(f, NULL, NULL, NULL);
-+    }
-+
-+    if (!pub) {
-+         ERR_print_errors_fp (stderr);
-+         LOG_ERR("Reading public PEM file \"%s\" failed", path);
-+         return NULL;
-+    }
-+
-+    return pub;
-+}
-diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h
-index d749cb350ac..d3f4a0d7a32 100644
---- a/lib/tpm2_openssl.h
-+++ b/lib/tpm2_openssl.h
-@@ -34,6 +34,8 @@
- #include <openssl/hmac.h>
- #include <openssl/rsa.h>
- 
-+#include "pcr.h"
-+
- #if (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) /* OpenSSL 1.1.0 */
- #define LIB_TPM2_OPENSSL_OPENSSL_PRE11
- #endif
-@@ -60,6 +62,16 @@ int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
-  */
- typedef unsigned char *(*digester)(const unsigned char *d, size_t n, unsigned char *md);
- 
-+/**
-+
-+ * Get an openssl hash algorithm ID from a tpm hashing algorithm ID.
-+ * @param algorithm
-+ *  The tpm algorithm to get the corresponding openssl version of.
-+ * @return
-+ *  The openssl hash algorithm id.
-+ */
-+int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm);
-+
- /**
-  * Get an openssl message digest from a tpm hashing algorithm.
-  * @param algorithm
-@@ -86,6 +98,39 @@ EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void);
-  */
- void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx);
- 
-+/**
-+ * Hash a byte buffer.
-+ * @param halg
-+ *  The hashing algorithm to use.
-+ * @param buffer
-+ *  The byte buffer to be hashed.
-+ * @param length
-+ *  The length of the byte buffer to hash.
-+^ * @param digest
-+^ *  The result of hashing digests with halg.
-+ * @return
-+ *  true on success, false on error.
-+ */
-+bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg,
-+        BYTE *buffer, UINT16 length, TPM2B_DIGEST *digest);
-+
-+/**
-+ * Hash a list of PCR digests, supporting multiple banks.
-+ * @param halg
-+ *  The hashing algorithm to use.
-+ * @param pcrSelect
-+ *  The list that specifies which PCRs are selected.
-+ * @param pcrs
-+ *  The list of PCR banks, each containing a list of PCR digests to hash.
-+^ * @param digest
-+^ *  The result of hashing digests with halg.
-+ * @return
-+ *  true on success, false on error.
-+ */
-+bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg, 
-+        TPML_PCR_SELECTION *pcrSelect, 
-+        tpm2_pcrs *pcrs, TPM2B_DIGEST *digest);
-+
- /**
-  * Returns a function pointer capable of performing the
-  * given digest from a TPMI_HASH_ALG.
-@@ -105,4 +150,16 @@ enum tpm2_openssl_load_rc {
- };
- 
- 
-+/**
-+ * Retrieves a public portion of an RSA key from a PEM file.
-+ *
-+ * @param f
-+ *  The FILE object that is open for reading the path.
-+ * @param path
-+ *  The path to load from.
-+ * @return
-+ *  The public structure.
-+ */
-+RSA* tpm2_openssl_get_public_RSA_from_pem(FILE *f, const char *path);
-+
- #endif /* LIB_TPM2_OPENSSL_H_ */
-diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
-index 57d6c762a70..edfda4a8b0b 100644
---- a/lib/tpm2_util.c
-+++ b/lib/tpm2_util.c
-@@ -41,6 +41,154 @@
- #include "tpm2_tool.h"
- #include "tpm2_util.h"
- 
-+
-+bool tpm2_util_get_digest_from_quote(TPM2B_ATTEST *quoted, TPM2B_DIGEST *digest, TPM2B_DATA *extraData) {
-+    TPM2_GENERATED magic;
-+    TPMI_ST_ATTEST type;
-+    UINT16 nameSize = 0;
-+    UINT32 i = 0;
-+
-+    // Ensure required headers are at least there
-+    if (quoted->size < 6) {
-+        LOG_ERR("Malformed TPM2B_ATTEST headers");
-+        return false;
-+    }
-+
-+    memcpy(&magic, &quoted->attestationData[i], 4);i += 4;
-+    memcpy(&type, &quoted->attestationData[i], 2);i += 2;
-+    if (!tpm2_util_is_big_endian()) {
-+        magic = tpm2_util_endian_swap_32(magic);
-+        type = tpm2_util_endian_swap_16(type);
-+    }
-+
-+    if (magic != TPM2_GENERATED_VALUE) {
-+        LOG_ERR("Malformed TPM2_GENERATED magic value");
-+        return false;
-+    }
-+
-+    if (type != TPM2_ST_ATTEST_QUOTE) {
-+        LOG_ERR("Malformed TPMI_ST_ATTEST quote value");
-+        return false;
-+    }
-+
-+    // Qualified signer name (skip)
-+    if (i+2 >= quoted->size) {
-+        LOG_ERR("Malformed TPM2B_NAME value");
-+        return false;
-+    }
-+    memcpy(&nameSize, &quoted->attestationData[i], 2);i += 2;
-+    if (!tpm2_util_is_big_endian()) {
-+        nameSize = tpm2_util_endian_swap_16(nameSize);
-+    }
-+    i += nameSize;
-+
-+    // Extra data (skip)
-+    if (i+2 >= quoted->size) {
-+        LOG_ERR("Malformed TPM2B_DATA value");
-+        return false;
-+    }
-+    memcpy(&extraData->size, &quoted->attestationData[i], 2);i += 2;
-+    if (!tpm2_util_is_big_endian()) {
-+        extraData->size = tpm2_util_endian_swap_16(extraData->size);
-+    }
-+    if (extraData->size+i > quoted->size) {
-+        LOG_ERR("Malformed extraData TPM2B_DATA value");
-+        return false;
-+    }
-+    memcpy(&extraData->buffer, &quoted->attestationData[i], extraData->size);i += extraData->size;
-+
-+    // Clock info (skip)
-+    i += 17;
-+    if (i >= quoted->size) {
-+        LOG_ERR("Malformed TPMS_CLOCK_INFO value");
-+        return false;
-+    }
-+
-+    // Firmware info (skip)
-+    i += 8;
-+    if (i >= quoted->size) {
-+        LOG_ERR("Malformed firmware version value");
-+        return false;
-+    }
-+
-+    // PCR select info
-+    UINT8 sos;
-+    TPMI_ALG_HASH hashAlg;
-+    UINT32 pcrSelCount = 0, j = 0;
-+    if (i+4 >= quoted->size) {
-+        LOG_ERR("Malformed TPML_PCR_SELECTION value");
-+        return false;
-+    }
-+    memcpy(&pcrSelCount, &quoted->attestationData[i], 4);i += 4;
-+    if (!tpm2_util_is_big_endian()) {
-+        pcrSelCount = tpm2_util_endian_swap_32(pcrSelCount);
-+    }
-+    for (j = 0; j < pcrSelCount; j++) {
-+        // Hash 
-+        if (i+2 >= quoted->size) {
-+            LOG_ERR("Malformed TPMS_PCR_SELECTION value");
-+            return false;
-+        }
-+        memcpy(&hashAlg, &quoted->attestationData[i], 2);i += 2;
-+        if (!tpm2_util_is_big_endian()) {
-+            hashAlg = tpm2_util_endian_swap_16(hashAlg);
-+        }
-+
-+        // SizeOfSelected
-+        if (i+1 >= quoted->size) {
-+            LOG_ERR("Malformed TPMS_PCR_SELECTION value");
-+            return false;
-+        }
-+        memcpy(&sos, &quoted->attestationData[i], 1);i += 1;
-+
-+        // PCR Select (skip)
-+        i += sos;
-+        if (i >= quoted->size) {
-+            LOG_ERR("Malformed TPMS_PCR_SELECTION value");
-+            return false;
-+        }
-+    }
-+
-+    // Digest
-+    if (i+2 >= quoted->size) {
-+        LOG_ERR("Malformed TPM2B_DIGEST value");
-+        return false;
-+    }
-+    memcpy(&digest->size, &quoted->attestationData[i], 2);i += 2;
-+    if (!tpm2_util_is_big_endian()) {
-+        digest->size = tpm2_util_endian_swap_16(digest->size);
-+    }
-+
-+    if (digest->size+i > quoted->size) {
-+        LOG_ERR("Malformed TPM2B_DIGEST value");
-+        return false;
-+    }
-+    memcpy(&digest->buffer, &quoted->attestationData[i], digest->size);
-+
-+    return true;
-+}
-+
-+// verify that the quote digest equals the digest we calculated
-+bool tpm2_util_verify_digests(TPM2B_DIGEST *quoteDigest, TPM2B_DIGEST *pcrDigest) {
-+
-+    // Sanity check -- they should at least be same size!
-+    if (quoteDigest->size != pcrDigest->size) {
-+        LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!");
-+        return false;
-+    }
-+
-+    // Compare running digest with quote's digest
-+    int k;
-+    for (k = 0; k < quoteDigest->size; k++) {
-+        if (quoteDigest->buffer[k] != pcrDigest->buffer[k]) {
-+            LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!");
-+            return false;
-+        }
-+    }
-+
-+    return true;
-+}
-+
- bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append) {
- 
-     if (!result || !append) {
-diff --git a/lib/tpm2_util.h b/lib/tpm2_util.h
-index e803dc1c30e..8b77c9e5374 100644
---- a/lib/tpm2_util.h
-+++ b/lib/tpm2_util.h
-@@ -111,6 +111,30 @@ struct TPM2B {
- 
- int tpm2_util_hex_to_byte_structure(const char *inStr, UINT16 *byteLenth, BYTE *byteBuffer);
- 
-+/**
-+ * Pulls the TPM2B_DIGEST out of a TPM2B_ATTEST quote.
-+ * @param quoted
-+ *  The attestation quote structure.
-+^ * @param digest
-+^ *  The digest from the quote.
-+^ * @param extraData
-+^ *  The extraData from the quote.
-+ * @return
-+ *  True on success, false otherwise.
-+ */
-+bool tpm2_util_get_digest_from_quote(TPM2B_ATTEST *quoted, TPM2B_DIGEST *digest, TPM2B_DATA *extraData);
-+
-+/**
-+ * Compares two digests to ensure they are equal (for validation).
-+ * @param quoteDigest
-+ *  The digest from the quote.
-+ * @param pcrDigest
-+ *  The digest calculated off-TMP from the PCRs.
-+ * @return
-+ *  True on success, false otherwise.
-+ */
-+bool tpm2_util_verify_digests(TPM2B_DIGEST *quoteDigest, TPM2B_DIGEST *pcrDigest);
-+
- /**
-  * Appends a TPM2B_DIGEST buffer to a TPM2B_MAX buffer.
-  * @param result
-@@ -170,6 +194,15 @@ static inline void tpm2_util_print_tpm2b(TPM2B *buffer) {
- 
- void tpm2_util_print_tpm2b(TPM2B *buffer);
- 
-+/**
-+ * Determines if given PCR value is selected in TPMS_PCR_SELECTION structure.
-+ * @param pcr_selection the TPMS_PCR_SELECTION structure to check pcr against.
-+ * @param pcr the PCR ID to check selection status of.
-+ */
-+static inline bool tpm2_util_is_pcr_select_bit_set(TPMS_PCR_SELECTION *pcr_selection, UINT32 pcr) {
-+    return (pcr_selection->pcrSelect[((pcr) / 8)] & (1 << ((pcr) % 8)));
-+}
-+
- /**
-  * Copies a tpm2b from dest to src and clears dest if src is NULL.
-  * If src is NULL, it is a NOP.
-diff --git a/man/tpm2_checkquote.1.md b/man/tpm2_checkquote.1.md
-new file mode 100644
-index 00000000000..00bb4bee9a7
---- /dev/null
-+++ b/man/tpm2_checkquote.1.md
-@@ -0,0 +1,95 @@
-+% tpm2_checkquote(1) tpm2-tools | General Commands Manual
-+%
-+% JANUARY 2019
-+
-+# NAME
-+
-+**tpm2_checkquote**(1) - Validates a quote provided by a TPM.
-+
-+# SYNOPSIS
-+
-+**tpm2_checkquote** [*OPTIONS*]
-+
-+# DESCRIPTION
-+
-+**tpm2_checkquote**(1) - Uses the public portion of the provided key to validate a quote 
-+generated by a TPM. This will validate the signature against the quote message and, if 
-+provided, verify that the qualifying data and PCR values match those in the quote.
-+
-+# OPTIONS
-+
-+  * **-c**, **--key-context**=_KEY\_CONTEXT\_OBJECT_:
-+
-+    Context object for the key context used for the operation. Either a file
-+    or a handle number. See section "Context Object Format".
-+
-+  * **-G**, **--halg**=_HASH\_ALGORITHM_:
-+
-+    The hash algorithm used to digest the message.
-+    Algorithms should follow the "formatting standards", see section
-+    "Algorithm Specifiers".
-+    Also, see section "Supported Hash Algorithms" for a list of supported hash
-+    algorithms.
-+
-+  * **-m**, **--message**=_MSG\_FILE_:
-+
-+    The quote message that makes up the data that is signed by the TPM.
-+
-+  * **-s**, **--sig**=_SIG\_FILE_:
-+
-+    The input signature file of the signature to be validated.
-+
-+  * **-f**, **--format**:
-+
-+    Set the input signature file to a specified format. The default is the TPM2.0 **TPMT_SIGNATURE**
-+    data format, however different schemes can be selected if the data came from an external
-+    source like OpenSSL. The tool currently only supports rsassa.
-+
-+    Algorithms should follow the "formatting standards", see section
-+    "Algorithm Specifiers".
-+    Also, see section "Supported Signing Schemes" for a list of supported hash
-+    algorithms.
-+
-+  * **-p**, **--pcrs**:
-+
-+    PCR output file, optional, records the list of PCR values that were included 
-+    in the quote. 
-+
-+  * **-q**, **--qualify-data**:
-+
-+    Data given as a hex string that was used to qualify the quote. This is typically
-+    used to add a nonce against replay attacks.
-+
-+[common options](common/options.md)
-+
-+[common tcti options](common/tcti.md)
-+
-+[context object format](common/ctxobj.md)
-+
-+[authorization formatting](common/password.md)
-+
-+[supported hash algorithms](common/hash.md)
-+
-+[supported signing schemes](common/signschemes.md)
-+
-+[algorithm specifiers](common/alg.md)
-+
-+# EXAMPLES
-+
-+## Generate a quote with a TPM, then verify it
-+```
-+tpm2_createprimary -H e -g sha256 -G rsa -C primary.ctx
-+tpm2_create -g sha256 -G rsa -u ak.pub -r ak.priv -c primary.ctx
-+tpm2_load -c primary.ctx  -u ak.pub -r ak.priv -n ak.name -C ak.ctx
-+tpm2_readpublic -c ak.ctx -o akpub.pem -f pem
-+
-+tpm2_quote -c ak.ctx -L sha256:15,16,22 -q abc123 -m quote.out -s sig.out -p pcrs.out -G sha256
-+
-+tpm2_checkquote -c akpub.pem -m quote.out -s sig.out -p pcrs.out -G sha256 -q abc123
-+```
-+
-+# RETURNS
-+
-+0 on success or 1 on failure.
-+
-+[footer](common/footer.md)
-diff --git a/man/tpm2_quote.1.md b/man/tpm2_quote.1.md
-index 88c37e040c1..491848201d9 100644
---- a/man/tpm2_quote.1.md
-+++ b/man/tpm2_quote.1.md
-@@ -53,6 +53,13 @@
- 
-     Format selection for the signature output file. See section "Signature Format Specifiers".
- 
-+  * **-p**, **--pcrs**:
-+
-+    PCR output file, optional, records the list of PCR values as defined
-+    by **-l** or **-L**.  Note that only the digest of these values is stored in the
-+    signed quote message -- these values themselves are not signed or
-+    stored in the message.
-+
-   * **-q**, **--qualify-data**:
- 
-     Data given as a Hex string to qualify the  quote, optional. This is typically
-@@ -63,7 +70,7 @@
- 
-   * **-G**, **--sig-hash-algorithm**:
- 
--    Hash algorithm for signature.
-+    Hash algorithm for signature. Required if **-p** is given.
- 
- [common options](common/options.md)
- 
-diff --git a/test/system/test_tpm2_checkquote.sh b/test/system/test_tpm2_checkquote.sh
-new file mode 100755
-index 00000000000..670e3a737d1
---- /dev/null
-+++ b/test/system/test_tpm2_checkquote.sh
-@@ -0,0 +1,86 @@
-+#!/bin/bash
-+#;**********************************************************************;
-+#
-+# Copyright (c) 2019 Massachusetts Institute of Technology.
-+# All rights reserved.
-+#
-+# Redistribution and use in source and binary forms, with or without
-+# modification, are permitted provided that the following conditions are met:
-+#
-+# 1. Redistributions of source code must retain the above copyright notice,
-+# this list of conditions and the following disclaimer.
-+#
-+# 2. Redistributions in binary form must reproduce the above copyright notice,
-+# this list of conditions and the following disclaimer in the documentation
-+# and/or other materials provided with the distribution.
-+#
-+# 3. Neither the name of Intel Corporation nor the names of its contributors
-+# may be used to endorse or promote products derived from this software without
-+# specific prior written permission.
-+#
-+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+# THE POSSIBILITY OF SUCH DAMAGE.
-+#;**********************************************************************;
-+
-+source test_helpers.sh
-+
-+alg_primary_obj=sha256
-+alg_primary_key=rsa
-+alg_create_obj=sha256
-+alg_create_key=rsa
-+
-+file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key"
-+file_quote_key_pub=opu_"$alg_create_obj"_"$alg_create_key"
-+file_quote_key_priv=opr_"$alg_create_obj"_"$alg_create_key"
-+file_quote_key_name=name.load_"$alg_primary_obj"_"$alg_primary_key"-"$alg_create_obj"_"$alg_create_key"
-+file_quote_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-"$alg_create_obj"_"$alg_create_key"
-+output_ak_pub_pem=akpub.pem
-+output_quote=quote.out
-+output_quotesig=quotesig.out
-+output_quotepcr=quotepcr.out
-+
-+maxdigest=$(tpm2_getcap -c properties-fixed | grep TPM_PT_MAX_DIGEST | sed -r -e 's/.*(0x[0-9a-f]+)/\1/g')
-+if ! [[ "$maxdigest" =~ ^(0x)*[0-9]+$ ]] ; then
-+ echo "error: not a number, got: \"$maxdigest\"" >&2
-+ exit 1
-+fi
-+
-+nonce=12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde
-+nonce=${nonce:0:2*$maxdigest}
-+
-+cleanup() {
-+  rm -f $file_primary_key_ctx $file_quote_key_pub $file_quote_key_priv \
-+        $file_quote_key_name $file_quote_key_ctx $output_ak_pub_pem \
-+        $output_quote $output_quotesig $output_quotepcr
-+}
-+trap cleanup EXIT
-+
-+cleanup
-+
-+
-+tpm2_takeownership -c
-+
-+# Key generation
-+tpm2_createprimary -Q -H e -g $alg_primary_obj -G $alg_primary_key -C $file_primary_key_ctx
-+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
-+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
-+
-+# Get the PEM version of pub ak cert
-+tpm2_readpublic -Q -c $file_quote_key_ctx -o $output_ak_pub_pem -f pem
-+
-+# Quoting
-+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
-+
-+# Verify quote
-+tpm2_checkquote -Q -c $output_ak_pub_pem -m $output_quote -s $output_quotesig -p $output_quotepcr -G $alg_primary_obj -q $nonce
-+
-+exit 0
-diff --git a/test/system/test_tpm2_quote.sh b/test/system/test_tpm2_quote.sh
-index 231bed326ec..aa06a3d7040 100755
---- a/test/system/test_tpm2_quote.sh
-+++ b/test/system/test_tpm2_quote.sh
-@@ -52,6 +52,8 @@ Handle_ek_quote=0x81010017
- Handle_ak_quote2=0x81010018
- Handle_ak_quote3=0x81010019
- 
-+toss_out=junk.out
-+
- maxdigest=$(tpm2_getcap -c properties-fixed | grep TPM_PT_MAX_DIGEST | sed -r -e 's/.*(0x[0-9a-f]+)/\1/g')
- if ! [[ "$maxdigest" =~ ^(0x)*[0-9]+$ ]] ; then
-  echo "error: not a number, got: \"$maxdigest\"" >&2
-@@ -69,7 +71,7 @@ trap onerror ERR
- 
- cleanup() {
-     rm -f $file_primary_key_ctx $file_quote_key_pub $file_quote_key_priv \
--    $file_quote_key_name $file_quote_key_ctx ek.pub2 ak.pub2 ak.name_2 \
-+    $file_quote_key_name $file_quote_key_ctx $toss_out ek.pub2 ak.pub2 ak.name_2 \
- 
-     tpm2_evictcontrol -Q -Ao -H $Handle_ek_quote 2>/dev/null || true
-     tpm2_evictcontrol -Q -Ao -H $Handle_ak_quote 2>/dev/null || true
-@@ -90,21 +92,21 @@ tpm2_load -Q -c $file_primary_key_ctx  -u $file_quote_key_pub  -r $file_quote_ke
- 
- tpm2_quote -Q -c $file_quote_key_ctx  -g $alg_quote -l 16,17,18 -q $nonce
- 
--tpm2_quote -Q -c $file_quote_key_ctx  -L $alg_quote:16,17,18+$alg_quote1:16,17,18 -q $nonce
-+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
- 
- #####handle testing
- tpm2_evictcontrol -Q -A o -c $file_quote_key_ctx -S $Handle_ak_quote
- 
--tpm2_quote -Q -k $Handle_ak_quote  -g $alg_quote -l 16,17,18 -q $nonce
-+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
- 
--tpm2_quote -Q -k $Handle_ak_quote  -L $alg_quote:16,17,18+$alg_quote1:16,17,18 -q $nonce
-+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
- 
- #####AK
- tpm2_getpubek -Q -H  $Handle_ek_quote -g 0x01 -f ek.pub2
- 
- tpm2_getpubak -Q -E  $Handle_ek_quote -k  $Handle_ak_quote2 -f ak.pub2 -n ak.name_2
- 
--tpm2_quote -Q -k $Handle_ak_quote -g $alg_quote -l 16,17,18 -q $nonce
-+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
- 
- #####AK with password
- tpm2_getpubak -Q -E  $Handle_ek_quote -k  $Handle_ak_quote3 -f ak.pub2 -n ak.name_2 -P abc123
-diff --git a/tools/tpm2_checkquote.c b/tools/tpm2_checkquote.c
-new file mode 100644
-index 00000000000..0efd7f3ca88
---- /dev/null
-+++ b/tools/tpm2_checkquote.c
-@@ -0,0 +1,409 @@
-+//**********************************************************************;
-+// Copyright (c) 2019 Massachusetts Institute of Technology.
-+// All rights reserved.
-+//
-+// Redistribution and use in source and binary forms, with or without
-+// modification, are permitted provided that the following conditions are met:
-+//
-+// 1. Redistributions of source code must retain the above copyright notice,
-+// this list of conditions and the following disclaimer.
-+//
-+// 2. Redistributions in binary form must reproduce the above copyright notice,
-+// this list of conditions and the following disclaimer in the documentation
-+// and/or other materials provided with the distribution.
-+//
-+// 3. Neither the name of Intel Corporation nor the names of its contributors
-+// may be used to endorse or promote products derived from this software without
-+// specific prior written permission.
-+//
-+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+// THE POSSIBILITY OF SUCH DAMAGE.
-+//**********************************************************************;
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <errno.h>
-+
-+#include <tss2/tss2_esys.h>
-+
-+#include <openssl/rsa.h>
-+
-+#include "files.h"
-+#include "log.h"
-+#include "pcr.h"
-+#include "tpm2_alg_util.h"
-+#include "conversion.h"
-+#include "tpm_hash.h"
-+#include "tpm2_openssl.h"
-+#include "tpm2_options.h"
-+#include "tpm2_tool.h"
-+#include "tpm2_util.h"
-+
-+typedef struct tpm2_verifysig_ctx tpm2_verifysig_ctx;
-+struct tpm2_verifysig_ctx {
-+    union {
-+        struct {
-+            UINT8 halg :1;
-+            UINT8 msg :1;
-+            UINT8 sig :1;
-+            UINT8 pcr :1;
-+            UINT8 extra :1;
-+            UINT8 key_context :1;
-+            UINT8 fmt;
-+        };
-+        UINT8 all;
-+    } flags;
-+    TPMI_ALG_SIG_SCHEME format;
-+    TPMI_ALG_HASH halg;
-+    TPM2B_DIGEST msgHash;
-+    TPM2B_DIGEST pcrHash;
-+    TPM2B_DIGEST quoteHash;
-+    TPM2B_DATA quoteExtraData;
-+    TPM2B_DATA extraData;
-+    TPMT_SIGNATURE signature;
-+    char *msg_file_path;
-+    char *sig_file_path;
-+    char *out_file_path;
-+    char *pcr_file_path;
-+    const char *pubkey_file_path;
-+};
-+
-+tpm2_verifysig_ctx ctx = {
-+        .format = TPM2_ALG_ERROR,
-+        .halg = TPM2_ALG_SHA1,
-+        .msgHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
-+        .pcrHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
-+        .quoteHash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
-+        .quoteExtraData = TPM2B_TYPE_INIT(TPM2B_DATA, buffer),
-+        .extraData = TPM2B_TYPE_INIT(TPM2B_DATA, buffer),
-+};
-+
-+static bool verify_signature() {
-+
-+    bool result = false;
-+
-+    // Read in the AKpub they provided as an RSA object
-+    FILE *pubkey_input = fopen(ctx.pubkey_file_path, "rb");
-+    if (!pubkey_input) {
-+        LOG_ERR("Could not open RSA pubkey input file \"%s\" error: \"%s\"",
-+                ctx.pubkey_file_path, strerror(errno));
-+        return false;
-+    }
-+    RSA *pubKey = tpm2_openssl_get_public_RSA_from_pem(pubkey_input, ctx.pubkey_file_path);
-+    if (pubKey == NULL) {
-+        LOG_ERR("Failed to load RSA public key from file");
-+        goto err;
-+    }
-+
-+    // Get the signature ready
-+    if (ctx.signature.sigAlg != TPM2_ALG_RSASSA) {
-+        LOG_ERR("Only RSASSA is supported for signatures");
-+        goto err;
-+    }
-+    TPM2B_PUBLIC_KEY_RSA sig = ctx.signature.signature.rsassa.sig;
-+    tpm2_tool_output("sigBuffer: ");
-+    tpm2_util_hexdump(sig.buffer, sig.size, true);
-+    tpm2_tool_output("\n");
-+
-+    // Verify the signature matches message digest
-+    int opensslHash = tpm2_openssl_halgid_from_tpmhalg(ctx.signature.signature.rsassa.hash);
-+    if (!RSA_verify(opensslHash, ctx.msgHash.buffer, ctx.msgHash.size, 
-+            sig.buffer, sig.size, pubKey)) {
-+        LOG_ERR("Error validating signed message with public key provided");
-+        goto err;
-+    }
-+
-+    // Ensure nonce is the same as given
-+    if (ctx.flags.extra) {
-+        if (
-+            ctx.quoteExtraData.size != ctx.extraData.size 
-+            || memcmp(ctx.quoteExtraData.buffer, ctx.extraData.buffer, ctx.extraData.size) != 0
-+        ) {
-+            LOG_ERR("Error validating nonce from quote");
-+            goto err;
-+        }
-+    }
-+
-+    // Also ensure digest from quote matches PCR digest
-+    if (ctx.flags.pcr) {
-+        if (!tpm2_util_verify_digests(&ctx.quoteHash, &ctx.pcrHash)) {
-+            LOG_ERR("Error validating PCR composite against signed message");
-+            goto err;
-+        }
-+    }
-+
-+    result = true;
-+
-+err: 
-+    if (pubkey_input) {
-+        fclose(pubkey_input);
-+    }
-+
-+    RSA_free(pubKey);
-+
-+    return result;
-+}
-+
-+static TPM2B_ATTEST *message_from_file(const char *msg_file_path) {
-+
-+    unsigned long size;
-+
-+    bool result = files_get_file_size_path(msg_file_path, &size);
-+    if (!result) {
-+        return NULL;
-+    }
-+
-+    if (!size) {
-+        LOG_ERR("The msg file \"%s\" is empty", msg_file_path);
-+        return NULL;
-+    }
-+
-+    TPM2B_ATTEST *msg = (TPM2B_ATTEST *) calloc(1, sizeof(TPM2B_ATTEST) + size);
-+    if (!msg) {
-+        LOG_ERR("OOM");
-+        return NULL;
-+    }
-+
-+    UINT16 tmp = msg->size = size;
-+    if (!files_load_bytes_from_path(msg_file_path, msg->attestationData, &tmp)) {
-+        free(msg);
-+        return NULL;
-+    }
-+    return msg;
-+}
-+
-+static bool pcrs_from_file(const char *pcr_file_path, 
-+        TPML_PCR_SELECTION *pcrSel, tpm2_pcrs *pcrs) {
-+
-+    bool result = false;
-+    unsigned long size;
-+
-+    if (!files_get_file_size_path(pcr_file_path, &size)) {
-+        return false;
-+    }
-+
-+    if (!size) {
-+        LOG_ERR("The pcr file \"%s\" is empty", pcr_file_path);
-+        return false;
-+    }
-+
-+    FILE *pcr_input = fopen(pcr_file_path, "rb");
-+    if (!pcr_input) {
-+        LOG_ERR("Could not open PCRs input file \"%s\" error: \"%s\"",
-+                pcr_file_path, strerror(errno));
-+        goto out;
-+    }
-+
-+    // Import TPML_PCR_SELECTION structure to pcr outfile
-+    if (fread(pcrSel, sizeof(TPML_PCR_SELECTION), 1, pcr_input) != 1) {
-+        LOG_ERR("Failed to read PCR selection from file");
-+        goto out;
-+    }
-+
-+    // Import PCR digests to pcr outfile
-+    if (fread(&pcrs->count, sizeof(UINT32), 1, pcr_input) != 1) {
-+        LOG_ERR("Failed to read PCR digests header from file");
-+        goto out;
-+    }
-+
-+    UINT32 j;
-+    for (j = 0; j < pcrs->count; j++) {
-+        if (fread(&pcrs->pcr_values[j], sizeof(TPML_DIGEST), 1, pcr_input) != 1) {
-+            LOG_ERR("Failed to read PCR digest from file");
-+            goto out;
-+        }
-+    }
-+
-+    result = true;
-+
-+out:
-+    if (pcr_input) {
-+        fclose(pcr_input);
-+    }
-+
-+    return result;
-+}
-+
-+static bool init() {
-+
-+    /* check flags for mismatches */
-+    if (!(ctx.pubkey_file_path && ctx.flags.sig && ctx.flags.msg && ctx.flags.halg)) {
-+        LOG_ERR(
-+                "--pubkey (-c), --msg (-m), --halg (-g) and --sig (-s) are required");
-+        return false;
-+    }
-+
-+    TPM2B_ATTEST *msg = NULL;
-+    TPML_PCR_SELECTION pcrSel;
-+    tpm2_pcrs pcrs;
-+    bool return_value = false;
-+
-+    if (ctx.flags.msg) {
-+        msg = message_from_file(ctx.msg_file_path);
-+        if (!msg) {
-+            /* message_from_file() logs specific error no need to here */
-+            return false;
-+        }
-+    }
-+
-+    if (ctx.flags.sig) {
-+        bool res =  files_load_signature(ctx.sig_file_path, &ctx.signature);
-+        if (!res) {
-+            goto err;
-+        }
-+    }
-+
-+    /* If no digest is specified, compute it */
-+    if (!ctx.flags.msg) {
-+        /*
-+         * This is a redundant check since main() checks this case, but we'll add it here to silence any
-+         * complainers.
-+         */
-+        LOG_ERR("No digest set and no message file to compute from, cannot compute message hash!");
-+        goto err;
-+    }
-+
-+    if (ctx.flags.pcr) {
-+        if (!pcrs_from_file(ctx.pcr_file_path, &pcrSel, &pcrs)) {
-+            /* pcrs_from_file() logs specific error no need to here */
-+            goto err;
-+        }
-+
-+        if (!tpm2_openssl_hash_pcr_banks(ctx.halg, &pcrSel, &pcrs, &ctx.pcrHash)) {
-+            LOG_ERR("Failed to hash PCR values related to quote!");
-+            goto err;
-+        }
-+        if (!pcr_print_pcr_struct(&pcrSel, &pcrs)) {
-+            LOG_ERR("Failed to print PCR values related to quote!");
-+            goto err;
-+        }
-+        tpm2_tool_output("calcDigest: ");
-+        tpm2_util_hexdump(ctx.pcrHash.buffer, ctx.pcrHash.size, true);
-+        tpm2_tool_output("\n");
-+    }
-+
-+    // Figure out the extra data (nonce) from this message
-+    if (!tpm2_util_get_digest_from_quote(msg, &ctx.quoteHash, &ctx.quoteExtraData)) {
-+        LOG_ERR("Failed to get digest from quote!");
-+        goto err;
-+    }
-+
-+    // Figure out the digest for this message
-+    bool res = tpm2_openssl_hash_compute_data(ctx.halg, msg->attestationData, 
-+        msg->size, &ctx.msgHash);
-+    if (!res) {
-+        LOG_ERR("Compute message hash failed!");
-+        goto err;
-+    }
-+    tpm2_tool_output("msgDigest: ");
-+    tpm2_util_hexdump(ctx.msgHash.buffer, ctx.msgHash.size, true);
-+    tpm2_tool_output("\n");
-+
-+    return_value = true;
-+
-+err:
-+    free(msg);
-+    return return_value;
-+
-+}
-+
-+static bool on_option(char key, char *value) {
-+
-+	switch (key) {
-+	case 'c':
-+	    ctx.pubkey_file_path = value;
-+	    break;
-+	case 'G': {
-+		ctx.halg = tpm2_alg_util_from_optarg(value);
-+		if (ctx.halg == TPM2_ALG_ERROR) {
-+			LOG_ERR("Unable to convert algorithm, got: \"%s\"", value);
-+			return false;
-+		}
-+		ctx.flags.halg = 1;
-+	}
-+		break;
-+	case 'm': {
-+		ctx.msg_file_path = value;
-+		ctx.flags.msg = 1;
-+	}
-+		break;
-+	case 'f': {
-+		ctx.format = tpm2_alg_util_from_optarg(value);
-+		if (ctx.format == TPM2_ALG_ERROR) {
-+		    LOG_ERR("Unknown signing scheme, got: \"%s\"", value);
-+		    return false;
-+		}
-+
-+		ctx.flags.fmt = 1;
-+	} break;
-+	case 'q':
-+		ctx.extraData.size = sizeof(ctx.extraData) - 2;
-+		if(tpm2_util_hex_to_byte_structure(value, &ctx.extraData.size, ctx.extraData.buffer) != 0)
-+		{
-+			LOG_ERR("Could not convert \"%s\" from a hex string to byte array!", value);
-+			return false;
-+		}
-+		ctx.flags.extra = 1;
-+		break;
-+	case 's':
-+		ctx.sig_file_path = value;
-+		ctx.flags.sig = 1;
-+		break;
-+	case 'p':
-+		ctx.pcr_file_path = value;
-+		ctx.flags.pcr = 1;
-+		break;
-+		/* no default */
-+	}
-+
-+    return true;
-+}
-+
-+bool tpm2_tool_onstart(tpm2_options **opts) {
-+
-+    const struct option topts[] = {
-+            { "halg",         required_argument, NULL, 'G' },
-+            { "message",      required_argument, NULL, 'm' },
-+            { "format",       required_argument, NULL, 'f' },
-+            { "sig",          required_argument, NULL, 's' },
-+            { "pcrs",         required_argument, NULL, 'p' },
-+            { "pubkey",       required_argument, NULL, 'c' },
-+            { "qualify-data",         required_argument, NULL, 'q' },
-+    };
-+
-+
-+    *opts = tpm2_options_new("G:m:f:s:t:c:p:q:", ARRAY_LEN(topts), topts,
-+                             on_option, NULL, TPM2_OPTIONS_NO_SAPI);
-+
-+    return *opts != NULL;
-+}
-+
-+int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
-+
-+	UNUSED(sapi_context);
-+	UNUSED(flags);
-+
-+    /* initialize and process */
-+    bool res = init();
-+    if (!res) {
-+        return 1;
-+    }
-+
-+    res = verify_signature();
-+    if (!res) {
-+        LOG_ERR("Verify signature failed!");
-+        return 1;
-+    }
-+
-+    return 0;
-+}
-diff --git a/tools/tpm2_pcrlist.c b/tools/tpm2_pcrlist.c
-index 581bcecbd63..9a1ee457ce1 100644
---- a/tools/tpm2_pcrlist.c
-+++ b/tools/tpm2_pcrlist.c
-@@ -44,17 +44,6 @@
- #include "tpm2_alg_util.h"
- #include "tpm2_tool.h"
- 
--typedef struct tpm2_algorithm tpm2_algorithm;
--struct tpm2_algorithm {
--    int count;
--    TPMI_ALG_HASH alg[8]; //XXX Why 8?
--};
--
--typedef struct tpm2_pcrs tpm2_pcrs;
--struct tpm2_pcrs {
--    size_t count;
--    TPML_DIGEST pcr_values[24]; //XXX Why 24?
--};
- 
- typedef struct listpcr_context listpcr_context;
- struct listpcr_context {
-@@ -85,163 +74,6 @@ static listpcr_context ctx = {
-     },
- };
- 
--static inline void set_pcr_select_size(TPMS_PCR_SELECTION *pcr_selection,
--        UINT8 size) {
--
--    pcr_selection->sizeofSelect = size;
--}
--
--static bool is_pcr_select_bit_set(TPMS_PCR_SELECTION *pcr_selection, UINT32 pcr) {
--
--    return (pcr_selection->pcrSelect[((pcr) / 8)] & (1 << ((pcr) % 8)));
--}
--
--static void update_pcr_selections(TPML_PCR_SELECTION *s1, TPML_PCR_SELECTION *s2) {
--
--    UINT32 i1, i2, j;
--    for (i2 = 0; i2 < s2->count; i2++) {
--        for (i1 = 0; i1 < s1->count; i1++) {
--            if (s2->pcrSelections[i2].hash != s1->pcrSelections[i1].hash)
--                continue;
--
--            for (j = 0; j < s1->pcrSelections[i1].sizeofSelect; j++)
--                s1->pcrSelections[i1].pcrSelect[j] &=
--                        ~s2->pcrSelections[i2].pcrSelect[j];
--        }
--    }
--}
--
--static bool unset_pcr_sections(TPML_PCR_SELECTION *s) {
--
--    UINT32 i, j;
--    for (i = 0; i < s->count; i++) {
--        for (j = 0; j < s->pcrSelections[i].sizeofSelect; j++) {
--            if (s->pcrSelections[i].pcrSelect[j]) {
--                return false;
--            }
--        }
--    }
--
--    return true;
--}
--
--static bool read_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
--
--    TPML_PCR_SELECTION pcr_selection_tmp;
--    TPML_PCR_SELECTION pcr_selection_out;
--    UINT32 pcr_update_counter;
--
--    //1. prepare pcrSelectionIn with g_pcrSelections
--    memcpy(&pcr_selection_tmp, &ctx.pcr_selections, sizeof(pcr_selection_tmp));
--
--    //2. call pcr_read
--    ctx.pcrs.count = 0;
--    do {
--        UINT32 rval = TSS2_RETRY_EXP(Tss2_Sys_PCR_Read(sapi_context, no_argument, &pcr_selection_tmp,
--                &pcr_update_counter, &pcr_selection_out,
--                &ctx.pcrs.pcr_values[ctx.pcrs.count], 0));
--
--        if (rval != TPM2_RC_SUCCESS) {
--            LOG_ERR("read pcr failed. tpm error 0x%0x", rval);
--            return -1;
--        }
--
--        //3. unmask pcrSelectionOut bits from pcrSelectionIn
--        update_pcr_selections(&pcr_selection_tmp, &pcr_selection_out);
--
--        //4. goto step 2 if pcrSelctionIn still has bits set
--    } while (++ctx.pcrs.count < 24 && !unset_pcr_sections(&pcr_selection_tmp));
--
--    if (ctx.pcrs.count >= 24 && !unset_pcr_sections(&pcr_selection_tmp)) {
--        LOG_ERR("too much pcrs to get! try to split into multiple calls...");
--        return false;
--    }
--
--    return true;
--}
--
--static bool init_pcr_selection(void) {
--
--    TPMS_CAPABILITY_DATA *cap_data = &ctx.cap_data;
--    TPML_PCR_SELECTION *pcr_sel = &ctx.pcr_selections;
--    UINT32 i, j;
--
--    TPMI_ALG_HASH alg_id = ctx.selected_algorithm;
--
--    pcr_sel->count = 0;
--
--    for (i = 0; i < cap_data->data.assignedPCR.count; i++) {
--        if (alg_id && (cap_data->data.assignedPCR.pcrSelections[i].hash != alg_id))
--            continue;
--        pcr_sel->pcrSelections[pcr_sel->count].hash = cap_data->data.assignedPCR.pcrSelections[i].hash;
--        set_pcr_select_size(&pcr_sel->pcrSelections[pcr_sel->count], cap_data->data.assignedPCR.pcrSelections[i].sizeofSelect);
--        for (j = 0; j < pcr_sel->pcrSelections[pcr_sel->count].sizeofSelect; j++)
--            pcr_sel->pcrSelections[pcr_sel->count].pcrSelect[j] = cap_data->data.assignedPCR.pcrSelections[i].pcrSelect[j];
--        pcr_sel->count++;
--    }
--
--    if (pcr_sel->count == 0)
--        return false;
--
--    return true;
--}
--
--static void shrink_pcr_selection(TPML_PCR_SELECTION *s) {
--
--    UINT32 i, j;
--
--    //seek for the first empty item
--    for (i = 0; i < s->count; i++)
--        if (!s->pcrSelections[i].hash)
--            break;
--    j = i + 1;
--
--    for (; i < s->count; i++) {
--        if (!s->pcrSelections[i].hash) {
--            for (; j < s->count; j++)
--                if (s->pcrSelections[j].hash)
--                    break;
--            if (j >= s->count)
--                break;
--
--            memcpy(&s->pcrSelections[i], &s->pcrSelections[j], sizeof(s->pcrSelections[i]));
--            s->pcrSelections[j].hash = 0;
--            j++;
--        }
--    }
--
--    s->count = i;
--}
--
--static bool check_pcr_selection(void) {
--
--    TPMS_CAPABILITY_DATA *cap_data = &ctx.cap_data;
--    TPML_PCR_SELECTION *pcr_sel = &ctx.pcr_selections;
--    UINT32 i, j, k;
--
--    for (i = 0; i < pcr_sel->count; i++) {
--        for (j = 0; j < cap_data->data.assignedPCR.count; j++) {
--            if (pcr_sel->pcrSelections[i].hash == cap_data->data.assignedPCR.pcrSelections[j].hash) {
--                for (k = 0; k < pcr_sel->pcrSelections[i].sizeofSelect; k++)
--                    pcr_sel->pcrSelections[i].pcrSelect[k] &= cap_data->data.assignedPCR.pcrSelections[j].pcrSelect[k];
--                break;
--            }
--        }
--
--        if (j >= cap_data->data.assignedPCR.count) {
--            const char *alg_name = tpm2_alg_util_algtostr(pcr_sel->pcrSelections[i].hash);
--            LOG_WARN("Ignore unsupported bank/algorithm: %s(0x%04x)", alg_name, pcr_sel->pcrSelections[i].hash);
--            pcr_sel->pcrSelections[i].hash = 0; //mark it as to be removed
--        }
--    }
--
--    shrink_pcr_selection(pcr_sel);
--    if (pcr_sel->count == 0)
--        return false;
--
--    return true;
--}
--
- // show all PCR banks according to g_pcrSelection & g_pcrs->
- static bool show_pcr_values(void) {
- 
-@@ -255,7 +87,7 @@ static bool show_pcr_values(void) {
- 
-         UINT32 pcr_id;
-         for (pcr_id = 0; pcr_id < ctx.pcr_selections.pcrSelections[i].sizeofSelect * 8; pcr_id++) {
--            if (!is_pcr_select_bit_set(&ctx.pcr_selections.pcrSelections[i],
-+            if (!tpm2_util_is_pcr_select_bit_set(&ctx.pcr_selections.pcrSelections[i],
-                     pcr_id)) {
-                 continue;
-             }
-@@ -296,10 +128,10 @@ static bool show_pcr_values(void) {
- 
- static bool show_selected_pcr_values(TSS2_SYS_CONTEXT *sapi_context, bool check) {
- 
--    if (check && !check_pcr_selection())
-+    if (check && !pcr_check_pcr_selection(&ctx.cap_data, &ctx.pcr_selections))
-         return false;
- 
--    if (!read_pcr_values(sapi_context))
-+    if (!pcr_read_pcr_values(sapi_context, &ctx.pcr_selections, &ctx.pcrs))
-         return false;
- 
-     if (!show_pcr_values())
-@@ -310,7 +142,7 @@ static bool show_selected_pcr_values(TSS2_SYS_CONTEXT *sapi_context, bool check)
- 
- static bool show_all_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
- 
--    if (!init_pcr_selection())
-+    if (!pcr_init_pcr_selection(&ctx.cap_data, &ctx.pcr_selections, ctx.selected_algorithm))
-         return false;
- 
-     return show_selected_pcr_values(sapi_context, false);
-@@ -318,37 +150,12 @@ static bool show_all_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
- 
- static bool show_alg_pcr_values(TSS2_SYS_CONTEXT *sapi_context) {
- 
--    if (!init_pcr_selection())
-+    if (!pcr_init_pcr_selection(&ctx.cap_data, &ctx.pcr_selections, ctx.selected_algorithm))
-         return false;
- 
-     return show_selected_pcr_values(sapi_context, false);
- }
- 
--static bool get_banks(TSS2_SYS_CONTEXT *sapi_context) {
--
--    TPMI_YES_NO more_data;
--    TPMS_CAPABILITY_DATA *capability_data = &ctx.cap_data;
--    UINT32 rval;
--
--    rval = TSS2_RETRY_EXP(Tss2_Sys_GetCapability(sapi_context, no_argument, TPM2_CAP_PCRS, no_argument, required_argument,
--            &more_data, capability_data, 0));
--    if (rval != TPM2_RC_SUCCESS) {
--        LOG_ERR(
--                "GetCapability: Get PCR allocation status Error. TPM Error:0x%x......",
--                rval);
--        return false;
--    }
--
--    unsigned i;
--    for (i = 0; i < capability_data->data.assignedPCR.count; i++) {
--        ctx.algs.alg[i] =
--                capability_data->data.assignedPCR.pcrSelections[i].hash;
--    }
--    ctx.algs.count = capability_data->data.assignedPCR.count;
--
--    return true;
--}
--
- static void show_banks(tpm2_algorithm *g_banks) {
- 
-     tpm2_tool_output("Supported Bank/Algorithm:");
-@@ -432,7 +239,7 @@ int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
-         }
-     }
- 
--    success = get_banks(sapi_context);
-+    success = pcr_get_banks(sapi_context, &ctx.cap_data, &ctx.algs);
-     if (!success) {
-         goto error;
-     }
-diff --git a/tools/tpm2_quote.c b/tools/tpm2_quote.c
-index 05b6d641656..2efba240340 100644
---- a/tools/tpm2_quote.c
-+++ b/tools/tpm2_quote.c
-@@ -42,6 +42,7 @@
- #include "conversion.h"
- #include "tpm2_alg_util.h"
- #include "tpm2_password_util.h"
-+#include "tpm2_openssl.h"
- #include "tpm2_tool.h"
- #include "tpm2_util.h"
- 
-@@ -54,15 +55,27 @@ static TPMS_AUTH_COMMAND sessionData = TPMS_AUTH_COMMAND_INIT(TPM2_RS_PW);
- static char *outFilePath;
- static char *signature_path;
- static char *message_path;
-+static char *pcr_path;
-+static FILE *pcr_output;
-+static TPMS_CAPABILITY_DATA cap_data;
- static signature_format sig_format;
- static TPMI_ALG_HASH sig_hash_algorithm;
-+static tpm2_algorithm algs = {
-+    .count = 3,
-+    .alg = {
-+        TPM2_ALG_SHA1,
-+        TPM2_ALG_SHA256,
-+        TPM2_ALG_SHA384
-+    }
-+};
- static TPM2B_DATA qualifyingData = TPM2B_EMPTY_INIT;
- static TPML_PCR_SELECTION  pcrSelections;
- static bool is_auth_session;
- static TPMI_SH_AUTH_SESSION auth_session_handle;
--static int k_flag, c_flag, l_flag, g_flag, L_flag, o_flag, G_flag, P_flag;
-+static int k_flag, c_flag, l_flag, g_flag, L_flag, o_flag, G_flag, P_flag, p_flag;
- static char *contextFilePath;
- static TPM2_HANDLE akHandle;
-+static tpm2_pcrs pcrs;
- 
- static void PrintBuffer( UINT8 *buffer, UINT32 size )
- {
-@@ -74,6 +87,40 @@ static void PrintBuffer( UINT8 *buffer, UINT32 size )
-     tpm2_tool_output("\n");
- }
- 
-+
-+// write all PCR banks according to g_pcrSelection & g_pcrs->
-+static bool write_pcr_values() {
-+
-+    // PCR output to file wasn't requested
-+    if (pcr_output == NULL) {
-+        return true;
-+    }
-+
-+    // Export TPML_PCR_SELECTION structure to pcr outfile
-+    if (fwrite(&pcrSelections,
-+            sizeof(TPML_PCR_SELECTION), 1,
-+            pcr_output) != 1) {
-+        LOG_ERR("write to output file failed: %s", strerror(errno));
-+        return false;
-+    }
-+
-+    // Export PCR digests to pcr outfile
-+    if (fwrite(&pcrs.count, sizeof(UINT32), 1, pcr_output) != 1) {
-+        LOG_ERR("write to output file failed: %s", strerror(errno));
-+        return false;
-+    }
-+
-+    UINT32 j;
-+    for (j = 0; j < pcrs.count; j++) {
-+        if (fwrite(&pcrs.pcr_values[j], sizeof(TPML_DIGEST), 1, pcr_output) != 1) {
-+            LOG_ERR("write to output file failed: %s", strerror(errno));
-+            return false;
-+        }
-+    }
-+
-+    return true;
-+}
-+
- static bool write_output_files(TPM2B_ATTEST *quoted, TPMT_SIGNATURE *signature) {
- 
-     bool res = true;
-@@ -87,6 +134,8 @@ static bool write_output_files(TPM2B_ATTEST *quoted, TPMT_SIGNATURE *signature)
-                 quoted->size);
-     }
- 
-+    res &= write_pcr_values();
-+
-     return res;
- }
- 
-@@ -125,7 +174,53 @@ static int quote(TSS2_SYS_CONTEXT *sapi_context, TPM2_HANDLE akHandle, TPML_PCR_
-     PrintBuffer( (UINT8 *)&signature, sizeof(signature) );
-     //PrintTPMT_SIGNATURE(&signature);
- 
-+    if (pcr_output) {
-+        // Filter out invalid/unavailable PCR selections
-+        if (!pcr_check_pcr_selection(&cap_data, &pcrSelections)) {
-+            LOG_ERR("Failed to filter unavailable PCR values for quote!");
-+            return false;
-+        }
-+
-+        // Gather PCR values from the TPM (the quote doesn't have them!)
-+        if (!pcr_read_pcr_values(sapi_context, &pcrSelections, &pcrs)) {
-+            LOG_ERR("Failed to retrieve PCR values related to quote!");
-+            return false;
-+        }
-+
-+        // Grab the digest from the quote
-+        TPM2B_DIGEST quoteDigest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
-+        TPM2B_DATA extraData = TPM2B_TYPE_INIT(TPM2B_DATA, buffer);
-+        if (!tpm2_util_get_digest_from_quote(&quoted, &quoteDigest, &extraData)) {
-+            LOG_ERR("Failed to get digest from quote!");
-+            return false;
-+        }
-+
-+        // Print out PCR values as output
-+        if (!pcr_print_pcr_struct(&pcrSelections, &pcrs)) {
-+            LOG_ERR("Failed to print PCR values related to quote!");
-+            return false;
-+        }
-+
-+        // Calculate the digest from our selected PCR values (to ensure correctness)
-+        TPM2B_DIGEST pcr_digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
-+        if (!tpm2_openssl_hash_pcr_banks(sig_hash_algorithm, &pcrSelections, &pcrs, &pcr_digest)) {
-+            LOG_ERR("Failed to hash PCR values related to quote!");
-+            return false;
-+        }
-+        tpm2_tool_output("calcDigest: ");
-+        tpm2_util_hexdump(pcr_digest.buffer, pcr_digest.size, true);
-+        tpm2_tool_output("\n");
-+
-+        // Make sure digest from quote matches calculated PCR digest
-+        if (!tpm2_util_verify_digests(&quoteDigest, &pcr_digest)) {
-+            LOG_ERR("Error validating calculated PCR composite with quote");
-+            return false;
-+        }
-+    }
-+
-+    // Write everything out
-     bool res = write_output_files(&quoted, &signature);
-+
-     return res == true ? 0 : 1;
- }
- 
-@@ -206,6 +301,10 @@ static bool on_option(char key, char *value) {
-     case 'm':
-          message_path = optarg;
-          break;
-+    case 'p':
-+         pcr_path = optarg;
-+         p_flag = 1;
-+         break;
-     case 'f':
-          sig_format = tpm2_parse_signature_format(optarg);
- 
-@@ -239,11 +338,12 @@ bool tpm2_tool_onstart(tpm2_options **opts) {
-         { "input-session-handle", required_argument, NULL, 'S' },
-         { "signature",            required_argument, NULL, 's' },
-         { "message",              required_argument, NULL, 'm' },
-+        { "pcrs",                 required_argument, NULL, 'p' },
-         { "format",               required_argument, NULL, 'f' },
-         { "sig-hash-algorithm",   required_argument, NULL, 'G' }
-     };
- 
--    *opts = tpm2_options_new("k:c:P:l:g:L:S:q:s:m:f:G:", ARRAY_LEN(topts), topts,
-+    *opts = tpm2_options_new("k:c:P:l:g:L:S:q:s:m:p:f:G:", ARRAY_LEN(topts), topts,
-             on_option, NULL, TPM2_OPTIONS_SHOW_USAGE);
- 
-     return *opts != NULL;
-@@ -270,5 +370,25 @@ int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
-         sessionData.hmac.size = 0;
-     }
- 
-+    if (p_flag) {
-+        if (!G_flag) {
-+            LOG_ERR("Must specify -G if -p is requested.");
-+            return -1;
-+        }
-+        pcr_output = fopen(pcr_path, "wb+");
-+        if (!pcr_output) {
-+            LOG_ERR("Could not open PCR output file \"%s\" error: \"%s\"",
-+                    pcr_path, strerror(errno));
-+            return 1;
-+        }
-+    }
-+
-+    if (!pcr_get_banks(sapi_context, &cap_data, &algs)) {
-+        if (pcr_output) {
-+            fclose(pcr_output);
-+        }
-+        return 1;
-+    }
-+
-     return quote(sapi_context, akHandle, &pcrSelections);
- }
--- 
-2.21.0
-
diff --git a/Add-ability-to-run-tpm2_makecredential-without-a-TPM.patch b/Add-ability-to-run-tpm2_makecredential-without-a-TPM.patch
deleted file mode 100644
index 9929d13..0000000
--- a/Add-ability-to-run-tpm2_makecredential-without-a-TPM.patch
+++ /dev/null
@@ -1,1305 +0,0 @@
-From d74b094191f2e09b29cfad4f03322e0cd64497ab Mon Sep 17 00:00:00 2001
-From: jetwhiz <charles.munson@ll.mit.edu>
-Date: Tue, 5 Feb 2019 17:24:44 -0500
-Subject: [PATCH] Add ability to run tpm2_makecredential without a TPM
-
-Used some functions from tpm2_import for off-TPM functionality
- - Move needed, overlap code into tpm2_identity_util
-Add new global -X/--openssl-backend option for any tools that can operate w/o TPM
-
-Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
----
- Makefile.am                             |   6 +-
- lib/tpm2_identity_util.c                | 480 ++++++++++++++++++++++++
- lib/tpm2_identity_util.h                | 141 +++++++
- lib/tpm2_openssl.c                      | 162 ++++++++
- lib/tpm2_openssl.h                      | 108 ++++++
- lib/tpm2_options.c                      |  36 +-
- lib/tpm2_options.h                      |   1 +
- man/common/tcti.md                      |   4 +
- man/tpm2_activatecredential.1.md        |   2 +-
- man/tpm2_certify.1.md                   |   2 +-
- man/tpm2_create.1.md                    |   2 +-
- man/tpm2_encryptdecrypt.1.md            |   2 +-
- man/tpm2_getpubak.1.md                  |   2 +-
- man/tpm2_makecredential.1.md            |   3 +-
- test/system/test_tpm2_makecredential.sh |   2 +
- tools/tpm2_makecredential.c             | 103 ++++-
- 16 files changed, 1033 insertions(+), 23 deletions(-)
- create mode 100644 lib/tpm2_identity_util.c
- create mode 100644 lib/tpm2_identity_util.h
- create mode 100644 lib/tpm2_openssl.c
- create mode 100644 lib/tpm2_openssl.h
-
-diff --git a/Makefile.am b/Makefile.am
-index ffe22f383e3..2195537ce01 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -119,7 +119,11 @@ lib_libcommon_a_SOURCES = \
-     lib/tpm2_errata.c \
-     lib/tpm2_errata.h \
-     lib/tpm2_header.h \
-+    lib/tpm2_identity_util.c \
-+    lib/tpm2_identity_util.h \
-     lib/tpm2_nv_util.h \
-+    lib/tpm2_openssl.c \
-+    lib/tpm2_openssl.h \
-     lib/tpm2_password_util.c \
-     lib/tpm2_password_util.h \
-     lib/tpm2_policy.c \
-@@ -347,4 +351,4 @@ man/man1/%.1 : man/%.1.md $(MARKDOWN_COMMON_DEPS)
- 	    -e '/\[object attribute specifiers\]/d' \
- 	    < $< | pandoc -s -t man > $@
- 
--CLEANFILES = $(man1_MANS)
-+CLEANFILES = $(man1_MANS)
-\ No newline at end of file
-diff --git a/lib/tpm2_identity_util.c b/lib/tpm2_identity_util.c
-new file mode 100644
-index 00000000000..70bf03647eb
---- /dev/null
-+++ b/lib/tpm2_identity_util.c
-@@ -0,0 +1,480 @@
-+//**********************************************************************;
-+// Copyright (c) 2017, Intel Corporation
-+// Copyright (c) 2019 Massachusetts Institute of Technology
-+// All rights reserved.
-+//
-+// Redistribution and use in source and binary forms, with or without
-+// modification, are permitted provided that the following conditions are met:
-+//
-+// 1. Redistributions of source code must retain the above copyright notice,
-+// this list of conditions and the following disclaimer.
-+//
-+// 2. Redistributions in binary form must reproduce the above copyright notice,
-+// this list of conditions and the following disclaimer in the documentation
-+// and/or other materials provided with the distribution.
-+//
-+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+// THE POSSIBILITY OF SUCH DAMAGE.
-+//**********************************************************************
-+
-+#include <errno.h>
-+#include <stdint.h>
-+#include <string.h>
-+
-+#include <openssl/aes.h>
-+#include <openssl/bn.h>
-+#include <openssl/evp.h>
-+#include <openssl/err.h>
-+#include <openssl/hmac.h>
-+#include <openssl/obj_mac.h>
-+#include <openssl/pem.h>
-+#include <openssl/rand.h>
-+#include <openssl/rsa.h>
-+
-+#include <tss2/tss2_mu.h>
-+#include <tss2/tss2_sys.h>
-+
-+#include "files.h"
-+#include "log.h"
-+#include "tpm2_alg_util.h"
-+#include "tpm_kdfa.h"
-+#include "tpm2_openssl.h"
-+#include "tpm2_identity_util.h"
-+#include "tpm2_util.h"
-+
-+
-+// Identity-related functionality that the TPM normally does, but using OpenSSL
-+
-+#if defined(LIBRESSL_VERSION_NUMBER)
-+static int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
-+        const unsigned char *from, int flen, const unsigned char *param, int plen,
-+        const EVP_MD *md, const EVP_MD *mgf1md) {
-+
-+    int ret = 0;
-+    int i, emlen = tlen - 1;
-+    unsigned char *db, *seed;
-+    unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE];
-+    int mdlen;
-+
-+    if (md == NULL)
-+        md = EVP_sha1();
-+    if (mgf1md == NULL)
-+        mgf1md = md;
-+
-+    mdlen = EVP_MD_size(md);
-+
-+    if (flen > emlen - 2 * mdlen - 1) {
-+        RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
-+               RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
-+        return 0;
-+    }
-+
-+    if (emlen < 2 * mdlen + 1) {
-+        RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
-+               RSA_R_KEY_SIZE_TOO_SMALL);
-+        return 0;
-+    }
-+
-+    to[0] = 0;
-+    seed = to + 1;
-+    db = to + mdlen + 1;
-+
-+    if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
-+        return 0;
-+    memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
-+    db[emlen - flen - mdlen - 1] = 0x01;
-+    memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
-+    if (RAND_bytes(seed, mdlen) <= 0)
-+        return 0;
-+
-+    dbmask = OPENSSL_malloc(emlen - mdlen);
-+    if (dbmask == NULL) {
-+        RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
-+        return 0;
-+    }
-+
-+    if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0)
-+        goto err;
-+    for (i = 0; i < emlen - mdlen; i++)
-+        db[i] ^= dbmask[i];
-+
-+    if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0)
-+        goto err;
-+    for (i = 0; i < mdlen; i++)
-+        seed[i] ^= seedmask[i];
-+
-+    ret = 1;
-+
-+ err:
-+    OPENSSL_free(dbmask);
-+
-+    return ret;
-+}
-+#endif
-+
-+static TPM2_KEY_BITS get_pub_asym_key_bits(TPM2B_PUBLIC *public) {
-+
-+    TPMU_PUBLIC_PARMS *p = &public->publicArea.parameters;
-+    switch(public->publicArea.type) {
-+    case TPM2_ALG_ECC:
-+        /* fall-thru */
-+    case TPM2_ALG_RSA:
-+        return p->asymDetail.symmetric.keyBits.sym;
-+    /* no default */
-+    }
-+
-+    return 0;
-+}
-+
-+static bool encrypt_seed_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed,
-+        TPM2B_PUBLIC *parent_pub, unsigned char *label, int labelLen,
-+        TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) {
-+    bool rval = false;
-+    RSA *rsa = NULL;
-+
-+    // Public modulus (RSA-only!)
-+    TPMI_RSA_KEY_BITS mod_size_bits = parent_pub->publicArea.parameters.rsaDetail.keyBits;
-+    UINT16 mod_size = mod_size_bits / 8;
-+    TPM2B *pub_key_val = (TPM2B *)&parent_pub->publicArea.unique.rsa;
-+    unsigned char *pub_modulus = malloc(mod_size);
-+    if (pub_modulus == NULL) {
-+        LOG_ERR("Failed to allocate memory to store public key's modulus.");
-+        return false;
-+    }
-+    memcpy(pub_modulus, pub_key_val->buffer, mod_size);
-+
-+    TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg;
-+
-+    /*
-+     * This is the biggest buffer value, so it should always be sufficient.
-+     */
-+    unsigned char encoded[TPM2_MAX_DIGEST_BUFFER];
-+    int return_code = RSA_padding_add_PKCS1_OAEP_mgf1(encoded,
-+            mod_size, protection_seed->buffer, protection_seed->size, label, labelLen,
-+            tpm2_openssl_halg_from_tpmhalg(parent_name_alg), NULL);
-+    if (return_code != 1) {
-+        LOG_ERR("Failed RSA_padding_add_PKCS1_OAEP_mgf1\n");
-+        goto error;
-+    }
-+    BIGNUM* bne = BN_new();
-+    if (!bne) {
-+        LOG_ERR("BN_new for bne failed\n");
-+        goto error;
-+    }
-+    return_code = BN_set_word(bne, RSA_F4);
-+    if (return_code != 1) {
-+        LOG_ERR("BN_set_word failed\n");
-+        BN_free(bne);
-+        goto error;
-+    }
-+    rsa = RSA_new();
-+    if (!rsa) {
-+        LOG_ERR("RSA_new failed\n");
-+        BN_free(bne);
-+        goto error;
-+    }
-+    return_code = RSA_generate_key_ex(rsa, mod_size_bits, bne, NULL);
-+    BN_free(bne);
-+    if (return_code != 1) {
-+        LOG_ERR("RSA_generate_key_ex failed\n");
-+        goto error;
-+    }
-+    BIGNUM *n = BN_bin2bn(pub_modulus, mod_size, NULL);
-+    if (n == NULL) {
-+        LOG_ERR("BN_bin2bn failed\n");
-+        goto error;
-+    }
-+    if (!RSA_set0_key(rsa, n, NULL, NULL)) {
-+        LOG_ERR("RSA_set0_key failed\n");
-+        BN_free(n);
-+        goto error;
-+    }
-+    // Encrypting
-+    encrypted_protection_seed->size = mod_size;
-+    return_code = RSA_public_encrypt(mod_size, encoded,
-+            encrypted_protection_seed->secret, rsa, RSA_NO_PADDING);
-+    if (return_code < 0) {
-+        LOG_ERR("Failed RSA_public_encrypt\n");
-+        goto error;
-+    }
-+
-+    rval = true;
-+
-+error:
-+    free(pub_modulus);
-+    RSA_free(rsa);
-+    return rval;
-+}
-+
-+bool tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(
-+        TPM2B_PUBLIC *parent_pub,
-+        TPM2B_NAME *pubname,
-+        TPM2B_DIGEST *protection_seed,
-+        TPM2B_MAX_BUFFER *protection_hmac_key,
-+        TPM2B_MAX_BUFFER *protection_enc_key) {
-+
-+    TPM2B null_2b = { .size = 0 };
-+
-+    TPMI_ALG_HASH parent_alg = parent_pub->publicArea.nameAlg;
-+    UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_alg);
-+
-+    TSS2_RC rval = tpm_kdfa(parent_alg, (TPM2B *)protection_seed, "INTEGRITY",
-+            &null_2b, &null_2b, parent_hash_size * 8, protection_hmac_key);
-+    if (rval != TPM2_RC_SUCCESS) {
-+        return false;
-+    }
-+
-+    TPM2_KEY_BITS pub_key_bits = get_pub_asym_key_bits(parent_pub);
-+
-+    rval = tpm_kdfa(parent_alg, (TPM2B *)protection_seed, "STORAGE",
-+            (TPM2B *)pubname, &null_2b, pub_key_bits,
-+            protection_enc_key);
-+    if (rval != TPM2_RC_SUCCESS) {
-+        return false;
-+    }
-+
-+    return true;
-+}
-+
-+
-+bool tpm2_identity_util_encrypt_seed_with_public_key(TPM2B_DIGEST *protection_seed,
-+        TPM2B_PUBLIC *parent_pub, unsigned char *label, int labelLen,
-+        TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) {
-+    bool result = false;
-+    TPMI_ALG_PUBLIC alg = parent_pub->publicArea.type;
-+    
-+    switch (alg) {
-+    case TPM2_ALG_RSA:
-+        result = encrypt_seed_with_tpm2_rsa_public_key(protection_seed, 
-+                parent_pub, label, labelLen, encrypted_protection_seed);
-+        break;
-+    case TPM2_ALG_ECC:
-+        LOG_ERR("Algorithm '%s' not supported yet", tpm2_alg_util_algtostr(alg));
-+        result = false;
-+        break;
-+    default:
-+        LOG_ERR("Cannot handle algorithm, got: %s", tpm2_alg_util_algtostr(alg));
-+        return false;
-+    }
-+    
-+    return result;
-+}
-+
-+static const EVP_CIPHER *tpm_alg_to_ossl(TPMT_SYM_DEF_OBJECT *sym) {
-+
-+    switch(sym->algorithm) {
-+        case TPM2_ALG_AES: {
-+            switch (sym->keyBits.aes) {
-+            case 128:
-+                return EVP_aes_128_cfb();
-+            case 256:
-+                return EVP_aes_256_cfb();
-+            /* no default */
-+            }
-+        }
-+        /* no default */
-+    }
-+
-+    LOG_ERR("Unsupported parent key symmetric parameters");
-+
-+    return NULL;
-+}
-+
-+static bool aes_encrypt_buffers(TPMT_SYM_DEF_OBJECT *sym, uint8_t *encryption_key,
-+        uint8_t *buf1, size_t buf1_len,
-+        uint8_t *buf2, size_t buf2_len,
-+        TPM2B_MAX_BUFFER *cipher_text) {
-+
-+    bool result = false;
-+
-+    unsigned offset = 0;
-+    size_t total_len = buf1_len + buf2_len;
-+
-+    if (total_len > sizeof(cipher_text->buffer)) {
-+        LOG_ERR("Plaintext too big, got %zu, expected less then %zu",
-+                total_len, sizeof(cipher_text->buffer));
-+        return false;
-+    }
-+
-+    const EVP_CIPHER *cipher = tpm_alg_to_ossl(sym);
-+    if (!cipher) {
-+        return false;
-+    }
-+
-+    const unsigned char iv[512] = { 0 };
-+
-+    if (((unsigned long)EVP_CIPHER_iv_length(cipher)) > sizeof(iv)) {
-+        LOG_ERR("IV size is bigger then IV buffer size");
-+        return false;
-+    }
-+
-+    EVP_CIPHER_CTX *ctx = tpm2_openssl_cipher_new();
-+
-+    int rc = EVP_EncryptInit_ex(ctx, cipher, NULL, encryption_key, iv);
-+    if (!rc) {
-+        return false;
-+    }
-+
-+    EVP_CIPHER_CTX_set_padding(ctx, 0);
-+
-+    uint8_t *bufs[2] = {
-+        buf1,
-+        buf2
-+    };
-+
-+    size_t lens[ARRAY_LEN(bufs)] = {
-+        buf1_len,
-+        buf2_len
-+    };
-+
-+    unsigned i;
-+    for (i=0; i < ARRAY_LEN(bufs); i++) {
-+
-+        uint8_t *b = bufs[i];
-+        size_t l = lens[i];
-+
-+        if (!b) {
-+            continue;
-+        }
-+
-+        int output_len = total_len - offset;
-+
-+        rc = EVP_EncryptUpdate(ctx, &cipher_text->buffer[offset], &output_len, b, l);
-+        if (!rc) {
-+            LOG_ERR("Encrypt failed");
-+            goto out;
-+        }
-+
-+        offset += l;
-+    }
-+
-+    int tmp_len = 0;
-+    rc = EVP_EncryptFinal_ex(ctx, NULL, &tmp_len);
-+    if (!rc) {
-+        LOG_ERR("Encrypt failed");
-+        goto out;
-+    }
-+
-+    cipher_text->size = total_len;
-+
-+    result = true;
-+
-+out:
-+    tpm2_openssl_cipher_free(ctx);
-+
-+    return result;
-+}
-+
-+static void hmac_outer_integrity(
-+        TPMI_ALG_HASH parent_name_alg,
-+        uint8_t *buffer1, uint16_t buffer1_size,
-+        uint8_t *buffer2, uint16_t buffer2_size, uint8_t *hmac_key,
-+        TPM2B_DIGEST *outer_integrity_hmac) {
-+
-+    uint8_t to_hmac_buffer[TPM2_MAX_DIGEST_BUFFER];
-+    memcpy(to_hmac_buffer, buffer1, buffer1_size);
-+    memcpy(to_hmac_buffer + buffer1_size, buffer2, buffer2_size);
-+    uint32_t size = 0;
-+
-+    UINT16 hash_size = tpm2_alg_util_get_hash_size(parent_name_alg);
-+
-+    HMAC(tpm2_openssl_halg_from_tpmhalg(parent_name_alg), hmac_key, hash_size, to_hmac_buffer,
-+            buffer1_size + buffer2_size, outer_integrity_hmac->buffer, &size);
-+    outer_integrity_hmac->size = size;
-+}
-+
-+bool tpm2_identity_util_calculate_inner_integrity(
-+        TPMI_ALG_HASH name_alg, 
-+        TPM2B_SENSITIVE *sensitive, 
-+        TPM2B_NAME *pubname, 
-+        TPM2B_DATA *enc_sensitive_key,
-+        TPMT_SYM_DEF_OBJECT *sym_alg,
-+        TPM2B_MAX_BUFFER *encrypted_inner_integrity) {
-+
-+    //Marshal sensitive area
-+    uint8_t buffer_marshalled_sensitiveArea[TPM2_MAX_DIGEST_BUFFER] = { 0 };
-+    size_t marshalled_sensitive_size = 0;
-+    Tss2_MU_TPMT_SENSITIVE_Marshal(&sensitive->sensitiveArea,
-+            buffer_marshalled_sensitiveArea + sizeof(uint16_t), TPM2_MAX_DIGEST_BUFFER,
-+            &marshalled_sensitive_size);
-+    size_t marshalled_sensitive_size_info = 0;
-+    Tss2_MU_UINT16_Marshal(marshalled_sensitive_size, buffer_marshalled_sensitiveArea,
-+            sizeof(uint16_t), &marshalled_sensitive_size_info);
-+
-+    //concatenate NAME
-+    memcpy(
-+            buffer_marshalled_sensitiveArea + marshalled_sensitive_size
-+                    + marshalled_sensitive_size_info,
-+            pubname->name,
-+            pubname->size);
-+
-+    //Digest marshalled-sensitive || name
-+    uint8_t *marshalled_sensitive_and_name_digest =
-+            buffer_marshalled_sensitiveArea + marshalled_sensitive_size
-+                    + marshalled_sensitive_size_info
-+                    + pubname->size;
-+    size_t digest_size_info = 0;
-+    UINT16 hash_size = tpm2_alg_util_get_hash_size(name_alg);
-+    Tss2_MU_UINT16_Marshal(hash_size, marshalled_sensitive_and_name_digest,
-+            sizeof(uint16_t), &digest_size_info);
-+
-+    digester d = tpm2_openssl_halg_to_digester(name_alg);
-+    d(buffer_marshalled_sensitiveArea,
-+            marshalled_sensitive_size_info + marshalled_sensitive_size
-+                    + pubname->size,
-+            marshalled_sensitive_and_name_digest + digest_size_info);
-+
-+    //Inner integrity
-+    encrypted_inner_integrity->size = marshalled_sensitive_size_info
-+            + marshalled_sensitive_size + pubname->size;
-+
-+    return aes_encrypt_buffers(
-+            sym_alg,
-+            enc_sensitive_key->buffer,
-+            marshalled_sensitive_and_name_digest, 
-+            hash_size + digest_size_info,
-+            buffer_marshalled_sensitiveArea, 
-+            marshalled_sensitive_size_info + marshalled_sensitive_size,
-+            encrypted_inner_integrity);
-+}
-+
-+void tpm2_identity_util_calculate_outer_integrity(
-+        TPMI_ALG_HASH parent_name_alg,
-+        TPM2B_NAME *pubname,
-+        TPM2B_MAX_BUFFER *marshalled_sensitive,
-+        TPM2B_MAX_BUFFER *protection_hmac_key,
-+        TPM2B_MAX_BUFFER *protection_enc_key,
-+        TPMT_SYM_DEF_OBJECT *sym_alg,
-+        TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive,
-+        TPM2B_DIGEST *outer_hmac) {
-+
-+    //Calculate dupSensitive
-+    encrypted_duplicate_sensitive->size =
-+            marshalled_sensitive->size;
-+
-+    aes_encrypt_buffers(
-+            sym_alg,
-+            protection_enc_key->buffer,
-+            marshalled_sensitive->buffer,
-+            marshalled_sensitive->size,
-+            NULL, 0,
-+            encrypted_duplicate_sensitive);
-+    //Calculate outerHMAC
-+    hmac_outer_integrity(
-+            parent_name_alg,
-+            encrypted_duplicate_sensitive->buffer,
-+            encrypted_duplicate_sensitive->size,
-+            pubname->name,
-+            pubname->size, 
-+            protection_hmac_key->buffer,
-+            outer_hmac);
-+}
-diff --git a/lib/tpm2_identity_util.h b/lib/tpm2_identity_util.h
-new file mode 100644
-index 00000000000..49f231a3347
---- /dev/null
-+++ b/lib/tpm2_identity_util.h
-@@ -0,0 +1,141 @@
-+//**********************************************************************;
-+// Copyright (c) 2017, Intel Corporation
-+// Copyright (c) 2019 Massachusetts Institute of Technology
-+// All rights reserved.
-+//
-+// Redistribution and use in source and binary forms, with or without
-+// modification, are permitted provided that the following conditions are met:
-+//
-+// 1. Redistributions of source code must retain the above copyright notice,
-+// this list of conditions and the following disclaimer.
-+//
-+// 2. Redistributions in binary form must reproduce the above copyright notice,
-+// this list of conditions and the following disclaimer in the documentation
-+// and/or other materials provided with the distribution.
-+//
-+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+// THE POSSIBILITY OF SUCH DAMAGE.
-+//**********************************************************************
-+
-+#ifndef LIB_TPM2_IDENTITY_UTIL_H_
-+#define LIB_TPM2_IDENTITY_UTIL_H_
-+
-+#include <tss2/tss2_sys.h>
-+
-+#include <openssl/err.h>
-+#include <openssl/hmac.h>
-+#include <openssl/rsa.h>
-+
-+
-+/**
-+ * Generates HMAC integrity and symmetric encryption keys for TPM2 identies.
-+ *
-+ * @param parent_pub
-+ *  The public key used for seed generation and protection.
-+ * @param pubname
-+ *  The Name object associated with the parent_pub credential.
-+ * @param protection_seed
-+ *  The symmetric seed value used to generate protection keys.
-+ * @param protection_hmac_key
-+ *  The HMAC integrity key to populate.
-+ * @param protection_enc_key
-+ *  The symmetric encryption key to populate.
-+ * @return
-+ *  True on success, false on failure.
-+ */
-+bool tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(
-+        TPM2B_PUBLIC *parent_pub,
-+        TPM2B_NAME *pubname,
-+        TPM2B_DIGEST *protection_seed,
-+        TPM2B_MAX_BUFFER *protection_hmac_key,
-+        TPM2B_MAX_BUFFER *protection_enc_key);
-+
-+/**
-+ * Encrypts seed with parent public key for TPM2 credential protection process.
-+ *
-+ * @param protection_seed
-+ *  The identity structure protection seed that is to be encrypted.
-+ * @param parent_pub
-+ *  The public key used for encryption.
-+ * @param label
-+ *  Indicates label for the seed, such as "IDENTITY" or "DUPLICATE".
-+ * @param labelLen
-+ *  Length of label.
-+ * @param encrypted_protection_seed
-+ *  The encrypted protection seed to populate.
-+ * @return
-+ *  True on success, false on failure.
-+ */
-+bool tpm2_identity_util_encrypt_seed_with_public_key(
-+        TPM2B_DIGEST *protection_seed,
-+        TPM2B_PUBLIC *parent_pub,
-+        unsigned char *label,
-+        int labelLen,
-+        TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed);
-+
-+/**
-+ * Marshalls Credential Value and encrypts it with the symmetric encryption key.
-+ *
-+ * @param name_alg
-+ *  Hash algorithm used to compute Name of the public key.
-+ * @param sensitive
-+ *  The Credential Value to be marshalled and encrypted with symmetric key.
-+ * @param pubname
-+ *  The Name object corresponding to the public key.
-+ * @param enc_sensitive_key
-+ *  The symmetric encryption key.
-+ * @param sym_alg
-+ *  The algorithm used for the symmetric encryption key.
-+ * @param encrypted_inner_integrity
-+ *  The encrypted, marshalled Credential Value to populate.
-+ * @return
-+ *  True on success, false on failure.
-+ */
-+bool tpm2_identity_util_calculate_inner_integrity(
-+        TPMI_ALG_HASH name_alg,
-+        TPM2B_SENSITIVE *sensitive,
-+        TPM2B_NAME *pubname,
-+        TPM2B_DATA *enc_sensitive_key,
-+        TPMT_SYM_DEF_OBJECT *sym_alg,
-+        TPM2B_MAX_BUFFER *encrypted_inner_integrity);
-+
-+/**
-+ * Encrypts Credential Value with enc key and calculates HMAC with hmac key.
-+ *
-+ * @param parent_name_alg
-+ *  Hash algorithm used to compute Name of the public key.
-+ * @param pubname
-+ *  The Name object corresponding to the public key.
-+ * @param marshalled_sensitive
-+ *  Marshalled Credential Value to be encrypted with symmetric encryption key.
-+ * @param protection_hmac_key
-+ *  The HMAC integrity key.
-+ * @param protection_enc_key
-+ *  The symmetric encryption key.
-+ * @param sym_alg
-+ *  The algorithm used for the symmetric encryption key.
-+ * @param encrypted_duplicate_sensitive
-+ *  The encrypted Credential Value to populate.
-+ * @param outer_hmac
-+ *  The outer HMAC structure to populate.
-+ */
-+void tpm2_identity_util_calculate_outer_integrity(
-+        TPMI_ALG_HASH parent_name_alg,
-+        TPM2B_NAME *pubname,
-+        TPM2B_MAX_BUFFER *marshalled_sensitive,
-+        TPM2B_MAX_BUFFER *protection_hmac_key,
-+        TPM2B_MAX_BUFFER *protection_enc_key,
-+        TPMT_SYM_DEF_OBJECT *sym_alg,
-+        TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive,
-+        TPM2B_DIGEST *outer_hmac);
-+
-+#endif /* LIB_TPM2_IDENTITY_UTIL_H_ */
-diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c
-new file mode 100644
-index 00000000000..0bfc95bd1ef
---- /dev/null
-+++ b/lib/tpm2_openssl.c
-@@ -0,0 +1,162 @@
-+//**********************************************************************;
-+// Copyright (c) 2017, Intel Corporation
-+// All rights reserved.
-+//
-+// Redistribution and use in source and binary forms, with or without
-+// modification, are permitted provided that the following conditions are met:
-+//
-+// 1. Redistributions of source code must retain the above copyright notice,
-+// this list of conditions and the following disclaimer.
-+//
-+// 2. Redistributions in binary form must reproduce the above copyright notice,
-+// this list of conditions and the following disclaimer in the documentation
-+// and/or other materials provided with the distribution.
-+//
-+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+// THE POSSIBILITY OF SUCH DAMAGE.
-+//**********************************************************************
-+
-+#include <errno.h>
-+#include <stdint.h>
-+#include <string.h>
-+
-+#include <openssl/aes.h>
-+#include <openssl/bn.h>
-+#include <openssl/evp.h>
-+#include <openssl/err.h>
-+#include <openssl/hmac.h>
-+#include <openssl/obj_mac.h>
-+#include <openssl/pem.h>
-+#include <openssl/rand.h>
-+#include <openssl/rsa.h>
-+
-+#include <tss2/tss2_sys.h>
-+
-+#include "files.h"
-+#include "log.h"
-+#include "tpm2_alg_util.h"
-+#include "tpm2_openssl.h"
-+#include "tpm2_util.h"
-+
-+
-+const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm) {
-+
-+    switch (algorithm) {
-+    case TPM2_ALG_SHA1:
-+        return EVP_sha1();
-+    case TPM2_ALG_SHA256:
-+        return EVP_sha256();
-+    case TPM2_ALG_SHA384:
-+        return EVP_sha384();
-+    case TPM2_ALG_SHA512:
-+        return EVP_sha512();
-+    default:
-+        return NULL;
-+    }
-+    /* no return, not possible */
-+}
-+
-+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
-+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
-+
-+    if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) {
-+        return 0;
-+    }
-+
-+    if (n != NULL) {
-+        BN_free(r->n);
-+        r->n = n;
-+    }
-+
-+    if (e != NULL) {
-+        BN_free(r->e);
-+        r->e = e;
-+    }
-+
-+    if (d != NULL) {
-+        BN_free(r->d);
-+        r->d = d;
-+    }
-+
-+    return 1;
-+}
-+#endif
-+
-+static inline const char *get_openssl_err(void) {
-+    return ERR_error_string(ERR_get_error(), NULL);
-+}
-+
-+
-+EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void) {
-+    EVP_CIPHER_CTX *ctx;
-+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
-+    ctx = malloc(sizeof(*ctx));
-+#else
-+    ctx = EVP_CIPHER_CTX_new();
-+#endif
-+    if (!ctx)
-+        return NULL;
-+
-+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
-+    EVP_CIPHER_CTX_init(ctx);
-+#endif
-+
-+    return ctx;
-+}
-+
-+void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx) {
-+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
-+    EVP_CIPHER_CTX_cleanup(ctx);
-+    free(ctx);
-+#else
-+    EVP_CIPHER_CTX_free(ctx);
-+#endif
-+}
-+
-+digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg) {
-+
-+    switch(halg) {
-+    case TPM2_ALG_SHA1:
-+        return SHA1;
-+    case TPM2_ALG_SHA256:
-+        return SHA256;
-+    case TPM2_ALG_SHA384:
-+        return SHA384;
-+    case TPM2_ALG_SHA512:
-+        return SHA512;
-+    /* no default */
-+    }
-+
-+    return NULL;
-+}
-+
-+/*
-+ * Per man openssl(1), handle the following --passin formats:
-+ *     pass:password
-+ *             the actual password is password. Since the password is visible to utilities (like 'ps' under Unix) this form should only be used where security is not
-+ *             important.
-+ *
-+ *   env:var   obtain the password from the environment variable var. Since the environment of other processes is visible on certain platforms (e.g. ps under certain
-+ *             Unix OSes) this option should be used with caution.
-+ *
-+ *   file:pathname
-+ *             the first line of pathname is the password. If the same pathname argument is supplied to -passin and -passout arguments then the first line will be used
-+ *             for the input password and the next line for the output password. pathname need not refer to a regular file: it could for example refer to a device or
-+ *             named pipe.
-+ *
-+ *   fd:number read the password from the file descriptor number. This can be used to send the data via a pipe for example.
-+ *
-+ *   stdin     read the password from standard input.
-+ *
-+ */
-+
-+typedef bool (*pfn_ossl_pw_handler)(const char *passin, char **pass);
-diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h
-new file mode 100644
-index 00000000000..d749cb350ac
---- /dev/null
-+++ b/lib/tpm2_openssl.h
-@@ -0,0 +1,108 @@
-+//**********************************************************************;
-+// Copyright (c) 2017, Intel Corporation
-+// All rights reserved.
-+//
-+// Redistribution and use in source and binary forms, with or without
-+// modification, are permitted provided that the following conditions are met:
-+//
-+// 1. Redistributions of source code must retain the above copyright notice,
-+// this list of conditions and the following disclaimer.
-+//
-+// 2. Redistributions in binary form must reproduce the above copyright notice,
-+// this list of conditions and the following disclaimer in the documentation
-+// and/or other materials provided with the distribution.
-+//
-+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+// THE POSSIBILITY OF SUCH DAMAGE.
-+//**********************************************************************
-+
-+#ifndef LIB_TPM2_OPENSSL_H_
-+#define LIB_TPM2_OPENSSL_H_
-+
-+#include <tss2/tss2_sys.h>
-+
-+#include <openssl/err.h>
-+#include <openssl/hmac.h>
-+#include <openssl/rsa.h>
-+
-+#if (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) /* OpenSSL 1.1.0 */
-+#define LIB_TPM2_OPENSSL_OPENSSL_PRE11
-+#endif
-+
-+
-+#if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
-+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
-+#endif
-+
-+
-+/**
-+ * Function prototype for a hashing routine.
-+ *
-+ * This is a wrapper around OSSL SHA256|384 and etc digesters.
-+ *
-+ * @param d
-+ *  The data to digest.
-+ * @param n
-+ *  The length of the data to digest.
-+ * @param md
-+ *  The output message digest.
-+ * @return
-+ * A pointer to the digest or NULL on error.
-+ */
-+typedef unsigned char *(*digester)(const unsigned char *d, size_t n, unsigned char *md);
-+
-+/**
-+ * Get an openssl message digest from a tpm hashing algorithm.
-+ * @param algorithm
-+ *  The tpm algorithm to get the corresponding openssl version of.
-+ * @return
-+ *  A pointer to a message digester or NULL on failure.
-+ */
-+const EVP_MD *tpm2_openssl_halg_from_tpmhalg(TPMI_ALG_HASH algorithm);
-+
-+/**
-+ * Obtains an OpenSSL EVP_CIPHER_CTX dealing with version
-+ * API changes in OSSL.
-+ *
-+ * @return
-+ *  An Initialized OpenSSL EVP_CIPHER_CTX.
-+ */
-+EVP_CIPHER_CTX *tpm2_openssl_cipher_new(void);
-+
-+/**
-+ * Free's an EVP_CIPHER_CTX obtained via tpm2_openssl_cipher_new()
-+ * dealing with OSSL API version changes.
-+ * @param ctx
-+ *  The EVP_CIPHER_CTX to free.
-+ */
-+void tpm2_openssl_cipher_free(EVP_CIPHER_CTX *ctx);
-+
-+/**
-+ * Returns a function pointer capable of performing the
-+ * given digest from a TPMI_HASH_ALG.
-+ *
-+ * @param halg
-+ *  The hashing algorithm to use.
-+ * @return
-+ *  NULL on failure or a valid digester on success.
-+ */
-+digester tpm2_openssl_halg_to_digester(TPMI_ALG_HASH halg);
-+
-+typedef enum tpm2_openssl_load_rc tpm2_openssl_load_rc;
-+enum tpm2_openssl_load_rc {
-+    lprc_error     = 0,      /* an error has occurred */
-+    lprc_private   = 1 << 0, /* successfully loaded a private portion of object */
-+    lprc_public    = 1 << 1, /* successfully loaded a public portion of object */
-+};
-+
-+
-+#endif /* LIB_TPM2_OPENSSL_H_ */
-diff --git a/lib/tpm2_options.c b/lib/tpm2_options.c
-index c2962ee95d4..8c3f36cacea 100644
---- a/lib/tpm2_options.c
-+++ b/lib/tpm2_options.c
-@@ -268,9 +268,8 @@ static char* parse_socket_tcti(void) {
- 
- static tcti_conf tcti_get_config(const char *optstr) {
- 
--    tcti_conf conf = {
--        .name = NULL
--    };
-+    /* set up the default configuration */
-+    tcti_conf conf = { 0 };
- 
-     /* no tcti config supplied, get it from env */
-     if (!optstr) {
-@@ -294,6 +293,11 @@ static tcti_conf tcti_get_config(const char *optstr) {
-             }
-         }
-     } else {
-+        /* handle case of TCTI set as "-T none" */
-+        if (!strcmp(optstr, "none")) {
-+            return conf;
-+        }
-+
-         parse_env_tcti(optstr, &conf);
-     }
- 
-@@ -400,7 +404,7 @@ tpm2_option_code tpm2_handle_options (int argc, char **argv,
-      * grep -rn case\ \'[a-zA-Z]\' | awk '{print $3}' | sed s/\'//g | sed s/\://g | sort | uniq | less
-      */
-     struct option long_options [] = {
--        { "tcti",          required_argument, NULL, 'T' },
-+        { "tcti",          optional_argument, NULL, 'T' },
-         { "help",          no_argument,       NULL, 'h' },
-         { "verbose",       no_argument,       NULL, 'V' },
-         { "quiet",         no_argument,       NULL, 'Q' },
-@@ -492,17 +496,23 @@ tpm2_option_code tpm2_handle_options (int argc, char **argv,
-     if (!tool_opts || !(tool_opts->flags & TPM2_OPTIONS_NO_SAPI)) {
-         tcti_conf conf = tcti_get_config(tcti_conf_option);
- 
--        *tcti = tpm2_tcti_ldr_load(conf.name, conf.opts);
--        if (!*tcti) {
--            LOG_ERR("Could not load tcti, got: \"%s\"", conf.name);
--            goto out;
--        }
-+        /* name can be NULL for optional SAPI tools */
-+        if (conf.name) {
-+            *tcti = tpm2_tcti_ldr_load(conf.name, conf.opts);
-+            if (!*tcti) {
-+                LOG_ERR("Could not load tcti, got: \"%s\"", conf.name);
-+                goto out;
-+            }
- 
--        if (!flags->enable_errata) {
--            flags->enable_errata = !!getenv (TPM2TOOLS_ENV_ENABLE_ERRATA);
-+            if (!flags->enable_errata) {
-+                flags->enable_errata = !!getenv (TPM2TOOLS_ENV_ENABLE_ERRATA);
-+            }
-+            free(conf.name);
-+            free(conf.opts);
-+        } else if (!tool_opts || !(tool_opts->flags & TPM2_OPTIONS_OPTIONAL_SAPI)) {
-+            LOG_ERR("Requested no tcti, but tool requires TCTI.");
-+            goto out;
-         }
--        free(conf.name);
--        free(conf.opts);
-     }
- 
-     rc = tpm2_option_code_continue;
-diff --git a/lib/tpm2_options.h b/lib/tpm2_options.h
-index 860d9b0deee..e16c5205044 100644
---- a/lib/tpm2_options.h
-+++ b/lib/tpm2_options.h
-@@ -105,6 +105,7 @@ typedef bool (*tpm2_arg_handler)(int argc, char **argv);
-  */
- #define TPM2_OPTIONS_SHOW_USAGE 0x1
- #define TPM2_OPTIONS_NO_SAPI 0x2
-+#define TPM2_OPTIONS_OPTIONAL_SAPI 0x4
- 
- struct tpm2_options {
-     struct {
-diff --git a/man/common/tcti.md b/man/common/tcti.md
-index fd5f1683dfe..0cb06e3c403 100644
---- a/man/common/tcti.md
-+++ b/man/common/tcti.md
-@@ -18,6 +18,10 @@ The variables respected depend on how the software was configured.
- 	* socket - Typically used with the old resource manager, or talking directly to
- 	           a simulator.
- 	* device - Used when talking directly to a TPM device file.
-+	* none   - Do not initialize a connection with the TPM. Some tools allow for off-tpm
-+               options and thus support not using a TCTI. Tools that do not support it
-+               will error when attempted to be used without a TCTI connection. Does not
-+               support *ANY* options and *MUST BE* presented as the exact text of "none".
- 
-   * _TPM2TOOLS\_DEVICE\_FILE_:
- 	When using the device TCTI, specify the TPM device file. The default is
-diff --git a/man/tpm2_activatecredential.1.md b/man/tpm2_activatecredential.1.md
-index 25478790baf..b15569ae5cf 100644
---- a/man/tpm2_activatecredential.1.md
-+++ b/man/tpm2_activatecredential.1.md
-@@ -56,7 +56,7 @@ These options control the object verification:
- ```
- tpm2_activatecredential -H 0x81010002 -k 0x81010001 -P abc123 -e abc123 -f <filePath> -o <filePath>
- tpm2_activatecredential -c ak.context -C ek.context -P abc123 -e abc123 -f <filePath> -o <filePath>
--tpm2_activatecredential -H 0x81010002 -k 0x81010001 -P 123abc -e 1a1b1c -X -f <filePath> -o <filePath>
-+tpm2_activatecredential -H 0x81010002 -k 0x81010001 -P 123abc -e 1a1b1c -f <filePath> -o <filePath>
- ```
- 
- # RETURNS
-diff --git a/man/tpm2_certify.1.md b/man/tpm2_certify.1.md
-index fba4a8f7c65..f4a78c70c00 100644
---- a/man/tpm2_certify.1.md
-+++ b/man/tpm2_certify.1.md
-@@ -71,7 +71,7 @@ These options control the ceritifcation:
- ```
- tpm2_certify -H 0x81010002 -k 0x81010001 -P 0x0011 -K 0x00FF -g 0x00B -a <fileName> -s <fileName>
- tpm2_certify -C obj.context -c key.context -P 0x0011 -K 0x00FF -g 0x00B -a <fileName> -s <fileName>
--tpm2_certify -H 0x81010002 -k 0x81010001 -P 0011 -K 00FF -X -g 0x00B -a <fileName> -s <fileName>
-+tpm2_certify -H 0x81010002 -k 0x81010001 -P 0011 -K 00FF -g 0x00B -a <fileName> -s <fileName>
- ```
- 
- # RETURNS
-diff --git a/man/tpm2_create.1.md b/man/tpm2_create.1.md
-index f6aed4a7756..51d71db2c75 100644
---- a/man/tpm2_create.1.md
-+++ b/man/tpm2_create.1.md
-@@ -86,7 +86,7 @@ These options for creating the tpm entity:
- ```
- tpm2_create -H 0x81010001 -P abc123 -K def456 -g sha256 -G keyedhash-I data.File
- tpm2_create -c parent.context -P abc123 -K def456 -g sha256 -G keyedhash -I data.File
--tpm2_create -H 0x81010001 -P 123abc -K 456def -X -g sha256 -G keyedhash -I data.File
-+tpm2_create -H 0x81010001 -P 123abc -K 456def -g sha256 -G keyedhash -I data.File
- ```
- 
- # RETURNS
-diff --git a/man/tpm2_encryptdecrypt.1.md b/man/tpm2_encryptdecrypt.1.md
-index ea349bec1e8..350737182dd 100644
---- a/man/tpm2_encryptdecrypt.1.md
-+++ b/man/tpm2_encryptdecrypt.1.md
-@@ -48,7 +48,7 @@ specified symmetric key.
- ```
- tpm2_encryptdecrypt -k 0x81010001 -P abc123 -D NO -I <filePath> -o <filePath>
- tpm2_encryptdecrypt -c key.context -P abc123 -D NO -I <filePath> -o <filePath>
--tpm2_encryptdecrypt -k 0x81010001 -P 123abca -X -D NO -I <filePath> -o <filePath>
-+tpm2_encryptdecrypt -k 0x81010001 -P 123abca -D NO -I <filePath> -o <filePath>
- ```
- 
- # RETURNS
-diff --git a/man/tpm2_getpubak.1.md b/man/tpm2_getpubak.1.md
-index 22ade8f0b33..1a71b49c110 100644
---- a/man/tpm2_getpubak.1.md
-+++ b/man/tpm2_getpubak.1.md
-@@ -80,7 +80,7 @@ loaded-key:
- 
- ```
- tpm2_getpubak -e abc123 -P abc123 -o passwd -E 0x81010001 -k 0x81010002 -f ./ak.pub -n ./ak.name
--tpm2_getpubak -e 1a1b1c -P 123abc -o 1a1b1c -X -E 0x81010001 -k 0x81010002 -f ./ak.pub -n ./ak.name
-+tpm2_getpubak -e 1a1b1c -P 123abc -o 1a1b1c -E 0x81010001 -k 0x81010002 -f ./ak.pub -n ./ak.name
- ```
- 
- # RETURNS
-diff --git a/man/tpm2_makecredential.1.md b/man/tpm2_makecredential.1.md
-index 736ead591b8..1008682fe7f 100644
---- a/man/tpm2_makecredential.1.md
-+++ b/man/tpm2_makecredential.1.md
-@@ -14,7 +14,8 @@ TPM.
- # DESCRIPTION
- 
- **tpm2_makecredential**(1) - Use a TPM public key to protect a secret that is used
--to encrypt the AK certififcate.
-+to encrypt the AK certificate.  This can be used without a TPM by using 
-+the **none** TCTI option.
- 
- # OPTIONS
- 
-diff --git a/test/system/test_tpm2_makecredential.sh b/test/system/test_tpm2_makecredential.sh
-index cc920ccae07..84f77b3647b 100755
---- a/test/system/test_tpm2_makecredential.sh
-+++ b/test/system/test_tpm2_makecredential.sh
-@@ -72,4 +72,6 @@ Loadkeyname=`cat $output_ak_pub_name | xxd -p -c $file_size`
- 
- tpm2_makecredential -Q -e $output_ek_pub  -s $file_input_data  -n $Loadkeyname -o $output_mkcredential
- 
-+tpm2_makecredential -T none -Q -e $output_ek_pub  -s $file_input_data  -n $Loadkeyname -o $output_mkcredential
-+
- exit 0
-diff --git a/tools/tpm2_makecredential.c b/tools/tpm2_makecredential.c
-index c8f49fe0207..259d39f30f3 100644
---- a/tools/tpm2_makecredential.c
-+++ b/tools/tpm2_makecredential.c
-@@ -1,5 +1,6 @@
- //**********************************************************************;
- // Copyright (c) 2015-2018, Intel Corporation
-+// Copyright (c) 2019 Massachusetts Institute of Technology
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
-@@ -38,12 +39,15 @@
- 
- #include <tss2/tss2_sys.h>
- #include <tss2/tss2_mu.h>
-+#include <openssl/rand.h>
- 
- #include "files.h"
- #include "tpm2_options.h"
- #include "log.h"
- #include "files.h"
--#include "tpm2_options.h"
-+#include "tpm2_alg_util.h"
-+#include "tpm2_openssl.h"
-+#include "tpm2_identity_util.h"
- #include "tpm2_tool.h"
- #include "tpm2_util.h"
- 
-@@ -117,6 +121,93 @@ out:
-     return result;
- }
- 
-+static bool make_external_credential_and_save() {
-+
-+    /*
-+     * Get name_alg from the public key
-+     */
-+    TPMI_ALG_HASH name_alg = ctx.public.publicArea.nameAlg;
-+
-+
-+    /* 
-+     * Generate and encrypt seed
-+     */
-+    TPM2B_DIGEST seed = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
-+    seed.size = tpm2_alg_util_get_hash_size(name_alg);
-+    RAND_bytes(seed.buffer, seed.size);
-+
-+    TPM2B_ENCRYPTED_SECRET encrypted_seed = TPM2B_EMPTY_INIT;
-+    unsigned char label[10] = { 'I', 'D', 'E', 'N', 'T', 'I', 'T', 'Y', 0 };
-+    bool res = tpm2_identity_util_encrypt_seed_with_public_key(&seed,
-+            &ctx.public, label, 9,
-+            &encrypted_seed);
-+    if (!res) {
-+        LOG_ERR("Failed Seed Encryption\n");
-+        return false;
-+    }
-+
-+    /* 
-+     * Perform identity structure calculations (off of the TPM)
-+     */
-+    TPM2B_MAX_BUFFER hmac_key;
-+    TPM2B_MAX_BUFFER enc_key;
-+    tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(
-+            &ctx.public,
-+            &ctx.object_name,
-+            &seed,
-+            &hmac_key,
-+            &enc_key);
-+
-+    /*
-+     * The ctx.credential needs to be marshalled into struct with 
-+     * both size and contents together (to be encrypted as a block)
-+     */
-+    TPM2B_MAX_BUFFER marshalled_inner_integrity = TPM2B_EMPTY_INIT;
-+    marshalled_inner_integrity.size = ctx.credential.size + sizeof(ctx.credential.size);
-+    UINT16 credSize = ctx.credential.size;
-+    if (!tpm2_util_is_big_endian()) {
-+        credSize = tpm2_util_endian_swap_16(credSize);
-+    }
-+    memcpy(marshalled_inner_integrity.buffer, &credSize, sizeof(credSize));
-+    memcpy(&marshalled_inner_integrity.buffer[2], ctx.credential.buffer, ctx.credential.size);
-+
-+    /*
-+     * Perform inner encryption (encIdentity) and outer HMAC (outerHMAC)
-+     */
-+    TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT;
-+    TPM2B_MAX_BUFFER encrypted_sensitive = TPM2B_EMPTY_INIT;
-+    tpm2_identity_util_calculate_outer_integrity(
-+            name_alg,
-+            &ctx.object_name,
-+            &marshalled_inner_integrity,
-+            &hmac_key,
-+            &enc_key,
-+            &ctx.public.publicArea.parameters.rsaDetail.symmetric,
-+            &encrypted_sensitive,
-+            &outer_hmac);
-+
-+    /*
-+     * Package up the info to save
-+     * cred_bloc = outer_hmac || encrypted_sensitive
-+     * secret = encrypted_seed (with pubEK)
-+     */
-+    TPM2B_ID_OBJECT cred_blob = TPM2B_TYPE_INIT(TPM2B_ID_OBJECT, credential);
-+
-+    UINT16 outer_hmac_size = outer_hmac.size;
-+    if (!tpm2_util_is_big_endian()) {
-+        outer_hmac_size = tpm2_util_endian_swap_16(outer_hmac_size);
-+    }
-+    int offset = 0;
-+    memcpy(cred_blob.credential + offset, &outer_hmac_size, sizeof(outer_hmac.size));offset += sizeof(outer_hmac.size);
-+    memcpy(cred_blob.credential + offset, outer_hmac.buffer, outer_hmac.size);offset += outer_hmac.size;
-+    //NOTE: do NOT include the encrypted_sensitive size, since it is encrypted with the blob!
-+    memcpy(cred_blob.credential + offset, encrypted_sensitive.buffer, encrypted_sensitive.size);
-+
-+    cred_blob.size = outer_hmac.size + encrypted_sensitive.size + sizeof(outer_hmac.size);
-+
-+    return write_cred_and_secret(ctx.out_file_path, &cred_blob, &encrypted_seed);
-+}
-+
- static bool make_credential_and_save(TSS2_SYS_CONTEXT *sapi_context)
- {
-     TSS2L_SYS_AUTH_RESPONSE sessions_data_out;
-@@ -198,7 +289,8 @@ bool tpm2_tool_onstart(tpm2_options **opts) {
-     };
- 
-     *opts = tpm2_options_new("e:s:n:o:", ARRAY_LEN(topts), topts,
--            on_option, NULL, TPM2_OPTIONS_SHOW_USAGE);
-+            on_option, NULL, 
-+            TPM2_OPTIONS_SHOW_USAGE | TPM2_OPTIONS_OPTIONAL_SAPI);
- 
-     return *opts != NULL;
- }
-@@ -212,5 +304,10 @@ int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
-         return false;
-     }
- 
--    return make_credential_and_save(sapi_context) != true;
-+    printf("make credential has SAPI CTX: %p", sapi_context);
-+
-+    bool result = sapi_context ? make_credential_and_save(sapi_context) : 
-+            make_external_credential_and_save();
-+
-+    return result != true;
- }
--- 
-2.21.0
-
diff --git a/Add-attestation-test-which-ensures-full-attestation-.patch b/Add-attestation-test-which-ensures-full-attestation-.patch
deleted file mode 100644
index 2424416..0000000
--- a/Add-attestation-test-which-ensures-full-attestation-.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-From 70733e919aaa72aa03cccf6cd453bbe0da752de1 Mon Sep 17 00:00:00 2001
-From: jetwhiz <Charles.Munson@ll.mit.edu>
-Date: Tue, 9 Apr 2019 17:57:36 -0400
-Subject: [PATCH] Add attestation test, which ensures full attestation
- process works
-
-Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
----
- test/system/test_attestation.sh | 125 ++++++++++++++++++++++++++++++++
- 1 file changed, 125 insertions(+)
- create mode 100755 test/system/test_attestation.sh
-
-diff --git a/test/system/test_attestation.sh b/test/system/test_attestation.sh
-new file mode 100755
-index 00000000000..ea9da13a419
---- /dev/null
-+++ b/test/system/test_attestation.sh
-@@ -0,0 +1,125 @@
-+#!/bin/bash
-+#;**********************************************************************;
-+#
-+# Copyright (c) 2019 Massachusetts Institute of Technology.
-+# All rights reserved.
-+#
-+# Redistribution and use in source and binary forms, with or without
-+# modification, are permitted provided that the following conditions are met:
-+#
-+# 1. Redistributions of source code must retain the above copyright notice,
-+# this list of conditions and the following disclaimer.
-+#
-+# 2. Redistributions in binary form must reproduce the above copyright notice,
-+# this list of conditions and the following disclaimer in the documentation
-+# and/or other materials provided with the distribution.
-+#
-+# 3. Neither the name of Intel Corporation nor the names of its contributors
-+# may be used to endorse or promote products derived from this software without
-+# specific prior written permission.
-+#
-+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+# THE POSSIBILITY OF SUCH DAMAGE.
-+#;**********************************************************************;
-+
-+source test_helpers.sh
-+
-+handle_ek=0x81010007
-+handle_ak=0x81010008
-+handle_nv=0x1500018
-+handle_hier=0x40000001
-+ek_alg=rsa
-+ak_alg=rsa
-+digestAlg=sha256
-+signAlg=rsassa
-+ownerpw=ownerpass
-+endorsepw=endorsepass
-+ekpw=ekpass
-+akpw=akpass
-+
-+file_input_data=secret.data
-+file_input_key=nv.data
-+output_ek_pub_pem=ekpub.pem
-+output_ek_pub=ek.pub
-+output_ak_pub_pem=akpub.pem
-+output_ak_pub=ak.pub
-+output_ak_priv=ak.priv
-+output_ak_pub_name=ak.name
-+output_mkcredential=mkcred.out
-+output_actcredential=actcred.out
-+output_quote=quote.out
-+output_quotesig=quotesig.out
-+output_quotepcr=quotepcr.out
-+
-+cleanup() {
-+  rm -f $output_ak_priv \
-+        $file_input_data $file_input_key $output_ek_pub $output_ek_pub_pem $output_ak_pub \
-+        $output_ak_pub_pem $output_ak_pub_name $output_mkcredential \
-+        $output_actcredential $output_quote $output_quotesig $output_quotepcr rand.out 
-+
-+  tpm2_pcrreset 16
-+  tpm2_evictcontrol -Q -Ao -c $handle_ek 2>/dev/null || true
-+  tpm2_evictcontrol -Q -Ao -c $handle_ak 2>/dev/null || true
-+
-+  tpm2_nvrelease -Q -x $handle_nv -a $handle_hier -P "$ownerpw" 2>/dev/null || true
-+
-+  tpm2_takeownership -c 2>/dev/null || true
-+}
-+trap cleanup EXIT
-+
-+
-+cleanup
-+
-+echo "12345678" > $file_input_data
-+echo "1234567890123456789012345678901" > $file_input_key
-+
-+getrandom() {
-+  tpm2_getrandom -Q -o rand.out $1
-+  local file_size=`stat --printf="%s" rand.out`
-+  loaded_randomness=`cat rand.out | xxd -p -c $file_size`
-+}
-+
-+
-+tpm2_takeownership -o "$ownerpw" -e "$endorsepw"
-+
-+# Key generation
-+tpm2_getpubek -Q -H $handle_ek -g $ek_alg -f $output_ek_pub -P "$ekpw" -o "$ownerpw" -e "$endorsepw"
-+tpm2_readpublic -Q -H $handle_ek -o $output_ek_pub_pem -f pem
-+tpm2_getpubak -Q -E $handle_ek -k $handle_ak -g $ak_alg -D $digestAlg -s $signAlg -f $output_ak_pub -n $output_ak_pub_name -e "$endorsepw" -P "$akpw" -o "$ownerpw"
-+tpm2_readpublic -Q -H $handle_ak -o $output_ak_pub_pem -f pem
-+
-+# Validate keys (registrar)
-+file_size=`stat --printf="%s" $output_ak_pub_name`
-+loaded_key_name=`cat $output_ak_pub_name | xxd -p -c $file_size`
-+tpm2_makecredential -Q -T none -e $output_ek_pub  -s $file_input_data -n $loaded_key_name -o $output_mkcredential 
-+tpm2_activatecredential -Q -H $handle_ak -k $handle_ek -f $output_mkcredential -o $output_actcredential -P "$akpw" -e "$endorsepw"
-+diff $file_input_data $output_actcredential
-+
-+
-+# Quoting
-+tpm2_pcrreset -Q 16
-+tpm2_pcrextend -Q 16:sha256=6ea40aa7267bb71251c1de1c3605a3df759b86b22fa9f62aa298d4197cd88a38
-+tpm2_pcrlist -Q
-+getrandom 20
-+tpm2_quote -Q -k $handle_ak -L $digestAlg:15,16,22 -q $loaded_randomness -m $output_quote -s $output_quotesig -p $output_quotepcr -G $digestAlg -P "$akpw"
-+
-+
-+# Verify quote
-+tpm2_checkquote -Q -c $output_ak_pub_pem -m $output_quote -s $output_quotesig -p $output_quotepcr -G $digestAlg -q $loaded_randomness
-+
-+
-+# Save U key from verifier
-+tpm2_nvdefine -Q -x $handle_nv -a $handle_hier -s 32 -t "ownerread|policywrite|ownerwrite" -I "indexpass" -P "$ownerpw"
-+tpm2_nvwrite -Q -x $handle_nv -a $handle_hier -P "$ownerpw" $file_input_key
-+tpm2_nvread -Q -x $handle_nv -a $handle_hier -s 32 -P "$ownerpw"
-+
-+exit 0
--- 
-2.21.0
-
diff --git a/Fix-ups-in-tpm2_quote.md.1.patch b/Fix-ups-in-tpm2_quote.md.1.patch
deleted file mode 100644
index 00ee2e8..0000000
--- a/Fix-ups-in-tpm2_quote.md.1.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 6c25de22d981d26d0ae80d99706f86c52f713b06 Mon Sep 17 00:00:00 2001
-From: jetwhiz <Charles.Munson@ll.mit.edu>
-Date: Fri, 3 May 2019 13:46:41 -0400
-Subject: [PATCH] Fix-ups in tpm2_quote.md.1
-
-Capitalization fixes to follow preferred format
-
-Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
----
- man/tpm2_quote.1.md | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/man/tpm2_quote.1.md b/man/tpm2_quote.1.md
-index 491848201d9..c926f4d045d 100644
---- a/man/tpm2_quote.1.md
-+++ b/man/tpm2_quote.1.md
-@@ -41,12 +41,12 @@
- 
-   * **-m**, **--message**:
- 
--    message output file, records the quote message that makes up the data that
-+    Message output file, records the quote message that makes up the data that
-     is signed by the TPM.
- 
-   * **-s**, **--signature**:
- 
--    signature output file, records the signature in the format specified via the **-f**
-+    Signature output file, records the signature in the format specified via the **-f**
-     option.
- 
-   * **-f**, **--format**
--- 
-2.21.0
-
diff --git a/Update-CHANGELOG.md.patch b/Update-CHANGELOG.md.patch
deleted file mode 100644
index ad330a7..0000000
--- a/Update-CHANGELOG.md.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From edbbe53e225bcc68c6ee0a5a85bec82ae6cdc398 Mon Sep 17 00:00:00 2001
-From: William Roberts <william.c.roberts@intel.com>
-Date: Thu, 2 May 2019 08:44:48 -0700
-Subject: [PATCH] Update CHANGELOG.md
-
----
- CHANGELOG.md | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/CHANGELOG.md b/CHANGELOG.md
-index 19e831d7e7f..a8e4f39afde 100644
---- a/CHANGELOG.md
-+++ b/CHANGELOG.md
-@@ -1,4 +1,9 @@
- ## Changelog
-+### 3.2.0 - next
-+* tpm2_makecredential: add support for executing tool off-TPM.
-+* tpm2_pcrreset: introduce new tool for resetting PCRs.
-+* tpm2_quote: Fix AK auth password not being used.
-+
- ### 3.1.4 - 2019-03-14
-   * Fix various man pages
-   * tpm2_getmanufec: fix OSSL build warnings
--- 
-2.21.0
-
diff --git a/Wire-up-support-for-ak-auth-password-in-tpm2_quote-t.patch b/Wire-up-support-for-ak-auth-password-in-tpm2_quote-t.patch
deleted file mode 100644
index fbb65db..0000000
--- a/Wire-up-support-for-ak-auth-password-in-tpm2_quote-t.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From 993da58a612238bf2dd53a015dfdb2a6c0eb00b9 Mon Sep 17 00:00:00 2001
-From: jetwhiz <Charles.Munson@ll.mit.edu>
-Date: Mon, 22 Apr 2019 09:48:56 -0400
-Subject: [PATCH 1/6] Wire up support for ak auth password in tpm2_quote tool
-
-Add regression test
-
-Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
----
- test/system/test_tpm2_quote.sh |  9 ++++++++-
- tools/tpm2_quote.c             | 11 ++++++++---
- 2 files changed, 16 insertions(+), 4 deletions(-)
-
-diff --git a/test/system/test_tpm2_quote.sh b/test/system/test_tpm2_quote.sh
-index d845ea1bdb1..231bed326ec 100755
---- a/test/system/test_tpm2_quote.sh
-+++ b/test/system/test_tpm2_quote.sh
-@@ -50,6 +50,7 @@ file_quote_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-"$alg_crea
- Handle_ak_quote=0x81010016
- Handle_ek_quote=0x81010017
- Handle_ak_quote2=0x81010018
-+Handle_ak_quote3=0x81010019
- 
- maxdigest=$(tpm2_getcap -c properties-fixed | grep TPM_PT_MAX_DIGEST | sed -r -e 's/.*(0x[0-9a-f]+)/\1/g')
- if ! [[ "$maxdigest" =~ ^(0x)*[0-9]+$ ]] ; then
-@@ -73,6 +74,7 @@ cleanup() {
-     tpm2_evictcontrol -Q -Ao -H $Handle_ek_quote 2>/dev/null || true
-     tpm2_evictcontrol -Q -Ao -H $Handle_ak_quote 2>/dev/null || true
-     tpm2_evictcontrol -Q -Ao -H $Handle_ak_quote2 2>/dev/null || true
-+    tpm2_evictcontrol -Q -Ao -H $Handle_ak_quote3 2>/dev/null || true
- }
- trap cleanup EXIT
- 
-@@ -104,4 +106,9 @@ tpm2_getpubak -Q -E  $Handle_ek_quote -k  $Handle_ak_quote2 -f ak.pub2 -n ak.nam
- 
- tpm2_quote -Q -k $Handle_ak_quote -g $alg_quote -l 16,17,18 -q $nonce
- 
--exit 0
-+#####AK with password
-+tpm2_getpubak -Q -E  $Handle_ek_quote -k  $Handle_ak_quote3 -f ak.pub2 -n ak.name_2 -P abc123
-+
-+tpm2_quote -Q -k $Handle_ak_quote3 -g $alg_quote -l 16,17,18 -q $nonce -P abc123
-+
-+exit 0
-\ No newline at end of file
-diff --git a/tools/tpm2_quote.c b/tools/tpm2_quote.c
-index 3538947db31..05b6d641656 100644
---- a/tools/tpm2_quote.c
-+++ b/tools/tpm2_quote.c
-@@ -50,7 +50,7 @@ typedef struct {
-     UINT32 id[24];
- } PCR_LIST;
- 
--static TPMS_AUTH_COMMAND sessionData;
-+static TPMS_AUTH_COMMAND sessionData = TPMS_AUTH_COMMAND_INIT(TPM2_RS_PW);
- static char *outFilePath;
- static char *signature_path;
- static char *message_path;
-@@ -60,7 +60,7 @@ static TPM2B_DATA qualifyingData = TPM2B_EMPTY_INIT;
- static TPML_PCR_SELECTION  pcrSelections;
- static bool is_auth_session;
- static TPMI_SH_AUTH_SESSION auth_session_handle;
--static int k_flag, c_flag, l_flag, g_flag, L_flag, o_flag, G_flag;
-+static int k_flag, c_flag, l_flag, g_flag, L_flag, o_flag, G_flag, P_flag;
- static char *contextFilePath;
- static TPM2_HANDLE akHandle;
- 
-@@ -94,7 +94,7 @@ static int quote(TSS2_SYS_CONTEXT *sapi_context, TPM2_HANDLE akHandle, TPML_PCR_
- {
-     UINT32 rval;
-     TPMT_SIG_SCHEME inScheme;
--    TSS2L_SYS_AUTH_COMMAND sessionsData = { 1, {{.sessionHandle=TPM2_RS_PW}}};
-+    TSS2L_SYS_AUTH_COMMAND sessionsData = { 1, { sessionData }};
-     TSS2L_SYS_AUTH_RESPONSE sessionsDataOut;
-     TPM2B_ATTEST quoted = TPM2B_TYPE_INIT(TPM2B_ATTEST, attestationData);
-     TPMT_SIGNATURE signature;
-@@ -152,6 +152,7 @@ static bool on_option(char key, char *value) {
-             LOG_ERR("Invalid AK password, got\"%s\"", value);
-             return false;
-         }
-+        P_flag = 1;
-     } break;
-     case 'l':
-         if(!pcr_parse_list(value, strlen(value), &pcrSelections.pcrSelections[0]))
-@@ -265,5 +266,9 @@ int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
-         }
-     }
- 
-+    if (P_flag == 0) {
-+        sessionData.hmac.size = 0;
-+    }
-+
-     return quote(sapi_context, akHandle, &pcrSelections);
- }
--- 
-2.21.0
-
diff --git a/lib-tpm2_util.c-string_to_uint32-ensure-the-string-d.patch b/lib-tpm2_util.c-string_to_uint32-ensure-the-string-d.patch
deleted file mode 100644
index ff0162b..0000000
--- a/lib-tpm2_util.c-string_to_uint32-ensure-the-string-d.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 9685ea263f994537430323fb1681b210395eee7c Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?=
- =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= <git-dpa@aegee.org>
-Date: Tue, 2 Apr 2019 16:18:32 +0000
-Subject: [PATCH] lib/tpm2_util.c:string_to_uint32: ensure the string does not
- overflow in uint32
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Before this change input of "4294967295" generated output of 4294967295, which
-is UINT32_MAX = 2**32 - 1.  But input "4294967296" created output of 0.  The
-function is supposed to fail if the number is too big, rather than silently
-convert unsigned long int to uint32_t, ignoring some bits.
-
-Signed-Off-By: Дилян Палаузов <git-dpa@aegee.org>
----
- lib/tpm2_util.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c
-index edfda4a8b0b..ca9d8b7f4d7 100644
---- a/lib/tpm2_util.c
-+++ b/lib/tpm2_util.c
-@@ -236,8 +236,8 @@ bool tpm2_util_string_to_uint32(const char *str, uint32_t *value) {
- 
-     /* clear errno before the call, should be 0 afterwards */
-     errno = 0;
--    uint32_t tmp = strtoul(str, &endptr, 0);
--    if (errno) {
-+    unsigned long int tmp = strtoul(str, &endptr, 0);
-+    if (errno || tmp > UINT32_MAX) {
-         return false;
-     }
- 
-@@ -250,7 +250,7 @@ bool tpm2_util_string_to_uint32(const char *str, uint32_t *value) {
-         return false;
-     }
- 
--    *value = tmp;
-+    *value = (uint32_t) tmp;
-     return true;
- }
- 
--- 
-2.21.0
-
diff --git a/sources b/sources
index a0560ab..57117aa 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (tpm2-tools-3.1.4.tar.gz) = c5e1be4ffab305ee42a8b4a9c9aa4373158259a58844e273465f97a74f913fb12098b9fd81127148be95ecba7378f6a45b96af256dde3101a237e5e33e8e8ccb
+SHA512 (tpm2-tools-3.2.0.tar.gz) = ab8081ee3ac2d7f445522141395198b1c570b9649a42e4b27b11b0e04495f4c935ee3ec73b228a953934f9dbdf3dccd4640eb62c4e0bae6dd11b91260e67c227
diff --git a/tpm2-tools.spec b/tpm2-tools.spec
index 41bfef4..e0d68bb 100644
--- a/tpm2-tools.spec
+++ b/tpm2-tools.spec
@@ -1,21 +1,12 @@
 Name: tpm2-tools
-Version: 3.1.4
-Release: 2%{?dist}
+Version: 3.2.0
+Release: 1%{?dist}
 Summary: A TPM2.0 testing tool build upon TPM2.0-TSS
 
 License: BSD
 URL:     https://github.com/tpm2-software/tpm2-tools
 Source0: https://github.com/tpm2-software/tpm2-tools/releases/download/%{version}/%{name}-%{version}.tar.gz
 
-Patch0: Wire-up-support-for-ak-auth-password-in-tpm2_quote-t.patch
-Patch1: tpm2_pcrreset-new-tools.patch
-Patch2: Add-ability-to-run-tpm2_makecredential-without-a-TPM.patch
-Patch3: Update-CHANGELOG.md.patch
-Patch4: Add-ability-to-check-quotes-and-output-PCR-values-fo.patch
-Patch5: Add-attestation-test-which-ensures-full-attestation-.patch
-Patch6: Fix-ups-in-tpm2_quote.md.1.patch
-Patch7: lib-tpm2_util.c-string_to_uint32-ensure-the-string-d.patch
-
 BuildRequires: gcc-c++
 BuildRequires: libtool
 BuildRequires: autoconf-archive
@@ -54,6 +45,10 @@ tpm2-tools is a batch of testing tools for tpm2.0. It is based on tpm2-tss.
 %{_mandir}/man1/tpm2_*.1.gz
 
 %changelog
+* Fri Jun 21 2019 Yunying Sun <yunying.sun@intel.com> - 3.2.0-1
+- Update to 3.2.0 release
+- Removed patches since all have been included in 3.2.0 release
+
 * Fri May 10 2019 Javier Martinez Canillas <javierm@redhat.com> - 3.1.4-2
 - Allow tpm2_makecredential to run without a TPM (jetwhiz)
 - Add tpm2_pcrreset and tpm2_checkquote tools (jetwhiz)
diff --git a/tpm2_pcrreset-new-tools.patch b/tpm2_pcrreset-new-tools.patch
deleted file mode 100644
index ba6ca0b..0000000
--- a/tpm2_pcrreset-new-tools.patch
+++ /dev/null
@@ -1,313 +0,0 @@
-From 016ef077a2e81fab14cbcd5ba6fae10a6681688b Mon Sep 17 00:00:00 2001
-From: jetwhiz <charles.munson@ll.mit.edu>
-Date: Mon, 1 Oct 2018 17:55:13 -0400
-Subject: [PATCH 2/6] tpm2_pcrreset new tools
-
-New tool to allow resetting PCR registers, backport from 0ef0f31775
-
-Signed-off-by: jetwhiz <Charles.Munson@ll.mit.edu>
----
- Makefile.am                       |   3 +
- man/tpm2_pcrreset.1.md            |  58 ++++++++++++++
- test/system/test_tpm2_pcrreset.sh |  59 ++++++++++++++
- tools/tpm2_pcrreset.c             | 129 ++++++++++++++++++++++++++++++
- 4 files changed, 249 insertions(+)
- create mode 100644 man/tpm2_pcrreset.1.md
- create mode 100755 test/system/test_tpm2_pcrreset.sh
- create mode 100644 tools/tpm2_pcrreset.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 3856bcb400c..ffe22f383e3 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -87,6 +87,7 @@ bin_PROGRAMS = \
-     tools/tpm2_pcrevent \
-     tools/tpm2_pcrextend \
-     tools/tpm2_pcrlist \
-+    tools/tpm2_pcrreset \
-     tools/tpm2_quote \
-     tools/tpm2_rc_decode \
-     tools/tpm2_readpublic \
-@@ -179,6 +180,7 @@ tools_tpm2_unseal_SOURCES = tools/tpm2_unseal.c $(TOOL_SRC)
- tools_tpm2_dictionarylockout_SOURCES = tools/tpm2_dictionarylockout.c $(TOOL_SRC)
- tools_tpm2_createpolicy_SOURCES = tools/tpm2_createpolicy.c $(TOOL_SRC)
- tools_tpm2_pcrextend_SOURCES = tools/tpm2_pcrextend.c $(TOOL_SRC)
-+tools_tpm2_pcrreset_SOURCES = tools/tpm2_pcrreset.c $(TOOL_SRC)
- tools_tpm2_pcrevent_SOURCES = tools/tpm2_pcrevent.c $(TOOL_SRC)
- tools_tpm2_rc_decode_SOURCES = tools/tpm2_rc_decode.c $(TOOL_SRC)
- 
-@@ -279,6 +281,7 @@ if HAVE_MAN_PAGES
-     man/man1/tpm2_pcrevent.1 \
-     man/man1/tpm2_pcrextend.1 \
-     man/man1/tpm2_pcrlist.1 \
-+    man/man1/tpm2_pcrreset.1 \
-     man/man1/tpm2_quote.1 \
-     man/man1/tpm2_rc_decode.1 \
-     man/man1/tpm2_readpublic.1 \
-diff --git a/man/tpm2_pcrreset.1.md b/man/tpm2_pcrreset.1.md
-new file mode 100644
-index 00000000000..d5637137796
---- /dev/null
-+++ b/man/tpm2_pcrreset.1.md
-@@ -0,0 +1,58 @@
-+% tpm2_pcrreset(1) tpm2-tools | General Commands Manual
-+%
-+% JANUARY 2019
-+
-+# NAME
-+
-+**tpm2_pcrreset**(1) - Reset one or more PCR banks
-+
-+# SYNOPSIS
-+
-+**tpm2_pcrreset** [*OPTIONS*] _PCR\_INDEX_ ...
-+
-+# DESCRIPTION
-+
-+**tpm2_pcrreset**(1) - Reset PCR value in all banks for specified index.
-+More than one PCR index can be specified.
-+
-+The reset value is manufacturer-dependent and is either sequence of 00 or FF
-+on the length of the hash algorithm for each supported bank
-+
-+_PCR\_INDEX_ is a space separated list of PCR indexes to be reset when issuing
-+the command. 
-+
-+# OPTIONS
-+
-+This tool accepts no tool specific options.
-+
-+[common options](common/options.md)
-+
-+[common tcti options](common/tcti.md)
-+
-+# EXAMPLES
-+
-+## Reset a single PCR
-+```
-+tpm2_pcrreset 23
-+```
-+
-+## Reset multiple PCRs
-+```
-+tpm2_pcrreset 16 23
-+```
-+
-+# NOTES
-+
-+On operating system's locality (generally locality 0), only PCR 23 can be reset.
-+PCR-16 can also be reset on this locality, depending on TPM manufacturers
-+which could define this PCR as resettable.
-+
-+PCR 0 to 15 are not resettable (being part of SRTM). PCR 16 to 22 are mostly
-+reserved for DRTM or dedicated to specific localities and might not
-+be resettable depending on current TPM locality.
-+
-+# RETURNS
-+
-+0 on success or 1 on failure.
-+
-+[footer](common/footer.md)
-diff --git a/test/system/test_tpm2_pcrreset.sh b/test/system/test_tpm2_pcrreset.sh
-new file mode 100755
-index 00000000000..962de780ab4
---- /dev/null
-+++ b/test/system/test_tpm2_pcrreset.sh
-@@ -0,0 +1,59 @@
-+#!/bin/bash
-+#;**********************************************************************;
-+#
-+# Copyright (c) 2019, Sebastien LE STUM
-+# All rights reserved.
-+#
-+# Redistribution and use in source and binary forms, with or without
-+# modification, are permitted provided that the following conditions are met:
-+#
-+# 1. Redistributions of source code must retain the above copyright notice,
-+# this list of conditions and the following disclaimer.
-+#
-+# 2. Redistributions in binary form must reproduce the above copyright notice,
-+# this list of conditions and the following disclaimer in the documentation
-+# and/or other materials provided with the distribution.
-+#
-+# 3. Neither the name of Intel Corporation nor the names of its contributors
-+# may be used to endorse or promote products derived from this software without
-+# specific prior written permission.
-+#
-+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+# THE POSSIBILITY OF SUCH DAMAGE.
-+#;**********************************************************************;
-+
-+source test_helpers.sh
-+
-+# Reset a resettable PCR
-+tpm2_pcrreset 23
-+
-+# Reset more than one resettable PCR
-+tpm2_pcrreset 16 23
-+
-+# Get PCR_Reset out of bound index error
-+tpm2_pcrreset 999 2>&1 1>/dev/null | grep -q "out of bound PCR"
-+
-+# Get PCR_Reset wrong index error
-+tpm2_pcrreset toto 2>&1 1>/dev/null | grep -q "invalid PCR"
-+
-+# Get PCR_Reset index out of range error
-+if tpm2_pcrreset 29 2>&1 1>/dev/null ; then
-+    echo "tpm2_pcrreset on out of range PCR index didn't fail"
-+    exit 1
-+else
-+    true
-+fi
-+
-+# Get PCR_Reset bad locality error
-+tpm2_pcrreset 0 2>&1 1>/dev/null | grep -q "0x907"
-+
-+exit 0
-diff --git a/tools/tpm2_pcrreset.c b/tools/tpm2_pcrreset.c
-new file mode 100644
-index 00000000000..5fa1de121e7
---- /dev/null
-+++ b/tools/tpm2_pcrreset.c
-@@ -0,0 +1,129 @@
-+//**********************************************************************;
-+// Copyright (c) 2017, Intel Corporation
-+// All rights reserved.
-+//
-+// Redistribution and use in source and binary forms, with or without
-+// modification, are permitted provided that the following conditions are met:
-+//
-+// 1. Redistributions of source code must retain the above copyright notice,
-+// this list of conditions and the following disclaimer.
-+//
-+// 2. Redistributions in binary form must reproduce the above copyright notice,
-+// this list of conditions and the following disclaimer in the documentation
-+// and/or other materials provided with the distribution.
-+//
-+// 3. Neither the name of Intel Corporation nor the names of its contributors
-+// may be used to endorse or promote products derived from this software without
-+// specific prior written permission.
-+//
-+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-+// THE POSSIBILITY OF SUCH DAMAGE.
-+//**********************************************************************;
-+
-+#include <ctype.h>
-+#include <errno.h>
-+#include <stdbool.h>
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#include <tss2/tss2_sys.h>
-+
-+#include "log.h"
-+#include "pcr.h"
-+#include "tpm2_options.h"
-+#include "tpm2_tool.h"
-+#include "tpm2_util.h"
-+
-+typedef struct tpm_pcr_reset_ctx tpm_pcr_reset_ctx;
-+struct tpm_pcr_reset_ctx {
-+    bool            pcr_list[TPM2_MAX_PCRS];
-+};
-+
-+static tpm_pcr_reset_ctx ctx;
-+
-+static bool pcr_reset_one(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_PCR pcr_index) {
-+    TSS2L_SYS_AUTH_RESPONSE sessions_data_out;
-+    TSS2L_SYS_AUTH_COMMAND sessions_data = { 1, {{ .sessionHandle=TPM2_RS_PW }}};
-+
-+    TSS2_RC rval = TSS2_RETRY_EXP(Tss2_Sys_PCR_Reset(sapi_context, pcr_index, &sessions_data,
-+            &sessions_data_out));
-+    if (rval != TSS2_RC_SUCCESS) {
-+        LOG_ERR("Could not reset PCR index: %d", pcr_index);
-+        return false;
-+    }
-+
-+    return true;
-+}
-+
-+static bool pcr_reset(TSS2_SYS_CONTEXT *sapi_context) {
-+    size_t i;
-+
-+    for (i = 0; i < TPM2_MAX_PCRS; i++) {
-+        if(!ctx.pcr_list[i])
-+            continue;
-+
-+        bool result = pcr_reset_one(sapi_context, i);
-+        if (!result) {
-+            return false;
-+        }
-+    }
-+
-+    return true;
-+}
-+
-+static bool on_arg(int argc, char** argv){
-+    int i;
-+    uint32_t pcr;
-+
-+    memset(ctx.pcr_list, 0, TPM2_MAX_PCRS);
-+    
-+    if (argc < 1) {
-+        LOG_ERR("Expected at least one PCR index"
-+                "ie: <pcr index>, got: 0");
-+        return false;
-+    }
-+
-+    for(i = 0; i < argc; i++){
-+        if(!tpm2_util_string_to_uint32(argv[i], &pcr)){
-+            LOG_ERR("Got invalid PCR Index: \"%s\"", argv[i]);
-+            return false;
-+        }
-+
-+        /*
-+        * If any specified PCR index is greater than the last valid
-+        * index supported in the spec, throw an error 
-+        */
-+        if(pcr > TPM2_MAX_PCRS - 1){
-+            LOG_ERR("Got out of bound PCR Index: \"%s\"", argv[i]);
-+            return false;
-+        }
-+
-+        ctx.pcr_list[pcr] = 1;
-+    }
-+
-+    return true;
-+}
-+
-+bool tpm2_tool_onstart(tpm2_options **opts) {
-+
-+    *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_arg, 0);
-+
-+    return *opts != NULL;
-+}
-+
-+int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {
-+
-+    UNUSED(flags);
-+
-+    return pcr_reset(sapi_context) != true;
-+}
-+
--- 
-2.21.0
-