Setup TPM2-Plugin build environment

Add initial codes to build TPM2-plugin shared lib

Issue-ID: AAF-94
Change-Id: I96dee3699aa250b69350d6f01401f3831cf515f7
Signed-off-by: NingSun <ning.sun@intel.com>
diff --git a/TPM2-Plugin/lib/Makefile.am b/TPM2-Plugin/lib/Makefile.am
new file mode 100644
index 0000000..c82cf86
--- /dev/null
+++ b/TPM2-Plugin/lib/Makefile.am
@@ -0,0 +1,4 @@
+AM_CPPFLAGS = -I ./include
+lib_LTLIBRARIES = libtpm2-plugin.la
+libtpm2_plugin_la_SOURCES =  tpm2_error.c tpm2_plugin_api.c tpm2_plugin_init.c tpm2_tcti_ldr.c tpm2_util.c  log.c  plugin_register.c files.c tpm2_attr_util.c tpm2_alg_util.c tpm2_hash.c
+libtpm2_plugin_la_LDFLAGS = -version-info @VERSION_INFO@  -lsapi -ltcti-socket -ltcti-device -lcrypto -lssl -ldl
diff --git a/TPM2-Plugin/lib/files.c b/TPM2-Plugin/lib/files.c
new file mode 100644
index 0000000..e2e41f4
--- /dev/null
+++ b/TPM2-Plugin/lib/files.c
@@ -0,0 +1,636 @@
+//**********************************************************************;
+// 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 <errno.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <sapi/tpm20.h>
+#include <sapi/tss2_mu.h>
+
+#include "files.h"
+#include "log.h"
+#include "tpm2_util.h"
+
+bool files_get_file_size(FILE *fp, unsigned long *file_size, const char *path) {
+
+    long current = ftell(fp);
+    if (current < 0) {
+        if (path) {
+            LOG_ERR("Error getting current file offset for file \"%s\" error: %s", path, strerror(errno));
+        }
+        return false;
+    }
+
+    int rc = fseek(fp, 0, SEEK_END);
+    if (rc < 0) {
+        if (path) {
+            LOG_ERR("Error seeking to end of file \"%s\" error: %s", path, strerror(errno));
+        }
+        return false;
+    }
+
+    long size = ftell(fp);
+    if (size < 0) {
+        if (path) {
+            LOG_ERR("ftell on file \"%s\" failed: %s", path, strerror(errno));
+        }
+        return false;
+    }
+
+    rc = fseek(fp, current, SEEK_SET);
+    if (rc < 0) {
+        if (path) {
+            LOG_ERR("Could not restore initial stream position for file \"%s\" failed: %s", path, strerror(errno));
+        }
+        return false;
+    }
+
+    /* size cannot be negative at this point */
+    *file_size = (unsigned long)size;
+    return true;
+}
+
+static bool read_bytes_from_file(FILE *f, UINT8 *buf, UINT16 *size,
+                                 const char *path) {
+    unsigned long file_size;
+    bool result = files_get_file_size(f, &file_size, path);
+    if (!result) {
+        /* get_file_size() logs errors */
+        return false;
+    }
+
+    /* max is bounded on UINT16 */
+    if (file_size > *size) {
+        if (path) {
+            LOG_ERR(
+                    "File \"%s\" size is larger than buffer, got %lu expected less than %u",
+                    path, file_size, *size);
+        }
+        return false;
+    }
+
+    result = files_read_bytes(f, buf, file_size);
+    if (!result) {
+        if (path) {
+            LOG_ERR("Could not read data from file \"%s\"", path);
+        }
+        return false;
+    }
+
+    *size = file_size;
+
+    return true;
+}
+
+bool files_load_bytes_from_path(const char *path, UINT8 *buf, UINT16 *size) {
+    if (!buf || !size || !path) {
+        return false;
+    }
+
+    FILE *f = fopen(path, "rb");
+    if (!f) {
+        LOG_ERR("Could not open file \"%s\" error %s", path, strerror(errno));
+        return false;
+    }
+
+    bool result = read_bytes_from_file(f, buf, size, path);
+
+    fclose(f);
+    return result;
+}
+
+bool files_save_bytes_to_file(const char *path, UINT8 *buf, UINT16 size) {
+
+    if (!path || !buf) {
+        return false;
+    }
+
+    FILE *fp = fopen(path, "wb+");
+    if (!fp) {
+        LOG_ERR("Could not open file \"%s\", error: %s", path, strerror(errno));
+        return false;
+    }
+
+    bool result = files_write_bytes(fp, buf, size);
+    if (!result) {
+        LOG_ERR("Could not write data to file \"%s\"", path);
+    }
+    fclose(fp);
+    return result;
+}
+
+/*
+ * Current version to write TPMS_CONTEXT to disk.
+ */
+#define CONTEXT_VERSION 1
+
+bool files_save_tpm_context_to_file(TSS2_SYS_CONTEXT *sysContext, TPM2_HANDLE handle,
+        FILE *stream) {
+
+    TPMS_CONTEXT context;
+
+    TSS2_RC rval = Tss2_Sys_ContextSave(sysContext, handle, &context);
+    if (rval != TPM2_RC_SUCCESS) {
+        LOG_PERR(Tss2_Sys_ContextSave, rval);
+        return false;
+    }
+
+    /*
+     * Saving the TPMS_CONTEXT structure to disk, format:
+     * TPM2.0-TOOLS HEADER
+     * U32 hiearchy
+     * U32 savedHandle
+     * U64 sequence
+     * U16 contextBlobLength
+     * BYTE[] contextBlob
+     */
+    bool result = files_write_header(stream, CONTEXT_VERSION);
+    if (!result) {
+        LOG_ERR("Could not write context file header");
+        goto out;
+    }
+
+    // UINT32
+    result = files_write_32(stream, context.hierarchy);
+    if (!result) {
+        LOG_ERR("Could not write hierarchy");
+        goto out;
+    }
+
+    result = files_write_32(stream, context.savedHandle);
+    if (!result) {
+        LOG_ERR("Could not write savedHandle");
+        goto out;
+    }
+
+    // UINT64
+    result = files_write_64(stream, context.sequence);
+    if (!result) {
+        LOG_ERR("Could not write sequence");
+        goto out;
+    }
+
+    // U16 LENGTH
+    result = files_write_16(stream, context.contextBlob.size);
+    if (!result) {
+        LOG_ERR("Could not write contextBob size");
+        goto out;
+    }
+
+    // BYTE[] contextBlob
+    result = files_write_bytes(stream, context.contextBlob.buffer,
+            context.contextBlob.size);
+    if (!result) {
+        LOG_ERR("Could not write contextBlob buffer");
+    }
+    /* result is set by file_write_bytes() */
+
+out:
+    return result;
+}
+
+bool files_save_tpm_context_to_path(TSS2_SYS_CONTEXT *sysContext, TPM2_HANDLE handle,
+        const char *path) {
+
+    FILE *f = fopen(path, "w+b");
+    if (!f) {
+        LOG_ERR("Error opening file \"%s\" due to error: %s", path,
+                strerror(errno));
+        return false;
+    }
+
+    bool result = files_save_tpm_context_to_file(sysContext, handle, f);
+    fclose(f);
+    return result;
+}
+
+
+bool files_load_tpm_context_from_file(TSS2_SYS_CONTEXT *sapi_context,
+        TPM2_HANDLE *handle, FILE *fstream) {
+
+    TSS2_RC rval;
+
+    /*
+     * Reading the TPMS_CONTEXT structure to disk, format:
+     * TPM2.0-TOOLS HEADER
+     * U32 hiearchy
+     * U32 savedHandle
+     * U64 sequence
+     * U16 contextBlobLength
+     * BYTE[] contextBlob
+     */
+    UINT32 version;
+    TPMS_CONTEXT context;
+    bool result = files_read_header(fstream, &version);
+    if (!result) {
+        LOG_WARN(
+            "The loaded tpm context does not appear to be in the proper format,"
+            "assuming old format, this will be converted on the next save.");
+        rewind(fstream);
+        result = files_read_bytes(fstream, (UINT8 *) &context, sizeof(context));
+        if (!result) {
+            LOG_ERR("Could not load tpm context file");
+            goto out;
+        }
+        /* Success load the context into the TPM */
+        goto load_to_tpm;
+    }
+
+    if (version != CONTEXT_VERSION) {
+        LOG_ERR("Unsupported context file format version found, got: %"PRIu32,
+                version);
+        result = false;
+        goto out;
+    }
+
+    result = files_read_32(fstream, &context.hierarchy);
+    if (!result) {
+        LOG_ERR("Error reading hierarchy!");
+        goto out;
+    }
+
+    result = files_read_32(fstream, &context.savedHandle);
+    if (!result) {
+        LOG_ERR("Error reading savedHandle!");
+        goto out;
+    }
+
+    result = files_read_64(fstream, &context.sequence);
+    if (!result) {
+        LOG_ERR("Error reading sequence!");
+        goto out;
+    }
+
+    result = files_read_16(fstream, &context.contextBlob.size);
+    if (!result) {
+        LOG_ERR("Error reading contextBlob.size!");
+        goto out;
+    }
+
+    if (context.contextBlob.size > sizeof(context.contextBlob.buffer)) {
+        LOG_ERR(
+                "Size mismatch found on contextBlob, got %"PRIu16" expected less than or equal to %zu",
+                context.contextBlob.size,
+                sizeof(context.contextBlob.buffer));
+        result = false;
+        goto out;
+    }
+
+    result = files_read_bytes(fstream, context.contextBlob.buffer,
+            context.contextBlob.size);
+    if (!result) {
+        LOG_ERR("Error reading contextBlob.size!");
+        goto out;
+    }
+
+load_to_tpm:
+    rval = Tss2_Sys_ContextLoad(sapi_context, &context, handle);
+    if (rval != TPM2_RC_SUCCESS) {
+        LOG_PERR(Tss2_Sys_ContextLoad, rval);
+        result = false;
+        goto out;
+    }
+
+    result = true;
+
+out:
+    return result;
+}
+
+bool files_load_tpm_context_from_path(TSS2_SYS_CONTEXT *sapi_context,
+        TPM2_HANDLE *handle, const char *path) {
+
+    FILE *f = fopen(path, "rb");
+    if (!f) {
+        LOG_ERR("Error opening file \"%s\" due to error: %s", path,
+                strerror(errno));
+        return false;
+    }
+
+    bool result = files_load_tpm_context_from_file(sapi_context, handle, f);
+
+    fclose(f);
+    return result;
+}
+
+bool files_does_file_exist(const char *path) {
+
+    if (!path) {
+        LOG_ERR("Path cannot be NULL");
+        return false;
+    }
+
+    FILE *fp = fopen(path,"rb");
+    if (fp) {
+        fclose(fp);
+        LOG_ERR("Path: %s already exists. Please rename or delete the file!",
+                path);
+        return true;
+    }
+    return false;
+}
+
+bool files_get_file_size_path(const char *path, unsigned long *file_size) {
+
+    bool result = false;
+
+    if (!path) {
+        LOG_ERR("Must specify a path argument, cannot be NULL!");
+        return false;
+    }
+
+    if (!file_size) {
+        LOG_ERR("Must specify a file size argument, cannot be NULL!");
+        return false;
+    }
+
+    FILE *fp = fopen(path,"rb");
+    if(!fp) {
+        LOG_ERR("Could not open file: \"%s\" error: %s", path, strerror(errno));
+        return false;
+    }
+
+    result = files_get_file_size(fp, file_size, path);
+
+    fclose(fp);
+    return result;
+}
+
+/**
+ * This is the magic for the file header. The header is organized
+ * as a big endian U32 (BEU32) of MAGIC followed by a BEU32 of the
+ * version number. Tools can define their own, individual file
+ * formats as they make sense, but they should always have the header.
+ */
+static const UINT32 MAGIC = 0xBADCC0DE;
+
+/**
+ * Writes size bytes to a file, continuing on EINTR short writes.
+ * @param f
+ *  The file to write to.
+ * @param data
+ *  The data to write.
+ * @param size
+ *  The size, in bytes, of that data.
+ * @return
+ *  True on success, False otherwise.
+ */
+static bool writex(FILE *f, UINT8 *data, size_t size) {
+
+    size_t wrote = 0;
+    size_t index = 0;
+    do {
+        wrote = fwrite(&data[index], 1, size, f);
+        if (wrote != size) {
+            if (errno != EINTR) {
+                return false;
+            }
+            /* continue on EINTR */
+        }
+        size -= wrote;
+        index += wrote;
+    } while (size > 0);
+
+    return true;
+}
+
+/**
+ * Reads size bytes from a file, continuing on EINTR short reads.
+ * @param f
+ *  The file to read from.
+ * @param data
+ *  The data buffer to read into.
+ * @param size
+ *  The size of the buffer, which is also the amount of bytes to read.
+ * @return
+ *  True on success, False otherwise.
+ */
+static bool readx(FILE *f, UINT8 *data, size_t size) {
+
+    size_t bread = 0;
+    size_t index = 0;
+    do {
+        bread = fread(&data[index], 1, size, f);
+        if (bread != size) {
+            if (feof(f) || (errno != EINTR)) {
+                return false;
+            }
+            /* continue on EINTR */
+        }
+        size -= bread;
+        index += bread;
+    } while (size > 0);
+
+    return true;
+}
+
+#define BAIL_ON_NULL(param, x) \
+    do { \
+        if (!x) { \
+            LOG_ERR(param" must be specified"); \
+            return false; \
+        } \
+    } while(0)
+
+#define BE_CONVERT(value, size) \
+    do { \
+        if (!tpm2_util_is_big_endian()) { \
+            value = tpm2_util_endian_swap_##size(value); \
+        } \
+    } while (0)
+
+#define FILE_WRITE(size) \
+    bool files_write_##size(FILE *out, UINT##size data) { \
+        BAIL_ON_NULL("FILE", out); \
+        BE_CONVERT(data, size); \
+        return writex(out, (UINT8 *)&data, sizeof(data)); \
+    }
+
+#define FILE_READ(size) \
+    bool files_read_##size(FILE *out, UINT##size *data) { \
+	    BAIL_ON_NULL("FILE", out); \
+	    BAIL_ON_NULL("data", data); \
+        bool res = readx(out, (UINT8 *)data, sizeof(*data)); \
+        if (res) { \
+            BE_CONVERT(*data, size); \
+        } \
+        return res; \
+    }
+
+/*
+ * all the files_read|write_bytes_16|32|64 functions
+ */
+FILE_READ(16);
+FILE_WRITE(16)
+
+FILE_READ(32);
+FILE_WRITE(32)
+
+FILE_READ(64)
+FILE_WRITE(64)
+
+bool files_read_bytes(FILE *out, UINT8 bytes[], size_t len) {
+
+    BAIL_ON_NULL("FILE", out);
+    BAIL_ON_NULL("bytes", bytes);
+    return readx(out, bytes, len);
+}
+
+bool files_write_bytes(FILE *out, uint8_t bytes[], size_t len) {
+
+    BAIL_ON_NULL("FILE", out);
+    BAIL_ON_NULL("bytes", bytes);
+    return writex(out, bytes, len);
+}
+
+bool files_write_header(FILE *out, UINT32 version) {
+
+    BAIL_ON_NULL("FILE", out);
+
+    bool res = files_write_32(out, MAGIC);
+    if (!res) {
+        return false;
+    }
+    return files_write_32(out, version);
+}
+
+bool files_read_header(FILE *out, uint32_t *version) {
+
+    BAIL_ON_NULL("FILE", out);
+    BAIL_ON_NULL("version", version);
+
+    UINT32 magic;
+    bool res = files_read_32(out, &magic);
+    if (!res) {
+        return false;
+    }
+
+    if (magic != MAGIC) {
+        LOG_ERR("Found magic 0x%x did not match expected magic of 0x%x!",
+                magic, MAGIC);
+        return false;
+    }
+
+    return files_read_32(out, version);
+}
+
+bool files_load_bytes_from_file_or_stdin(const char *path, UINT16 *size, BYTE *buf) {
+
+    FILE *file =  path ? fopen(path, "rb") : stdin;
+    path = file != stdin ? path : "<stdin>";
+    if (!file) {
+        LOG_ERR("Could not open file: \"%s\", error: %s", path,
+                strerror(errno));
+        return false;
+    }
+
+    /*
+     * Attempt to accurately read the file based on the file size.
+     * This may fail on stdin when it's a pipe.
+     */
+    if (file == stdin) {
+        path = NULL;
+    }
+
+    UINT16 original_size = *size;
+    bool res = files_load_bytes_from_path(path, buf,
+            size);
+    if (!res) {
+        res = true;
+        *size = fread(buf, 1,
+                *size, file);
+        if (!feof(file)) {
+            LOG_ERR("Data to be sealed larger than expected. Got %u expected %u",
+                    original_size, res);
+            res = false;
+        }
+        else if (ferror(file)) {
+            LOG_ERR("Error reading sealed data from \"<stdin>\"");
+            res = false;
+        }
+    }
+
+    if (file != stdin) {
+        fclose(file);
+    }
+
+    return res;
+}
+
+#define SAVE_TYPE(type, name) \
+    bool files_save_##name(type *name, const char *path) { \
+    \
+        size_t offset = 0; \
+        UINT8 buffer[sizeof(*name)]; \
+        TSS2_RC rc = Tss2_MU_##type##_Marshal(name, buffer, sizeof(buffer), &offset); \
+        if (rc != TSS2_RC_SUCCESS) { \
+            LOG_ERR("Error serializing "str(name)" structure: 0x%x", rc); \
+            return false; \
+        } \
+    \
+        return files_save_bytes_to_file(path, buffer, offset); \
+    }
+
+#define LOAD_TYPE(type, name) \
+    bool files_load_##name(const char *path, type *name) { \
+    \
+        UINT8 buffer[sizeof(*name)]; \
+        UINT16 size = sizeof(buffer); \
+        bool res = files_load_bytes_from_path(path, buffer, &size); \
+        if (!res) { \
+            return false; \
+        } \
+        \
+        size_t offset = 0; \
+        TSS2_RC rc = Tss2_MU_##type##_Unmarshal(buffer, size, &offset, name); \
+        if (rc != TSS2_RC_SUCCESS) { \
+            LOG_ERR("Error serializing "str(name)" structure: 0x%x", rc); \
+            return false; \
+        } \
+        \
+        return rc == TPM2_RC_SUCCESS; \
+    }
+
+SAVE_TYPE(TPM2B_PUBLIC, public)
+LOAD_TYPE(TPM2B_PUBLIC, public)
+
+SAVE_TYPE(TPMT_SIGNATURE, signature)
+LOAD_TYPE(TPMT_SIGNATURE, signature)
+
+SAVE_TYPE(TPMT_TK_VERIFIED, ticket)
+LOAD_TYPE(TPMT_TK_VERIFIED, ticket)
+
+SAVE_TYPE(TPM2B_SENSITIVE, sensitive)
+LOAD_TYPE(TPM2B_SENSITIVE, sensitive)
+
+SAVE_TYPE(TPMT_TK_HASHCHECK, validation)
+LOAD_TYPE(TPMT_TK_HASHCHECK, validation)
diff --git a/TPM2-Plugin/lib/include/files.h b/TPM2-Plugin/lib/include/files.h
new file mode 100644
index 0000000..164e308
--- /dev/null
+++ b/TPM2-Plugin/lib/include/files.h
@@ -0,0 +1,366 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+#ifndef FILES_H
+#define FILES_H
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <sapi/tpm20.h>
+
+/**
+ * Reads a series of bytes from a file as a byte array. This is similar to files_read_bytes(),
+ * but opens and closes the FILE for the caller. Size is both an input and output value where
+ * the size value is the max buffer size on call and the returned size is how much was read.
+ *
+ * This interface could be cleaned up in a later revision.
+ * @param path
+ *  The path to the file to open.
+ * @param buf
+ *  The buffer to read the data into
+ * @param size
+ *  The max size of the buffer on call, and the size of the data read on return.
+ * @return
+ *  True on success, false otherwise.
+ */
+bool files_load_bytes_from_path(const char *path, UINT8 *buf, UINT16 *size);
+
+/**
+ * Loads data from a file path or stdin enforcing an upper bound on size.
+ * @param path
+ *  The path to load data from, NULL means stdin.
+ * @param size
+ *  The maximum size.
+ * @param buf
+ *  The buffer to write the data into.
+ * @return
+ *  True on success or false otherwise.
+ */
+bool files_load_bytes_from_file_or_stdin(const char *path, UINT16 *size, BYTE *buf);
+
+/**
+ * Similar to files_write_bytes(), in that it writes an array of bytes to disk,
+ * but this routine opens and closes the file on the callers behalf.
+ * @param path
+ *  The path to the file to write the data to.
+ * @param buf
+ *  The buffer of data to write
+ * @param size
+ *  The size of the data to write in bytes.
+ * @return
+ *  True on success, false otherwise.
+ */
+bool files_save_bytes_to_file(const char *path, UINT8 *buf, UINT16 size);
+
+/**
+ * Saves the TPM context for an object handle to disk by calling Tss2_Sys_ContextSave() and serializing the
+ * resulting TPMS_CONTEXT structure to disk.
+ * @param sapi_context
+ *  The system api context
+ * @param handle
+ *  The object handle for the object to save.
+ * @param path
+ *  The output path of the file.
+ *
+ * @return
+ *  True on success, False on error.
+ */
+bool files_save_tpm_context_to_path(TSS2_SYS_CONTEXT *sapi_context, TPM2_HANDLE handle, const char *path);
+
+/**
+ * Like files_save_tpm_context_to_path() but saves a tpm session to a FILE stream.
+ * @param sapi_context
+ *  The system api context
+ * @param handle
+ *  The object handle for the object to save.
+ * @param stream
+ *  The FILE stream to save too.
+ * @return
+ *  True on success, False on error.
+ */
+bool files_save_tpm_context_to_file(TSS2_SYS_CONTEXT *sapi_context, TPM2_HANDLE handle,
+        FILE *stream);
+
+/**
+ * Loads a TPM object context from disk.
+ * @param sapi_context
+ *  The system API context
+ * @param handle
+ *  The object handle that was saved.
+ * @param path
+ *  The path to the input file.
+ * @return
+ *  True on Success, false on error.
+ */
+bool files_load_tpm_context_from_path(TSS2_SYS_CONTEXT *sapi_context, TPM2_HANDLE *handle, const char *path);
+
+/**
+ * Like files_load_tpm_context_from_path() but loads the context from a FILE stream.
+ * @param sapi_context
+ *  The system API context
+ * @param handle
+ *  The object handle that was saved.
+ * @param stream
+ *  The FILE stream to read from.
+ * @return
+ *  True on success, False on error.
+ */
+bool files_load_tpm_context_from_file(TSS2_SYS_CONTEXT *sapi_context,
+        TPM2_HANDLE *handle, FILE *stream);
+
+/**
+ * Serializes a TPM2B_PUBLIC to the file path provided.
+ * @param public
+ *  The TPM2B_PUBLIC to save to disk.
+ * @param path
+ *  The path to save to.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_save_public(TPM2B_PUBLIC *public, const char *path);
+
+/**
+ * Loads a TPM2B_PUBLIC from disk that was saved with files_save_pubkey()
+ * @param path
+ *  The path to load from.
+ * @param public
+ *  The TPM2B_PUBLIC to load.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_load_public(const char *path, TPM2B_PUBLIC *public);
+
+/**
+ * Serializes a TPMT_SIGNATURE to the file path provided.
+ * @param signature
+ *  The TPMT_SIGNATURE to save to disk.
+ * @param path
+ *  The path to save to.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_save_signature(TPMT_SIGNATURE *signature, const char *path);
+
+/**
+ * Loads a TPMT_SIGNATURE from disk that was saved with files_save_signature()
+ * @param path
+ *  The path to load from.
+ * @param signature
+ *  The TPMT_SIGNATURE to load.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_load_signature(const char *path, TPMT_SIGNATURE *signature);
+
+/**
+ * Serializes a TPMT_TK_VERIFIED to the file path provided.
+ * @param signature
+ *  The TPMT_SIGNATURE to save to disk.
+ * @param path
+ *  The path to save to.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_save_ticket(TPMT_TK_VERIFIED *ticket, const char *path);
+
+/**
+ * Loads a TPMT_TK_VERIFIED from disk that was saved with files_save_ticket()
+ * @param path
+ *  The path to load from.
+ * @param signature
+ *  The TPMT_TK_VERIFIED to load.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_load_ticket(const char *path, TPMT_TK_VERIFIED *ticket);
+
+/**
+ * Loads a TPM2B_SENSITIVE from disk.
+ * @param path
+ *  The path to load from.
+ * @param signature
+ *  The TPM2B_SENSITIVE to load.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_load_sensitive(const char *path, TPM2B_SENSITIVE *sensitive);
+
+/**
+ * Serializes a TPMT_TK_HASHCHECK to the file path provided.
+ * @param validation
+ *  The TPMT_TK_HASHCHECK to save to disk.
+ * @param path
+ *  The path to save to.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_save_validation(TPMT_TK_HASHCHECK *validation, const char *path);
+
+/**
+ * Loads a TPMT_TK_HASHCHECK from disk.
+ * @param path
+ *  The path to load from.
+ * @param validation
+ *  The TPMT_TK_HASHCHECK to load.
+ * @return
+ *  true on success, false on error.
+ */
+bool files_load_validation(const char *path, TPMT_TK_HASHCHECK *validation);
+
+/**
+ * Checks a file for existence.
+ * @param path
+ *  The file to check for existence.
+ * @return
+ * true if a file exists with read permissions, false if it doesn't exist or an error occurs.
+ *
+ */
+bool files_does_file_exist(const char *path);
+
+/**
+ * Retrieves a files size given a file path.
+ * @param path
+ *  The path of the file to retreive the size of.
+ * @param file_size
+ *  A pointer to an unsigned long to return the file size. The
+ *  pointed to value is valid only on a true return.
+ *
+ * @return
+ *  True for success or False for error.
+ */
+bool files_get_file_size_path(const char *path, unsigned long *file_size);
+
+/**
+ * Similar to files_get_file_size_path(), but uses an already opened FILE object.
+ * @param fp
+ *  The file pointer to query the size of.
+ * @param file_size
+ *  Output of the file size.
+ * @param path
+ *  An optional path used for error reporting, a NULL path disables error logging.
+ * @return
+ *  True on success, False otherwise.
+ */
+bool files_get_file_size(FILE *fp, unsigned long *file_size, const char *path);
+
+/**
+ * Writes a TPM2.0 header to a file.
+ * @param f
+ *  The file to write to.
+ * @param version
+ *  The version number of the format of the file.
+ * @return
+ *  True on success, false on error.
+ */
+bool files_write_header(FILE *f, UINT32 version);
+
+/**
+ * Reads a TPM2.0 header from a file.
+ * @param f
+ *  The file to read.
+ * @param version
+ *  The version that was found.
+ * @return
+ *  True on Success, False on error.
+ */
+bool files_read_header(FILE *f, UINT32 *version);
+
+/**
+ * Writes a 16 bit value to the file in big endian, converting
+ * if needed.
+ * @param out
+ *  The file to write.
+ * @param data
+ *  The 16 bit value to write.
+ * @return
+ *  True on success, False on error.
+ */
+bool files_write_16(FILE *out, UINT16 data);
+
+/**
+ * Same as files_write_16 but for 32 bit values.
+ */
+bool files_write_32(FILE *out, UINT32 data);
+
+/**
+ * Same as files_write_16 but for 64 bit values.
+ */
+bool files_write_64(FILE *out, UINT64 data);
+
+/**
+ * Writes a byte array out to a file.
+ * @param out
+ *  The file to write to.
+ * @param data
+ *  The data to write.
+ * @param size
+ *  The size of the data to write in bytes.
+ * @return
+ *  True on success, False otherwise.
+ */
+bool files_write_bytes(FILE *out, UINT8 data[], size_t size);
+
+/**
+ * Reads a 16 bit value from a file converting from big endian to host
+ * endianess.
+ * @param out
+ *  The file to read from.
+ * @param data
+ *  The data that is read, valid on a true return.
+ * @return
+ *  True on success, False on error.
+ */
+bool files_read_16(FILE *out, UINT16 *data);
+
+/**
+ * Same as files_read_16 but for 32 bit values.
+ */
+bool files_read_32(FILE *out, UINT32 *data);
+
+/**
+ * Same as files_read_16 but for 64 bit values.
+ */
+bool files_read_64(FILE *out, UINT64 *data);
+
+/**
+ * Reads len bytes from a file.
+ * @param out
+ *  The file to read from.
+ * @param data
+ *  The buffer to read into, only valid on a True return.
+ * @param size
+ *  The number of bytes to read.
+ * @return
+ *  True on success, False otherwise.
+ */
+bool files_read_bytes(FILE *out, UINT8 data[], size_t size);
+
+#endif /* FILES_H */
diff --git a/TPM2-Plugin/lib/include/log.h b/TPM2-Plugin/lib/include/log.h
new file mode 100644
index 0000000..c4ae0bd
--- /dev/null
+++ b/TPM2-Plugin/lib/include/log.h
@@ -0,0 +1,107 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+#ifndef SRC_LOG_H_
+#define SRC_LOG_H_
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <sapi/tpm20.h>
+
+#include "tpm2_error.h"
+#include "tpm2_util.h"
+
+typedef enum log_level log_level;
+enum log_level {
+    log_level_error,
+    log_level_warning,
+    log_level_verbose
+};
+
+void _log (log_level level, const char *file, unsigned lineno, const char *fmt, ...)
+    COMPILER_ATTR(format (printf, 4, 5));
+
+/*
+ * Prints an error message. The fmt and variadic arguments mirror printf.
+ *
+ * Use this to log all error conditions.
+ */
+#define LOG_ERR(fmt, ...) _log(log_level_error, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+
+/**
+ * Prints an error message for a TSS2_Sys call to the TPM.
+ * The format is <function-name>(0x<rc>) - <error string>
+ * @param func
+ *  The function that caused the error
+ * @param rc
+ *  The return code to print.
+ */
+#define LOG_PERR(func, rc) _LOG_PERR(xstr(func), rc)
+
+/**
+ * Internal use only.
+ *
+ * Handles the expanded LOG_PERR call checking argument values
+ * and handing them off to LOG_ERR.
+ * @param func
+ *  The function name.
+ * @param rc
+ *  The rc to decode.
+ */
+static inline void _LOG_PERR(const char *func, TSS2_RC rc) {
+
+    LOG_ERR("%s(0x%X) - %s", func, rc, tpm2_error_str(rc));
+}
+
+/*
+ * Prints an warning message. The fmt and variadic arguments mirror printf.
+ *
+ * Use this to log a warning. A warning is when something is wrong, but it is not a fatal
+ * issue.
+ */
+#define LOG_WARN(fmt, ...) _log(log_level_warning, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+
+/*
+ * Prints an informational message. The fmt and variadic arguments mirror printf.
+ *
+ * Informational messages are only shown when verboseness is increased. Valid messages
+ * would be debugging type messages where additional, extraneous information is printed.
+ */
+#define LOG_INFO(fmt, ...) _log(log_level_verbose, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+
+/**
+ * Sets the log level so only messages <= to it print.
+ * @param level
+ *  The logging level to set.
+ */
+void log_set_level (log_level level);
+
+#endif /* SRC_LOG_H_ */
diff --git a/TPM2-Plugin/lib/include/plugin_api.h b/TPM2-Plugin/lib/include/plugin_api.h
new file mode 100644
index 0000000..5f4b924
--- /dev/null
+++ b/TPM2-Plugin/lib/include/plugin_api.h
@@ -0,0 +1,48 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+
+#ifndef __PLUGIN_API_H__
+#define __PLUGIN_API_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int plugin_configure(char *configPath);
+
+void plugin_assign_hw_instance();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/TPM2-Plugin/lib/include/plugin_register.h b/TPM2-Plugin/lib/include/plugin_register.h
new file mode 100644
index 0000000..a154a24
--- /dev/null
+++ b/TPM2-Plugin/lib/include/plugin_register.h
@@ -0,0 +1,196 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+
+#ifndef __PLUGIN_REGISTER_H__
+#define __PLUGIN_REGISTER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Callback function definitions
+ */
+
+typedef int (*fp_crypto_rsa_decrypt_init) (
+    /* IN */
+    unsigned long mechanism,    /* PKCS#11 Mechanism */
+    void *param,                /* PKCS#11 Paramter */
+    unsigned long param_len,    /* PKCS#11 Parameter len */
+    /* OUT */
+    void *cb                   /* Address of pointer to store context block */ 
+    );
+
+typedef int (*fp_crypto_rsa_decrypt) (
+    /* IN */
+    void* cb,                /* Pointer Crypto Block which is created during decrypt_init */
+    unsigned char* cipher,   /* Input Cipher data */
+    int cipher_length,       /* Ciphet data length */
+    /* OUT */
+    unsigned char* out_data, /* Decrypted output data */
+    int* out_data_len        /* output length */
+    );
+
+typedef int (*fp_crypto_rsa_sign_init) (
+    /* IN */
+    unsigned long mechanism,    /* PKCS#11 Mechanism */
+    void *param,                /* PKCS#11 Paramter */
+    unsigned long param_len,    /* PKCS#11 Parameter len */
+    /* OUT */
+    void *cb                   /* Address of pointer to store context block */ 
+    );
+
+typedef int (*fp_crypto_rsa_sign_update) (
+    /* IN */
+    void *cb,                   /* Previously created context block (during sign_init) passed */
+    void *pPart,                /* pPart */
+    unsigned long ulPartLen     /* ulPartLen */
+    );
+
+typedef int (*fp_crypto_rsa_sign_final) (
+    /* IN */
+    void *cb,                   /* Previously passed context block */
+    /* OUT */
+    unsigned char *sig,         /* Output Signature buffer */
+    int *sigLen                 /* Pointer to hold signature buffer length */
+    );
+
+typedef int (*fp_crypto_rsa_sign) (
+    /* IN */
+    void *cb,                   /* Previously created context block (during sign_init) passed */
+    unsigned char* msg,         /* Data to be signed */
+    int msg_len,                /* Input data length */
+    /* OUT */
+    unsigned char *sig,         /* Output Signature buffer */
+    int *sig_len                /* Pointer to hold signature buffer length */
+    );
+
+typedef int (*fp_crypto_ecdsa_sign) (
+    /* IN */
+    void *cb,                   /* Previously created context block (during sign_init) passed */
+    unsigned char* data,        /* Data to be signed */
+    int data_len,               /* Input data length */
+    /* OUT */
+    unsigned char *sig,         /* Output Signature buffer */
+    int *sig_len                /* Pointer to hold signature buffer length */
+    );
+
+typedef int (*fp_crypto_ecdsa_verify) (
+    /* IN */
+    unsigned long appHandle,    /* Application handle needed for QAT KPT mode */
+    //DhsmWPKECDSAFormat *wpk,    /* Wrapped Private Key strcuture for ECDSA */
+    void *wpk,    /* Wrapped Private Key strcuture for ECDSA */
+    unsigned char* swk,         /* Symmetric Wrapping Key (SWK) value */
+    int swk_len,                /* SWK length */
+    unsigned char* iv,          /* IV value used during Application Key encryption */
+    int iv_len,                 /* IV length */
+    int tag_len,                /* AES-GCM tag length */
+    unsigned char* data,        /* Data which is used for signing */
+    int data_len,               /* Input data length */
+    unsigned char *sig,         /* Signature value */ 
+    int sig_len,                /* Signature length */
+    /* OUT */
+    int* verifyResult           /* Pointer to hold the verification result */
+    );
+
+typedef int (*fp_crypto_del_apphandle) (unsigned long skmKeyHandle);
+
+// SWK related operations
+typedef int (*fp_crypto_swk_getParentKey) (unsigned char** tlvbuffer, int* buflen);
+typedef int (*fp_crypto_swk_import) (
+    unsigned long appHandle, 
+    unsigned char* tlvbuffer, 
+    int buflen, 
+    unsigned char* iv, 
+    int iv_len, 
+    unsigned char* tpm_pwd, 
+    int tpm_pwd_len);
+
+typedef int (*fp_crypto_rsa_create_object) (
+    unsigned long appHandle,    /* Application handle needed for QAT KPT mode */
+    //DhsmWPKRSAFormat *wpk,      /* Wrapped Private Key structure for RSA */
+    void *wpk,      /* Wrapped Private Key structure for RSA */
+    unsigned char* swk,         /* Symmetric Wrapping Key (SWK) value */
+    int swk_len,                /* SWK length */
+    unsigned char* iv,          /* IV value used during Application Key encryption */
+    int iv_len,                 /* IV length */
+    int tag_len,                /* AES-GCM tag length */
+    void **cb_object            /* Pointer to store context block */
+    );
+
+typedef int (*fp_crypto_rsa_delete_object) (
+    void *cb_object             /* Pointer Crypto Block which is created during decrypt_create_object */
+    );
+
+typedef int (*fp_crypto_ecdsa_create_object) (
+    unsigned long appHandle,    /* Application handle needed for QAT KPT mode */
+    //DhsmWPKECDSAFormat *wpk,    /* Wrapped Private Key structure for RSA */
+    void *wpk,    /* Wrapped Private Key structure for RSA */
+    unsigned char* swk,         /* Symmetric Wrapping Key (SWK) value */
+    int swk_len,                /* SWK length */
+    unsigned char* iv,          /* IV value used during Application Key encryption */
+    int iv_len,                 /* IV length */
+    int tag_len,                /* AES-GCM tag length */
+    void **cb_object            /* Pointer to store context block */
+    );
+
+typedef int (*fp_crypto_ecdsa_delete_object) (
+    void *cb_object             /* Pointer Crypto Block which is created during decrypt_create_object */
+    );
+
+
+typedef struct 
+{
+    fp_crypto_rsa_decrypt_init     cb_crypto_rsa_decrypt_init;
+    fp_crypto_rsa_decrypt          cb_crypto_rsa_decrypt;	
+    fp_crypto_rsa_sign_init	   cb_crypto_rsa_sign_init;
+    fp_crypto_rsa_sign_update 	   cb_crypto_rsa_sign_update;
+    fp_crypto_rsa_sign_final	   cb_crypto_rsa_sign_final;
+    fp_crypto_rsa_sign		   cb_crypto_rsa_sign;
+    fp_crypto_ecdsa_sign	   cb_crypto_ecdsa_sign;
+    fp_crypto_ecdsa_verify	   cb_crypto_ecdsa_verify;
+    fp_crypto_del_apphandle	   cb_crypto_del_apphandle;
+    fp_crypto_swk_getParentKey 	   cb_crypto_swk_getParentKey;
+    fp_crypto_swk_import 	   cb_crypto_swk_import;
+    fp_crypto_rsa_create_object    cb_crypto_rsa_create_object;
+    fp_crypto_rsa_delete_object    cb_crypto_rsa_delete_object;
+    fp_crypto_ecdsa_create_object  cb_crypto_ecdsa_create_object;
+    fp_crypto_ecdsa_delete_object  cb_crypto_ecdsa_delete_object;
+
+} plugin_register;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/TPM2-Plugin/lib/include/tcti_util.h b/TPM2-Plugin/lib/include/tcti_util.h
new file mode 100644
index 0000000..1b3b289
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tcti_util.h
@@ -0,0 +1,109 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+
+//
+// The context for TCTI implementations is on opaque
+// structure. There shall never be a definition of its content.
+// Implementation provide the size information to
+// applications via the initialize call.
+// This makes use of a compiler trick that allows type
+// checking of the pointer even though the type isn't
+// defined.
+//
+// The first field of a Context must be the common part
+// (see below).
+#ifndef TSS2_TCTI_UTIL_H
+#define TSS2_TCTI_UTIL_H
+
+#if defined linux || defined unix
+#include <sys/socket.h>
+#define SOCKET int
+#endif
+
+#include <tcti/common.h>
+
+#define TCTI_MAGIC   0x7e18e9defa8bc9e2
+#define TCTI_VERSION 0x1
+
+#define TCTI_LOG_CALLBACK(ctx) ((TSS2_TCTI_CONTEXT_INTEL*)ctx)->logCallback
+#define TCTI_LOG_DATA(ctx)     ((TSS2_TCTI_CONTEXT_INTEL*)ctx)->logData
+#define TCTI_LOG_BUFFER_CALLBACK(ctx) ((TSS2_TCTI_CONTEXT_INTEL*)ctx)->logBufferCallback
+
+typedef TSS2_RC (*TCTI_TRANSMIT_PTR)( TSS2_TCTI_CONTEXT *tctiContext, size_t size, uint8_t *command);
+typedef TSS2_RC (*TCTI_RECEIVE_PTR) (TSS2_TCTI_CONTEXT *tctiContext, size_t *size, uint8_t *response, int32_t timeout);
+
+enum tctiStates { TCTI_STAGE_INITIALIZE, TCTI_STAGE_SEND_COMMAND, TCTI_STAGE_RECEIVE_RESPONSE };
+
+/* current Intel version */
+typedef struct {
+    uint64_t magic;
+    uint32_t version;
+    TCTI_TRANSMIT_PTR transmit;
+    TCTI_RECEIVE_PTR receive;
+    TSS2_RC (*finalize) (TSS2_TCTI_CONTEXT *tctiContext);
+    TSS2_RC (*cancel) (TSS2_TCTI_CONTEXT *tctiContext);
+    TSS2_RC (*getPollHandles) (TSS2_TCTI_CONTEXT *tctiContext,
+              TSS2_TCTI_POLL_HANDLE *handles, size_t *num_handles);
+    TSS2_RC (*setLocality) (TSS2_TCTI_CONTEXT *tctiContext, uint8_t locality);
+    struct {
+        UINT32 debugMsgEnabled: 1;
+        UINT32 locality: 8;
+        UINT32 commandSent: 1;
+        UINT32 rmDebugPrefix: 1;  // Used to add a prefix to RM debug messages.  This is ONLY used
+                                  // for TPM commands and responses as a way to differentiate
+                                  // RM generated TPM commands from application generated ones.
+
+        // Following two fields used to save partial response status in case receive buffer's too small.
+        UINT32 tagReceived: 1;
+        UINT32 responseSizeReceived: 1;
+        UINT32 protocolResponseSizeReceived: 1;
+    } status;
+
+    // Following two fields used to save partial response in case receive buffer's too small.
+    TPM_ST tag;
+    TPM_RC responseSize;
+
+    TSS2_TCTI_CONTEXT *currentTctiContext;
+
+    // Sockets if socket interface is being used.
+    SOCKET otherSock;
+    SOCKET tpmSock;
+    SOCKET currentConnectSock;
+
+    // File descriptor for device file if real TPM is being used.
+    int devFile;
+    UINT8 previousStage;            // Used to check for sequencing errors.
+    unsigned char responseBuffer[4096];
+    TCTI_LOG_CALLBACK logCallback;
+    TCTI_LOG_BUFFER_CALLBACK logBufferCallback;
+    void *logData;
+} TSS2_TCTI_CONTEXT_INTEL;
+
+#define TCTI_CONTEXT ( (TSS2_TCTI_CONTEXT_COMMON_CURRENT *)(SYS_CONTEXT->tctiContext) )
+#define TCTI_CONTEXT_INTEL ( (TSS2_TCTI_CONTEXT_INTEL *)tctiContext )
+
+#endif
diff --git a/TPM2-Plugin/lib/include/tpm2_alg_util.h b/TPM2-Plugin/lib/include/tpm2_alg_util.h
new file mode 100644
index 0000000..ce4083c
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tpm2_alg_util.h
@@ -0,0 +1,196 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+#ifndef LIB_TPM2_ALG_UTIL_H_
+#define LIB_TPM2_ALG_UTIL_H_
+
+#include <stdbool.h>
+
+#include <sapi/tpm20.h>
+
+/**
+ * Iterator callback routine for iterating over known algorithm name and value
+ * pairs.
+ * @param id
+ *  The algorithm id.
+ * @param name
+ *  The associated "nice-name".
+ * @param userdata
+ *  A user supplied data pointer.
+ * @return
+ *  True to stop iterating, false to keep iterating.
+ */
+typedef bool (*tpm2_alg_util_alg_iteraror)(TPM2_ALG_ID id, const char *name, void *userdata);
+
+/**
+ * Iterate over the algorithm name-value pairs calling the iterator callback for each pair.
+ * @param iterator
+ *  The iterator callback function.
+ * @param userdata
+ *  A pointer to user supplied data, this is passed to the iterator for each call.
+ */
+void tpm2_alg_util_for_each_alg(tpm2_alg_util_alg_iteraror iterator, void *userdata);
+
+/**
+ * Convert a "nice-name" string to an algorithm id.
+ * @param name
+ *  The "nice-name" to convert.
+ * @return
+ *  TPM2_ALG_ERROR on error, or a valid algorithm identifier.
+ */
+TPM2_ALG_ID tpm2_alg_util_strtoalg(const char *name);
+
+/**
+ * Convert an id to a nice-name.
+ * @param id
+ *  The id to convert.
+ * @return
+ *  The nice-name.
+ */
+const char *tpm2_alg_util_algtostr(TPM2_ALG_ID id);
+
+/**
+ * Converts either a string from algrotithm number or algorithm nice-name to
+ * an algorithm id.
+ * @param optarg
+ *  The string to convert from an algorithm number or nice name.
+ * @return
+ *  TPM2_ALG_ERROR on error or the algorithm id.
+ */
+TPM2_ALG_ID tpm2_alg_util_from_optarg(char *optarg);
+
+/**
+ * Detects if an algorithm is considered a hashing algorithm.
+ * @param id
+ *  The algorithm id to check.
+ * @return
+ *  True if it is a hash algorithm, False otherwise.
+ */
+bool tpm2_alg_util_is_hash_alg(TPM2_ALG_ID id);
+
+/**
+ * Contains the information from parsing an argv style vector of strings for
+ * pcr digest language specifications.
+ */
+typedef struct tpm2_pcr_digest_spec tpm2_pcr_digest_spec;
+struct tpm2_pcr_digest_spec {
+    TPML_DIGEST_VALUES digests;
+    TPMI_DH_PCR pcr_index;
+};
+
+/**
+ * Parses an argv array that contains a digest specification at each location
+ * within argv.
+ *
+ * The digest specification is as follows:
+ *   - A pcr identifier as understood by strtoul with 0 as the base.
+ *   - A colon followed by the algorithm hash specification.
+ *   - The algorithm hash specification is as follows:
+ *       - The algorithm friendly name or raw numerical as understood by
+ *         strtoul with a base of 0.
+ *       - An equals sign
+ *       - The hex hash value,
+ *
+ *   This all distills to a string that looks like this:
+ *   <pcr index>:<hash alg id>=<hash value>
+ *
+ *   Example:
+ *   "4:sha=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15"
+ *
+ *   Note:
+ *   Multiple specifications of PCR and hash are OK. Multiple hashes
+ *   cause the pcr to be extended with both hashes. Multiple same PCR
+ *   values cause the PCR to be extended multiple times. Extension
+ *   is done in order from left to right as specified.
+ *
+ *   At most 5 hash extensions per PCR entry are supported. This
+ *   is to keep the parser simple.
+ *
+ * @param sapi_context
+ *  The system API context for hashing files with the tpm. This can
+ *  be NULL if the argument vector doesn't have a file spec for the hash.
+ * @param argv
+ *  The argv of digest specifications to parse.
+ * @param len
+ *  The number of digest specifications to parse.
+ * @param digests
+ *  An array of tpm2_pcr_digest_spec big enough to hold len items.
+ * @return
+ *  True if parsing was successful, False otherwise.
+ *  @note
+ *  This function logs errors via LOG_ERR.
+ */
+bool pcr_parse_digest_list(char **argv, int len,
+        tpm2_pcr_digest_spec *digest_spec);
+
+/**
+ * Retrieves the size of a hash in bytes for a given hash
+ * algorithm or 0 if unknown/not found.
+ * @param id
+ *  The HASH algorithm identifier.
+ * @return
+ *  0 on failure or the size of the hash bytes.
+ */
+UINT16 tpm2_alg_util_get_hash_size(TPMI_ALG_HASH id);
+
+/**
+ * Extracts the plain signature data without any headers
+ *
+ * Communicates errors via LOG_ERR.
+ *
+ * @param size
+ *  Will receive the number of bytes stored in buffer.
+ * @signature The actual signature struct to extract the plain signature from.
+ * @return
+ *  Returns a buffer filled with the extracted signature or NULL on error.
+ *  Needs to be free()'d by the caller.
+ */
+UINT8* tpm2_extract_plain_signature(UINT16 *size, TPMT_SIGNATURE *signature);
+
+/**
+ * Retrieves an approproate signature scheme (scheme) signable by
+ * specified key (keyHandle) and hash algorithm (halg).
+ * @param sapi_context
+ *  System API context for tpm
+ * @param keyHandle
+ *  Handle to key used in signing operation
+ * @param halg
+ *  Hash algoritm for message
+ * @param scheme
+ *  Signature scheme output
+ * @return
+ *  True if successful
+ *  False otherwise, and scheme is left unmodified
+ */
+bool get_signature_scheme(TSS2_SYS_CONTEXT *sapi_context,
+        TPMI_DH_OBJECT keyHandle, TPMI_ALG_HASH halg,
+        TPMT_SIG_SCHEME *scheme);
+
+#endif /* LIB_TPM2_ALG_UTIL_H_ */
diff --git a/TPM2-Plugin/lib/include/tpm2_attr_util.h b/TPM2-Plugin/lib/include/tpm2_attr_util.h
new file mode 100644
index 0000000..2487982
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tpm2_attr_util.h
@@ -0,0 +1,98 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+#ifndef LIB_TPM2_ATTR_UTIL_H_
+#define LIB_TPM2_ATTR_UTIL_H_
+
+#include <stdbool.h>
+
+#include <sapi/tpm20.h>
+
+/**
+ * Converts a list of | (pipe) separated attributes as defined in tavle 204
+ * of https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
+ * to an actual bit field representation. The trailing TPMA_NV_ can be omitted and must be lower-case.
+ * For exmaple, TPMA_NV_PPWRITE, bcomes ppwrite. To append them together, just do the pipe inbetwwen.
+ * ppwrite|ownerwrite.
+ *
+ * @param attribute_list
+ *  The attribute string to parse, which may be modified in place.
+ * @param nvattrs
+ *  The TPMA_NV attributes set based on the attribute list. Only valid on true returns.
+ * @return
+ *  true on success, false on error.
+ */
+bool tpm2_attr_util_nv_strtoattr(char *attribute_list, TPMA_NV *nvattrs);
+
+/**
+ * Like tpm2_attr_util_nv_strtoattr() but converts TPMA_OBJECT attributes as defined in:
+ * Table 31 of https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
+ * @param attribute_list
+ *   The attribute string to parse, which may be modified in place.
+ *  The TPMA_OBJECT attributes set based on the attribute list. Only valid on true returns.
+ * @return
+ *  true on success, false on error.
+ */
+bool tpm2_attr_util_obj_strtoattr(char *attribute_list, TPMA_OBJECT *objattrs);
+
+/**
+ * Converts a numerical or friendly string described object attribute into the
+ * TPMA_OBJECT. Similar to tpm2_alg_util_from_optarg().
+ * @param argvalue
+ *  Either a raw numeric for a UINT32 or a friendly name object attribute list
+ *  as in tpm2_attr_util_nv_strtoattr().
+ * @param objattrs
+ *  The converted bits for a TPMA_OBJECT
+ * @return
+ *  true on success or false on error.
+ */
+bool tpm2_attr_util_obj_from_optarg(char *argvalue, TPMA_OBJECT *objattrs);
+
+/**
+ * Converts a TPMA_NV structure to a friendly name style string.
+ * @param nvattrs
+ *  The nvattrs to convert to nice name.
+ * @return A string allocated with calloc(), callers shall use
+ * free() to free it. The string is a null terminated text representation
+ * of the TPMA_NV attributes.
+ */
+char *tpm2_attr_util_nv_attrtostr(TPMA_NV nvattrs);
+
+/**
+ * Like tpm2_nv_util_obj_strtoattr() but converts TPMA_OBJECT attributes as defined in:
+ * Table 31 of https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
+ * @param objattrs
+ *  The object parameters to convert to a name
+ * @return
+ *  The name of the object attrs as a string that must be freed via free().
+ */
+char *tpm2_attr_util_obj_attrtostr(TPMA_OBJECT objattrs);
+
+#endif /* LIB_TPM2_ATTR_UTIL_H_ */
diff --git a/TPM2-Plugin/lib/include/tpm2_error.h b/TPM2-Plugin/lib/include/tpm2_error.h
new file mode 100644
index 0000000..0549edc
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tpm2_error.h
@@ -0,0 +1,136 @@
+//**********************************************************************;
+// Copyright (c) 2018, 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_ERROR_H_
+#define LIB_TPM2_ERROR_H_
+
+#include <stdbool.h>
+
+#include <sapi/tpm20.h>
+
+/**
+ * Number of error layers
+ */
+#define TPM2_ERROR_TSS2_RC_LAYER_COUNT (TSS2_RC_LAYER_MASK >> TSS2_RC_LAYER_SHIFT)
+
+/**
+ * Mask for the error bits of tpm2 compliant return code.
+ */
+#define TPM2_ERROR_TSS2_RC_ERROR_MASK 0xFFFF
+
+/**
+ * Retrieves the error bits from a TSS2_RC. The error bits are
+ * contained in the first 2 octets.
+ * @param rc
+ *  The rc to query for the error bits.
+ * @return
+ *  The error bits.
+ */
+static inline UINT16 tpm2_error_get(TSS2_RC rc) {
+    return ((rc & TPM2_ERROR_TSS2_RC_ERROR_MASK));
+}
+
+/**
+ * A custom error handler prototype.
+ * @param rc
+ *  The rc to decode with only the error bits set, ie no need to mask the
+ *  layer bits out. Handlers will never be invoked with the error bits set
+ *  to 0, as zero always indicates success.
+ * @return
+ *  An error string describing the rc. If the handler cannot determine
+ *  a valid response, it can return NULL indicating that the framework
+ *  should just print the raw hexidecimal value of the error field of
+ *  a tpm2_err_layer_rc.
+ *  Note that this WILL NOT BE FREED by the caller,
+ *  i.e. static.
+ */
+typedef const char *(*tpm2_error_handler)(TSS2_RC rc);
+
+/**
+ * Register or unregister a custom layer error handler.
+ * @param layer
+ *  The layer in which to register a handler for. It is an error
+ *  to register for the following reserved layers:
+ *    - TSS2_TPM_RC_LAYER  - layer  0
+ *    - TSS2_SYS_RC_LAYER  - layer  8
+ *    - TSS2_MU_RC_LAYER   - layer  9
+ *    - TSS2_TCTI_RC_LAYER - layer 10
+ * @param name
+ *  A friendly layer name. It is an error for the name to be of
+ *  length 0 or greater than 4.
+ * @param handler
+ *  The handler function to register or NULL to unregister.
+ * @return
+ *  True on success or False on error.
+ */
+bool tpm2_error_set_handler(UINT8 layer, const char *name,
+        tpm2_error_handler handler);
+
+/**
+ * Given a TSS2_RC return code, provides a static error string in the format:
+ * <layer-name>:<layer-specific-msg>.
+ *
+ * The layer-name section will either be the friendly name, or if no layer
+ * handler is registered, the base10 layer number.
+ *
+ * The "layer-specific-msg" is layer specific and will contain details on the
+ * error that occurred or the error code if it couldn't look it up.
+ *
+ * Known layer specific substrings:
+ * TPM - The tpm layer produces 2 distinct format codes that allign with:
+ *   - Section 6.6 of: https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
+ *   - Section 39.4 of: https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf
+ *
+ *   The two formats are format 0 and format 1.
+ *   Format 0 string format:
+ *     - "<error|warn>(<version>): <description>
+ *     - Examples:
+ *       - error(1.2): bad tag
+ *       - warn(2.0): the 1st handle in the handle area references a transient object or session that is not loaded
+ *
+ *   Format 1 string format:
+ *      - <handle|session|parameter>(<index>):<description>
+ *      - Examples:
+ *        - handle(unk):value is out of range or is not correct for the context
+ *        - tpm:handle(5):value is out of range or is not correct for the context
+ *
+ *   Note that passing TPM2_RC_SUCCESS results in the layer specific message of "success".
+ *
+ *   The System, TCTI and Marshaling (MU) layers, all define simple string
+ *   returns analogous to strerror(3).
+ *
+ *   Unknown layers will have the layer number in decimal and then a layer specific string of
+ *   a hex value representing the error code. For example: 9:0x3
+ *
+ * @param rc
+ *  The error code to decode.
+ * @return
+ *  A human understandable error description string.
+ */
+const char *tpm2_error_str(TSS2_RC rc);
+
+#endif /* LIB_TPM2_ERROR_H_ */
diff --git a/TPM2-Plugin/lib/include/tpm2_hash.h b/TPM2-Plugin/lib/include/tpm2_hash.h
new file mode 100644
index 0000000..7fab882
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tpm2_hash.h
@@ -0,0 +1,84 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+#ifndef SRC_TPM_HASH_H_
+#define SRC_TPM_HASH_H_
+
+#include <stdbool.h>
+
+#include <sapi/tpm20.h>
+
+/**
+ * Hashes a BYTE array via the tpm.
+ * @param sapi_context
+ *  The system api context.
+ * @param hash_alg
+ *  The hashing algorithm to use.
+ * @param hierarchy
+ *  The hierarchy.
+ * @param buffer
+ *  The data to hash.
+ * @param length
+ *  The length of the data.
+ * @param result
+ *  The digest result.
+ * @param validation
+ *  The validation ticket. Note that some hierarchies don't produce a
+ *  validation ticket and thus size will be 0.
+ * @return
+ *  True on success, false otherwise.
+ */
+bool tpm2_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH halg,
+        TPMI_RH_HIERARCHY hierarchy, BYTE *buffer, UINT16 length,
+        TPM2B_DIGEST *result, TPMT_TK_HASHCHECK *validation);
+
+/**
+ * Hashes a FILE * object via the tpm.
+ * @param sapi_context
+ *  The system api context.
+ * @param hash_alg
+ *  The hashing algorithm to use.
+ * @param hierarchy
+ *  The hierarchy.
+ * @param input
+ *  The FILE object to hash.
+ * @param result
+ *  The digest result.
+ * @param validation
+ *  The validation ticket. Note that some hierarchies don't produce a
+ *  validation ticket and thus size will be 0.
+ * @return
+ *  True on success, false otherwise.
+ */
+bool tpm2_hash_file(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH halg,
+        TPMI_RH_HIERARCHY hierarchy, FILE *input, TPM2B_DIGEST *result,
+        TPMT_TK_HASHCHECK *validation);
+
+#endif /* SRC_TPM_HASH_H_ */
diff --git a/TPM2-Plugin/lib/include/tpm2_plugin_api.h b/TPM2-Plugin/lib/include/tpm2_plugin_api.h
new file mode 100644
index 0000000..238af99
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tpm2_plugin_api.h
@@ -0,0 +1,136 @@
+//**********************************************************************;
+// 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 __TPM_API_H__
+#define __TPM_API_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <getopt.h>
+
+#include <sapi/tpm20.h>
+
+#include "plugin_register.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TPM_SKM_SRK_HANDLE 0x81000011
+
+#define TPM_SKM_AC0_HANDLE 0x90000000
+#define TPM_SKM_AC1_HANDLE 0x90000001
+#define TPM_SKM_AC2_HANDLE 0x90000002
+
+#define TPM_SKM_APP_HANDLE 0x91100001
+
+#define INIT_SIMPLE_TPM2B_SIZE( type ) (type).t.size = sizeof( type ) - 2;
+
+#define APP_RC_OFFSET 0x100
+
+#define TSS2_APP_RC_PASSED                      (APP_RC_PASSED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_GET_NAME_FAILED             (APP_RC_GET_NAME_FAILED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_CREATE_SESSION_KEY_FAILED   (APP_RC_CREATE_SESSION_KEY_FAILED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_SESSION_SLOT_NOT_FOUND      (APP_RC_SESSION_SLOT_NOT_FOUND + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_BAD_ALGORITHM               (APP_RC_BAD_ALGORITHM + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_SYS_CONTEXT_CREATE_FAILED   (APP_RC_SYS_CONTEXT_CREATE_FAILED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_GET_SESSION_STRUCT_FAILED   (APP_RC_GET_SESSION_STRUCT_FAILED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_GET_SESSION_ALG_ID_FAILED   (APP_RC_GET_SESSION_ALG_ID_FAILED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_INIT_SYS_CONTEXT_FAILED     (APP_RC_INIT_SYS_CONTEXT_FAILED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_TEARDOWN_SYS_CONTEXT_FAILED (APP_RC_TEARDOWN_SYS_CONTEXT_FAILED + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+#define TSS2_APP_RC_BAD_LOCALITY                (APP_RC_BAD_LOCALITY + APP_RC_OFFSET + TSS2_APP_ERROR_LEVEL)
+
+enum TSS2_APP_RC_CODE
+{
+    APP_RC_PASSED,
+    APP_RC_GET_NAME_FAILED,
+    APP_RC_CREATE_SESSION_KEY_FAILED,
+    APP_RC_SESSION_SLOT_NOT_FOUND,
+    APP_RC_BAD_ALGORITHM,
+    APP_RC_SYS_CONTEXT_CREATE_FAILED,
+    APP_RC_GET_SESSION_STRUCT_FAILED,
+    APP_RC_GET_SESSION_ALG_ID_FAILED,
+    APP_RC_INIT_SYS_CONTEXT_FAILED,
+    APP_RC_TEARDOWN_SYS_CONTEXT_FAILED,
+    APP_RC_BAD_LOCALITY
+};
+
+TSS2_SYS_CONTEXT *InitSysContext (UINT16 maxCommandSize,
+                                    TSS2_TCTI_CONTEXT *tctiContext,
+                                    TSS2_ABI_VERSION *abiVersion );
+
+void TeardownSysContext( TSS2_SYS_CONTEXT **sysContext );
+
+TSS2_RC TeardownTctiResMgrContext( TSS2_TCTI_CONTEXT *tctiContext );
+
+int tpm2_rsa_create_object(
+                        unsigned long appHandle,
+                        //DhsmWPKRSAFormat* wpk,
+                        void *wpk,
+                        unsigned char* swk,
+                        int swk_len,
+                        unsigned char* iv,
+                        int iv_len,
+                        int tag_len,
+                        void **cb_object);
+
+int tpm2_rsa_delete_object(
+                        void *cb_object);
+
+int tpm2_rsa_sign_init(
+        unsigned long mechanish,
+        void *param,
+        size_t len,
+        void *ctx);
+
+int tpm2_rsa_sign(
+        void *ctx,
+        unsigned char *msg,
+        int msg_len,
+        unsigned char *sig,
+        int *sig_len);
+
+
+int tpm2_import_object(
+        unsigned long appHandle, 
+        unsigned char* tlvbuffer, 
+        int buflen, 
+        unsigned char* iv, 
+        int iv_len, 
+        unsigned char* tpm_pwd, 
+        int tpm_pwd_len);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/TPM2-Plugin/lib/include/tpm2_tcti_ldr.h b/TPM2-Plugin/lib/include/tpm2_tcti_ldr.h
new file mode 100644
index 0000000..1e20d3d
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tpm2_tcti_ldr.h
@@ -0,0 +1,62 @@
+//**********************************************************************;
+// Copyright (c) 2018, 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 <sapi/tpm20.h>
+
+#ifndef LIB_TPM2_TCTI_LDR_H_
+#define LIB_TPM2_TCTI_LDR_H_
+
+/**
+ * Loads a TCTI from a friendly name, library name, or path.
+ * For example
+ *  friendly:     path = tabrmd
+ *  library name: path = libtcti-socket.so
+ *  full path:    path = /home/user/lib/libtcti-custom.so
+ * @param path
+ *  The path/library to load.
+ * @param opts
+ *  The tcti option configs.
+ * @return
+ *  A tcti context on success or NULL on failure.
+ */
+TSS2_TCTI_CONTEXT *tpm2_tcti_ldr_load(const char *path, const char *opts);
+
+/**
+ * Returns the loaded TCTIs information structure,
+ * which contains the initialization routine, description
+ * and help string amongst other things.
+ * @return
+ *  NULL if no TCTI is loaded, else the info structure pointer.
+ */
+const TSS2_TCTI_INFO *tpm2_tcti_ldr_getinfo(void);
+
+/**
+ * Unloads the tcti loaded via tpm2_tcti_ldr_load();
+ */
+void tpm2_tcti_ldr_unload(void);
+
+#endif /* LIB_TPM2_TCTI_LDR_H_ */
diff --git a/TPM2-Plugin/lib/include/tpm2_util.h b/TPM2-Plugin/lib/include/tpm2_util.h
new file mode 100644
index 0000000..edc759d
--- /dev/null
+++ b/TPM2-Plugin/lib/include/tpm2_util.h
@@ -0,0 +1,325 @@
+//**********************************************************************;
+// 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.
+//**********************************************************************;
+#ifndef STRING_BYTES_H
+#define STRING_BYTES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <sapi/tpm20.h>
+
+#include "tpm2_error.h"
+
+#if defined (__GNUC__)
+#define COMPILER_ATTR(...) __attribute__((__VA_ARGS__))
+#else
+#define COMPILER_ATTR(...)
+#endif
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define UNUSED(x) (void)x
+
+#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
+
+#define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->field)))
+
+#define TSS2_APP_RC_LAYER TSS2_RC_LAYER(5)
+
+#define TPM2B_TYPE_INIT(type, field) { .size = BUFFER_SIZE(type, field), }
+#define TPM2B_INIT(xsize) { .size = xsize, }
+#define TPM2B_EMPTY_INIT TPM2B_INIT(0)
+#define TPM2B_SENSITIVE_CREATE_EMPTY_INIT { \
+           .sensitive = { \
+                .data = {   \
+                    .size = 0 \
+                }, \
+                .userAuth = {   \
+                    .size = 0 \
+                } \
+            } \
+    }
+
+#define TPMS_AUTH_COMMAND_INIT(session_handle) { \
+        .sessionHandle = session_handle,\
+	    .nonce = TPM2B_EMPTY_INIT, \
+	    .sessionAttributes = TPMA_SESSION_CONTINUESESSION, \
+	    .hmac = TPM2B_EMPTY_INIT \
+    }
+
+#define TPMS_AUTH_COMMAND_EMPTY_INIT TPMS_AUTH_COMMAND_INIT(0)
+
+
+#define TPMT_TK_CREATION_EMPTY_INIT { \
+        .tag = 0, \
+		.hierarchy = 0, \
+		.digest = TPM2B_EMPTY_INIT \
+    }
+
+#define TPML_PCR_SELECTION_EMPTY_INIT { \
+        .count = 0, \
+    } //ignore pcrSelections since count is 0.
+
+#define TPMS_CAPABILITY_DATA_EMPTY_INIT { \
+        .capability = 0, \
+    } // ignore data since capability is 0.
+
+#define TPMT_TK_HASHCHECK_EMPTY_INIT { \
+		.tag = 0, \
+		.hierarchy = 0, \
+		.digest = TPM2B_EMPTY_INIT \
+    }
+
+#define TSS2L_SYS_AUTH_COMMAND_INIT(cnt, array) { \
+        .count = cnt, \
+        .auths = array, \
+    }
+
+/*
+ * This macro is useful as a wrapper around SAPI functions to automatically
+ * retry function calls when the RC is TPM2_RC_RETRY.
+ */
+#define TSS2_RETRY_EXP(expression)                         \
+    ({                                                     \
+        TSS2_RC __result = 0;                              \
+        do {                                               \
+            __result = (expression);                       \
+        } while (tpm2_error_get(__result) == TPM2_RC_RETRY); \
+        __result;                                          \
+    })
+
+/**
+ * prints output to stdout respecting the quiet option.
+ * Ie when quiet, don't print.
+ * @param fmt
+ *  The format specifier, ala printf.
+ * @param ...
+ *  The varargs, just like printf.
+ */
+#define tpm2_tool_output(fmt, ...)                   \
+    do {                                        \
+        if (output_enabled) {                   \
+            printf(fmt, ##__VA_ARGS__);         \
+        }                                       \
+    } while (0)
+
+int tpm2_util_hex_to_byte_structure(const char *inStr, UINT16 *byteLenth, BYTE *byteBuffer);
+
+/**
+ * Appends a TPM2B buffer to a MAX buffer.
+ * @param result
+ *  The MAX buffer to append to
+ * @param append
+ *  The buffer to append to result.
+ * @return
+ *  true on success, false otherwise.
+ */
+bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append);
+
+/**
+ * Converts a numerical string into a uint32 value.
+ * @param str
+ *  The numerical string to convert.
+ * @param value
+ *  The value to store the conversion into.
+ * @return
+ *  true on success, false otherwise.
+ */
+bool tpm2_util_string_to_uint32(const char *str, uint32_t *value);
+
+/**
+ * Converts a numerical string into a uint16 value.
+ * @param str
+ *  The numerical string to convert.
+ * @param value
+ *  The value to store the conversion into.
+ * @return
+ *  true on success, false otherwise.
+ */
+bool tpm2_util_string_to_uint16(const char *str, uint16_t *value);
+
+/**
+ * Prints an xxd compatible hexdump to stdout if output is enabled,
+ * ie no -Q option.
+ *
+ * @param data
+ *  The data to print.
+ * @param len
+ *  The length of the data.
+ * @param plain
+ *  true for a plain hex string false for an xxd compatable
+ *  dump.
+ */
+void tpm2_util_hexdump(const BYTE *data, size_t len, bool plain);
+
+/**
+ * Prints an xxd compatible hexdump to stdout if output is enabled,
+ * ie no -Q option.
+ *
+ * @param fd
+ *  A readable open file.
+ * @param len
+ *  The length of the data to read and print.
+ * @param plain
+ *  true for a plain hex string false for an xxd compatable
+ *  dump.
+ * @return
+ *  true if len bytes were successfully read and printed,
+ *  false otherwise
+ */
+bool tpm2_util_hexdump_file(FILE *fd, size_t len, bool plain);
+
+/**
+ * Prints a TPM2B as a hex dump.
+ * @param buffer the TPM2B to print.
+ */
+static inline void tpm2_util_print_tpm2b(TPM2B *buffer) {
+
+    return tpm2_util_hexdump(buffer->buffer, buffer->size, true);
+}
+
+/**
+ * Reads a TPM2B object from FILE* and prints data in hex.
+ * @param fd
+ *  A readable open file.
+ */
+bool tpm2_util_print_tpm2b_file(FILE *fd);
+
+/**
+ * Copies a tpm2b from dest to src and clears dest if src is NULL.
+ * If src is NULL, it is a NOP.
+ * @param dest
+ *  The destination TPM2B
+ * @param src
+ *  The source TPM2B
+ * @return
+ *  The number of bytes copied.
+ */
+UINT16 tpm2_util_copy_tpm2b(TPM2B *dest, TPM2B *src);
+
+/**
+ * Checks if the host is big endian
+ * @return
+ *  True of the host is big endian false otherwise.
+ */
+bool tpm2_util_is_big_endian(void);
+
+/**
+ * Swaps the endianess of 16 bit value.
+ * @param data
+ *  A 16 bit value to swap the endianess on.
+ * @return
+ * The 16 bit value with the endianess swapped.
+ */
+UINT16 tpm2_util_endian_swap_16(UINT16 data);
+
+/**
+ * Just like string_bytes_endian_convert_16 but for 32 bit values.
+ */
+UINT32 tpm2_util_endian_swap_32(UINT32 data);
+
+/**
+ * Just like string_bytes_endian_convert_16 but for 64 bit values.
+ */
+UINT64 tpm2_util_endian_swap_64(UINT64 data);
+
+/**
+ * Converts a 16 bit value from host endianess to network endianess.
+ * @param data
+ *  The data to possibly swap endianess.
+ * @return
+ *  The swapped data.
+ */
+UINT16 tpm2_util_hton_16(UINT16 data);
+
+/**
+ * Just like string_bytes_endian_hton_16 but for 32 bit values.
+ */
+UINT32 tpm2_util_hton_32(UINT32 data);
+
+/**
+ * Just like string_bytes_endian_hton_16 but for 64 bit values.
+ */
+UINT64 tpm2_util_hton_64(UINT64 data);
+
+/**
+ * Converts a 16 bit value from network endianess to host endianess.
+ * @param data
+ *  The data to possibly swap endianess.
+ * @return
+ *  The swapped data.
+ */
+UINT16 tpm2_util_ntoh_16(UINT16 data);
+
+/**
+ * Just like string_bytes_endian_ntoh_16 but for 32 bit values.
+ */
+UINT32 tpm2_util_ntoh_32(UINT32 data);
+
+/**
+ * Just like string_bytes_endian_ntoh_16 but for 64 bit values.
+ */
+UINT64 tpm2_util_ntoh_64(UINT64 data);
+
+/**
+ * Counts the number of set bits aka a population count.
+ * @param data
+ *  The data to count set bits in.
+ * @return
+ *  The number of set bits or population count.
+ */
+UINT32 tpm2_util_pop_count(UINT32 data);
+
+/**
+ * Prints whitespace indention for yaml output.
+ * @param indent_count
+ *  Number of times to indent
+ */
+void print_yaml_indent(size_t indent_count);
+
+/**
+ * Convert a TPM2B_PUBLIC into a yaml format and output if not quiet.
+ * @param public
+ *  The TPM2B_PUBLIC to output in YAML format.
+ */
+void tpm2_util_public_to_yaml(TPM2B_PUBLIC *public);
+
+
+/**
+ * Convert a TPMA_OBJECT to a yaml format and output if not quiet.
+ * @param obj
+ *  The TPMA_OBJECT attributes to print.
+ */
+void tpm2_util_tpma_object_to_yaml(TPMA_OBJECT obj);
+
+#endif /* STRING_BYTES_H */
diff --git a/TPM2-Plugin/lib/log.c b/TPM2-Plugin/lib/log.c
new file mode 100644
index 0000000..14797e4
--- /dev/null
+++ b/TPM2-Plugin/lib/log.c
@@ -0,0 +1,93 @@
+//**********************************************************************;
+// 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 <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "log.h"
+
+/*
+ * Note that the logging library is not thread safe, thus calls on separate
+ * threads will yield an interleaved output on stderr.
+ */
+
+static log_level current_log_level = log_level_warning;
+
+void
+log_set_level (log_level value)
+{
+    current_log_level = value;
+}
+
+static const char *
+get_level_msg (log_level level)
+{
+    const char *value = "UNK";
+    switch (level)
+    {
+        case log_level_error:
+            value = "ERROR";
+            break;
+        case log_level_warning:
+            value = "WARN";
+            break;
+        case log_level_verbose:
+            value = "INFO";
+    }
+    return value;
+}
+
+void
+_log (log_level level, const char *file, unsigned lineno, const char *fmt, ...)
+{
+
+    /* Skip printing messages outside of the log level */
+    if (level > current_log_level)
+        return;
+
+    va_list argptr;
+    va_start(argptr, fmt);
+
+    /* Verbose output prints file and line on error */
+    if (current_log_level >= log_level_verbose)
+        fprintf (stderr, "%s on line: \"%u\" in file: \"%s\": ",
+                 get_level_msg (level), lineno, file);
+    else
+        fprintf (stderr, "%s: ", get_level_msg (level));
+
+    /* Print the user supplied message */
+    vfprintf (stderr, fmt, argptr);
+
+    /* always add a new line so the user doesn't have to */
+    fprintf (stderr, "\n");
+
+    va_end(argptr);
+}
diff --git a/TPM2-Plugin/lib/plugin_register.c b/TPM2-Plugin/lib/plugin_register.c
new file mode 100644
index 0000000..3de390c
--- /dev/null
+++ b/TPM2-Plugin/lib/plugin_register.c
@@ -0,0 +1,40 @@
+//**********************************************************************;
+// 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 <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <dirent.h>
+
+#include "plugin_register.h"
+int (*plugin_init)(char* configPath);
+int (*plugin_functions_mapping)(plugin_register *plugin_fp);
+int (*plugin_finalize)();
diff --git a/TPM2-Plugin/lib/tpm2_alg_util.c b/TPM2-Plugin/lib/tpm2_alg_util.c
new file mode 100644
index 0000000..975f4ae
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_alg_util.c
@@ -0,0 +1,437 @@
+//**********************************************************************;
+// 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 <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sapi/tpm20.h>
+
+#include "files.h"
+#include "log.h"
+#include "tpm2_hash.h"
+#include "tpm2_alg_util.h"
+#include "tpm2_util.h"
+
+typedef struct alg_pair alg_pair;
+struct alg_pair {
+    const char *name;
+    TPM2_ALG_ID id;
+};
+
+void tpm2_alg_util_for_each_alg(tpm2_alg_util_alg_iteraror iterator, void *userdata) {
+
+    static const alg_pair algs[] = {
+        { .name = "rsa", .id = TPM2_ALG_RSA },
+        { .name = "sha1", .id = TPM2_ALG_SHA1 },
+        { .name = "hmac", .id = TPM2_ALG_HMAC },
+        { .name = "aes", .id = TPM2_ALG_AES },
+        { .name = "mgf1", .id = TPM2_ALG_MGF1 },
+        { .name = "keyedhash", .id = TPM2_ALG_KEYEDHASH },
+        { .name = "xor", .id = TPM2_ALG_XOR },
+        { .name = "sha256", .id = TPM2_ALG_SHA256 },
+        { .name = "sha384", .id = TPM2_ALG_SHA384 },
+        { .name = "sha512", .id = TPM2_ALG_SHA512 },
+        { .name = "null", .id = TPM2_ALG_NULL },
+        { .name = "sm3_256", .id = TPM2_ALG_SM3_256 },
+        { .name = "sm4", .id = TPM2_ALG_SM4 },
+        { .name = "rsassa", .id = TPM2_ALG_RSASSA },
+        { .name = "rsaes", .id = TPM2_ALG_RSAES },
+        { .name = "rsapss", .id = TPM2_ALG_RSAPSS },
+        { .name = "oaep", .id = TPM2_ALG_OAEP },
+        { .name = "ecdsa", .id = TPM2_ALG_ECDSA },
+        { .name = "ecdh", .id = TPM2_ALG_ECDH },
+        { .name = "ecdaa", .id = TPM2_ALG_ECDAA },
+        { .name = "sm2", .id = TPM2_ALG_SM2 },
+        { .name = "ecschnorr", .id = TPM2_ALG_ECSCHNORR },
+        { .name = "ecmqv", .id = TPM2_ALG_ECMQV },
+        { .name = "kdf1_sp800_56a", .id = TPM2_ALG_KDF1_SP800_56A },
+        { .name = "kdf2", .id = TPM2_ALG_KDF2 },
+        { .name = "kdf1_sp800_108", .id = TPM2_ALG_KDF1_SP800_108 },
+        { .name = "ecc", .id = TPM2_ALG_ECC },
+        { .name = "symcipher", .id = TPM2_ALG_SYMCIPHER },
+        { .name = "camellia", .id = TPM2_ALG_CAMELLIA },
+        { .name = "sha3_256", .id = TPM2_ALG_SHA3_256 },
+        { .name = "sha3_384", .id = TPM2_ALG_SHA3_384 },
+        { .name = "sha3_512", .id = TPM2_ALG_SHA3_512 },
+        { .name = "ctr", .id = TPM2_ALG_CTR },
+        { .name = "ofb", .id = TPM2_ALG_OFB },
+        { .name = "cbc", .id = TPM2_ALG_CBC },
+        { .name = "cfb", .id = TPM2_ALG_CFB },
+        { .name = "ecb", .id = TPM2_ALG_ECB },
+    };
+
+    size_t i;
+    for (i=0; i < ARRAY_LEN(algs); i++) {
+        const alg_pair *alg = &algs[i];
+        bool result = iterator(alg->id, alg->name, userdata);
+        if (result) {
+            return;
+        }
+    }
+}
+
+static bool find_match(TPM2_ALG_ID id, const char *name, void *userdata) {
+
+    alg_pair *search_data = (alg_pair *)userdata;
+
+    /*
+     * if name, then search on name, else
+     * search by id.
+     */
+    if (search_data->name && !strcmp(search_data->name, name)) {
+        search_data->id = id;
+        return true;
+    } else if (search_data->id == id) {
+        search_data->name = name;
+        return true;
+    }
+
+    return false;
+}
+
+TPM2_ALG_ID tpm2_alg_util_strtoalg(const char *name) {
+
+    alg_pair userdata = {
+        .name = name,
+        .id = TPM2_ALG_ERROR
+    };
+
+    if (name) {
+        tpm2_alg_util_for_each_alg(find_match, &userdata);
+    }
+
+    return userdata.id;
+}
+
+const char *tpm2_alg_util_algtostr(TPM2_ALG_ID id) {
+
+    alg_pair userdata = {
+        .name = NULL,
+        .id = id
+    };
+
+    tpm2_alg_util_for_each_alg(find_match, &userdata);
+
+    return userdata.name;
+}
+
+TPM2_ALG_ID tpm2_alg_util_from_optarg(char *optarg) {
+
+    TPM2_ALG_ID halg;
+    bool res = tpm2_util_string_to_uint16(optarg, &halg);
+    if (!res) {
+        halg = tpm2_alg_util_strtoalg(optarg);
+    }
+    return halg;
+}
+
+bool tpm2_alg_util_is_hash_alg(TPM2_ALG_ID id) {
+
+    switch (id) {
+    case TPM2_ALG_SHA1 :
+        /* fallsthrough */
+    case TPM2_ALG_SHA256 :
+        /* fallsthrough */
+    case TPM2_ALG_SHA384 :
+        /* fallsthrough */
+    case TPM2_ALG_SHA512 :
+        /* fallsthrough */
+    case TPM2_ALG_SM3_256 :
+        return true;
+        /* no default */
+    }
+
+    return false;
+}
+
+UINT16 tpm2_alg_util_get_hash_size(TPMI_ALG_HASH id) {
+
+    switch (id) {
+    case TPM2_ALG_SHA1 :
+        return TPM2_SHA1_DIGEST_SIZE;
+    case TPM2_ALG_SHA256 :
+        return TPM2_SHA256_DIGEST_SIZE;
+    case TPM2_ALG_SHA384 :
+        return TPM2_SHA384_DIGEST_SIZE;
+    case TPM2_ALG_SHA512 :
+        return TPM2_SHA512_DIGEST_SIZE;
+    case TPM2_ALG_SM3_256 :
+        return TPM2_SM3_256_DIGEST_SIZE;
+        /* no default */
+    }
+
+    return 0;
+}
+
+static const char *hex_to_byte_err(int rc) {
+
+    switch (rc) {
+    case -2:
+        return "String not even in length";
+    case -3:
+        return "Non hex digit found";
+    case -4:
+        return "Hex value too big for digest";
+    }
+    return "unknown";
+}
+
+bool pcr_parse_digest_list(char **argv, int len,
+        tpm2_pcr_digest_spec *digest_spec) {
+
+    /*
+     * int is chosen because of what is passed in from main, avoids
+     * sign differences.
+     * */
+    int i;
+    for (i = 0; i < len; i++) {
+        tpm2_pcr_digest_spec *dspec = &digest_spec[i];
+
+        UINT32 count = 0;
+
+        /*
+         * Split <pcr index>:<hash alg>=<hash value>,... on : and separate with null byte, ie:
+         * <pce index> '\0' <hash alg>'\0'<data>
+         *
+         * Start by splitting out the pcr index, and validating it.
+         */
+        char *spec_str = argv[i];
+        char *pcr_index_str = spec_str;
+        char *digest_spec_str = strchr(spec_str, ':');
+        if (!digest_spec_str) {
+            LOG_ERR("Expecting : in digest spec, not found, got: \"%s\"", spec_str);
+            return false;
+        }
+
+        *digest_spec_str = '\0';
+        digest_spec_str++;
+
+        bool result = tpm2_util_string_to_uint32(pcr_index_str, &dspec->pcr_index);
+        if (!result) {
+            LOG_ERR("Got invalid PCR Index: \"%s\", in digest spec: \"%s\"",
+                    pcr_index_str, spec_str);
+            return false;
+        }
+
+        /* now that the pcr_index is removed, parse the remaining <hash_name>=<hash_value>,.. */
+        char *digest_hash_tok;
+        char *save_ptr = NULL;
+
+        /* keep track of digests we have seen */
+
+        while ((digest_hash_tok = strtok_r(digest_spec_str, ",", &save_ptr))) {
+            digest_spec_str = NULL;
+
+            if (count >= ARRAY_LEN(dspec->digests.digests)) {
+                LOG_ERR("Specified too many digests per spec, max is: %zu",
+                        ARRAY_LEN(dspec->digests.digests));
+                return false;
+            }
+
+            TPMT_HA *d = &dspec->digests.digests[count];
+
+            char *stralg = digest_hash_tok;
+            char *split = strchr(digest_hash_tok, '=');
+            if (!split) {
+                LOG_ERR("Expecting = in <hash alg>=<hash value> spec, got: "
+                        "\"%s\"", digest_hash_tok);
+                return false;
+            }
+            *split = '\0';
+            split++;
+
+            char *data = split;
+
+            /*
+             * Convert and validate the hash algorithm. It should be a hash algorithm
+             */
+            TPM2_ALG_ID alg = tpm2_alg_util_from_optarg(stralg);
+            if (alg == TPM2_ALG_ERROR) {
+                LOG_ERR("Could not convert algorithm, got: \"%s\"", stralg);
+                return false;
+            }
+
+            bool is_hash_alg = tpm2_alg_util_is_hash_alg(alg);
+            if (!is_hash_alg) {
+                LOG_ERR("Algorithm is not a hash algorithm, got: \"%s\"",
+                        stralg);
+                return false;
+            }
+
+            d->hashAlg = alg;
+
+            /* fill up the TPMT_HA structure with algorithm and digest */
+            BYTE *digest_data = (BYTE *) &d->digest;
+
+            UINT16 expected_hash_size = tpm2_alg_util_get_hash_size(alg);
+            /* strip any preceding hex on the data as tpm2_util_hex_to_byte_structure doesn't support it */
+            bool is_hex = !strncmp("0x", data, 2);
+            if (is_hex) {
+                data += 2;
+            }
+
+            UINT16 size =  expected_hash_size;
+            int rc = tpm2_util_hex_to_byte_structure(data, &size,
+                    digest_data);
+            if (rc) {
+                LOG_ERR("Error \"%s\" converting hex string as data, got:"
+                    " \"%s\"", hex_to_byte_err(rc), data);
+                return false;
+            }
+
+            if (expected_hash_size != size) {
+                LOG_ERR(
+                        "Algorithm \"%s\" expects a size of %u bytes, got: %u",
+                        stralg, expected_hash_size, size);
+                return false;
+            }
+
+            count++;
+        }
+
+        if (!count) {
+            LOG_ERR("Missing or invalid <hash alg>=<hash value> spec for pcr:"
+                    " \"%s\"", pcr_index_str);
+            return false;
+        }
+
+        /* assign count at the end, so count is 0 on error */
+        dspec->digests.count = count;
+    }
+
+    return true;
+}
+
+UINT8* tpm2_extract_plain_signature(UINT16 *size, TPMT_SIGNATURE *signature) {
+
+    UINT8 *buffer = NULL;
+    *size = 0;
+
+    switch (signature->sigAlg) {
+    case TPM2_ALG_RSASSA:
+        *size = sizeof(signature->signature.rsassa.sig.buffer);
+        buffer = malloc(*size);
+        if (!buffer) {
+            goto nomem;
+        }
+        memcpy(buffer, signature->signature.rsassa.sig.buffer, *size);
+        break;
+    case TPM2_ALG_HMAC: {
+        TPMU_HA *hmac_sig = &(signature->signature.hmac.digest);
+        *size = tpm2_alg_util_get_hash_size(signature->signature.hmac.hashAlg);
+        buffer = malloc(*size);
+        if (!buffer) {
+            goto nomem;
+        }
+        memcpy(buffer, hmac_sig, *size);
+        break;
+    }
+    case TPM2_ALG_ECDSA: {
+        const size_t ECC_PAR_LEN = sizeof(TPM2B_ECC_PARAMETER);
+        *size = ECC_PAR_LEN * 2;
+        buffer = malloc(*size);
+        if (!buffer) {
+            goto nomem;
+        }
+        memcpy(buffer,
+            (UINT8*)&(signature->signature.ecdsa.signatureR),
+            ECC_PAR_LEN
+        );
+        memcpy(buffer + ECC_PAR_LEN,
+            (UINT8*)&(signature->signature.ecdsa.signatureS),
+            ECC_PAR_LEN
+        );
+        break;
+    }
+    default:
+        LOG_ERR("%s: unknown signature scheme: 0x%x", __func__,
+            signature->sigAlg);
+        return NULL;
+    }
+
+    return buffer;
+nomem:
+    LOG_ERR("%s: couldn't allocate memory", __func__);
+    return NULL;
+}
+
+static bool get_key_type(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT objectHandle,
+        TPMI_ALG_PUBLIC *type) {
+
+    TSS2L_SYS_AUTH_RESPONSE sessions_data_out;
+
+    TPM2B_PUBLIC out_public = TPM2B_EMPTY_INIT;
+
+    TPM2B_NAME name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
+
+    TPM2B_NAME qaulified_name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
+
+    TSS2_RC rval = Tss2_Sys_ReadPublic(sapi_context, objectHandle, 0, &out_public, &name,
+            &qaulified_name, &sessions_data_out);
+    if (rval != TPM2_RC_SUCCESS) {
+        LOG_ERR("Sys_ReadPublic failed, error code: 0x%x", rval);
+        return false;
+    }
+    *type = out_public.publicArea.type;
+    return true;
+}
+
+bool get_signature_scheme(TSS2_SYS_CONTEXT *sapi_context,
+        TPMI_DH_OBJECT keyHandle, TPMI_ALG_HASH halg,
+        TPMT_SIG_SCHEME *scheme) {
+
+    TPM2_ALG_ID type;
+    bool result = get_key_type(sapi_context, keyHandle, &type);
+    if (!result) {
+        return false;
+    }
+
+    switch (type) {
+    case TPM2_ALG_RSA :
+        scheme->scheme = TPM2_ALG_RSASSA;
+        scheme->details.rsassa.hashAlg = halg;
+        break;
+    case TPM2_ALG_KEYEDHASH :
+        scheme->scheme = TPM2_ALG_HMAC;
+        scheme->details.hmac.hashAlg = halg;
+        break;
+    case TPM2_ALG_ECC :
+        scheme->scheme = TPM2_ALG_ECDSA;
+        scheme->details.ecdsa.hashAlg = halg;
+        break;
+    case TPM2_ALG_SYMCIPHER :
+    default:
+        LOG_ERR("Unknown key type, got: 0x%x", type);
+        return false;
+    }
+
+    return true;
+}
diff --git a/TPM2-Plugin/lib/tpm2_attr_util.c b/TPM2-Plugin/lib/tpm2_attr_util.c
new file mode 100644
index 0000000..03ce2d5
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_attr_util.c
@@ -0,0 +1,645 @@
+//**********************************************************************;
+// 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 <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sapi/tpm20.h>
+
+#include "log.h"
+#include "tpm2_attr_util.h"
+#include "tpm2_util.h"
+
+#define dispatch_no_arg_add(x) \
+    { .name = str(x), .callback=(action)x, .width = 1 }
+
+#define dispatch_arg_add(x, w) \
+    { .name = str(x), .callback=(action)x, .width = w }
+
+#define dispatch_reserved(pos) \
+    { .name = "<reserved("xstr(pos)")>", .callback=NULL, .width = 1 }
+
+typedef enum dispatch_error dispatch_error;
+enum dispatch_error {
+    dispatch_ok = 0,
+    dispatch_err,
+    dispatch_no_match,
+};
+
+typedef bool (*action)(void *obj, char *arg);
+
+typedef struct dispatch_table dispatch_table;
+struct dispatch_table {
+    char *name;
+    action callback;
+    unsigned width; /* the width of the field, CANNOT be 0 */
+};
+
+static bool authread(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_AUTHREAD;
+    return true;
+}
+
+static bool authwrite(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_AUTHWRITE;
+    return true;
+}
+
+static bool clear_stclear(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_CLEAR_STCLEAR;
+    return true;
+}
+
+static bool globallock(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_GLOBALLOCK;
+    return true;
+}
+
+static bool no_da(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_NO_DA;
+    return true;
+}
+
+static bool orderly(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_ORDERLY;
+    return true;
+}
+
+static bool ownerread(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_OWNERREAD;
+    return true;
+}
+
+static bool ownerwrite(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_OWNERWRITE;
+    return true;
+}
+
+static bool platformcreate(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_PLATFORMCREATE;
+    return true;
+}
+
+static bool policyread(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_POLICYREAD;
+    return true;
+}
+
+static bool policywrite(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_POLICYWRITE;
+    return true;
+}
+
+static bool policydelete(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_POLICY_DELETE;
+    return true;
+}
+
+static bool ppread(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_PPREAD;
+    return true;
+}
+
+static bool ppwrite(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_PPWRITE;
+    return true;
+}
+
+static bool readlocked(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_READLOCKED;
+    return true;
+}
+
+static bool read_stclear(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_READ_STCLEAR;
+    return true;
+}
+
+static bool writeall(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_WRITEALL;
+    return true;
+}
+
+static bool writedefine(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_WRITEDEFINE;
+    return true;
+}
+
+static bool writelocked(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_WRITELOCKED;
+    return true;
+}
+
+static bool write_stclear(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_WRITE_STCLEAR;
+    return true;
+}
+
+static bool written(TPMA_NV *nv, char *arg) {
+
+    UNUSED(arg);
+    *nv |= TPMA_NV_TPMA_NV_WRITTEN;
+    return true;
+}
+
+static bool nt(TPMA_NV *nv, char *arg) {
+
+    uint16_t value;
+    bool result = tpm2_util_string_to_uint16(arg, &value);
+    if (!result) {
+        LOG_ERR("Could not convert \"%s\", to a number", arg);
+        return false;
+    }
+
+    /* nt space is 4 bits, so max of 15 */
+    if (value > 0x0F) {
+        LOG_ERR("Field TPM_NT of type TPMA_NV is only 4 bits,"
+                "value \"%s\" to big!", arg);
+        return false;
+    }
+
+    *nv &= ~TPMA_NV_TPM2_NT;
+    *nv |= value << 4;
+    return true;
+}
+
+/*
+ * The order of this table must be in order with the bit defines in table 204:
+ * https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
+ *
+ * This table is in bitfield order, thus the index of a bit set in a TPMA_NV
+ * can be used to lookup the name.
+ *
+ * if not the logic in tpm2_nv_util_strtoattr would need to change!
+ */
+static dispatch_table nv_attr_table[] = { // Bit Index
+    dispatch_no_arg_add(ppwrite),         //  0
+    dispatch_no_arg_add(ownerwrite),      //  1
+    dispatch_no_arg_add(authwrite),       //  2
+    dispatch_no_arg_add(policywrite),     //  3
+    dispatch_arg_add(nt, 4),              //  4
+    dispatch_arg_add(nt, 3),              //  5
+    dispatch_arg_add(nt, 2),              //  6
+    dispatch_arg_add(nt, 1),              //  7
+    dispatch_reserved(8),                 //  8
+    dispatch_reserved(9),                 //  9
+    dispatch_no_arg_add(policydelete),    // 10
+    dispatch_no_arg_add(writelocked),     // 11
+    dispatch_no_arg_add(writeall),        // 12
+    dispatch_no_arg_add(writedefine),     // 13
+    dispatch_no_arg_add(write_stclear),   // 14
+    dispatch_no_arg_add(globallock),      // 15
+    dispatch_no_arg_add(ppread),          // 16
+    dispatch_no_arg_add(ownerread),       // 17
+    dispatch_no_arg_add(authread),        // 18
+    dispatch_no_arg_add(policyread),      // 19
+    dispatch_reserved(20),                // 20
+    dispatch_reserved(21),                // 21
+    dispatch_reserved(22),                // 22
+    dispatch_reserved(23),                // 23
+    dispatch_reserved(24),                // 24
+    dispatch_no_arg_add(no_da),           // 25
+    dispatch_no_arg_add(orderly),         // 26
+    dispatch_no_arg_add(clear_stclear),   // 27
+    dispatch_no_arg_add(readlocked),      // 28
+    dispatch_no_arg_add(written),         // 29
+    dispatch_no_arg_add(platformcreate),  // 30
+    dispatch_no_arg_add(read_stclear),    // 31
+};
+
+static bool fixedtpm(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_FIXEDTPM;
+    return true;
+}
+
+static bool stclear(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_STCLEAR;
+    return true;
+}
+
+static bool fixedparent(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_FIXEDPARENT;
+    return true;
+}
+
+static bool sensitivedataorigin(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_SENSITIVEDATAORIGIN;
+    return true;
+}
+
+static bool userwithauth(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_USERWITHAUTH;
+    return true;
+}
+
+static bool adminwithpolicy(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_ADMINWITHPOLICY;
+    return true;
+}
+
+static bool noda(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_NODA;
+    return true;
+}
+
+static bool encryptedduplication(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_ENCRYPTEDDUPLICATION;
+    return true;
+}
+
+static bool restricted(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_RESTRICTED;
+    return true;
+}
+
+static bool decrypt(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_DECRYPT;
+    return true;
+}
+
+static bool sign(TPMA_OBJECT *obj, char *arg) {
+
+    UNUSED(arg);
+    *obj |= TPMA_OBJECT_SIGN;
+    return true;
+}
+
+static dispatch_table obj_attr_table[] = {         // Bit Index
+        dispatch_reserved(0),                      //  0
+        dispatch_no_arg_add(fixedtpm),             //  1
+        dispatch_no_arg_add(stclear),              //  2
+        dispatch_reserved(3),                      //  3
+        dispatch_no_arg_add(fixedparent),          //  4
+        dispatch_no_arg_add(sensitivedataorigin),  //  5
+        dispatch_no_arg_add(userwithauth),         //  6
+        dispatch_no_arg_add(adminwithpolicy),      //  7
+        dispatch_reserved(8),                      //  8
+        dispatch_reserved(9),                      //  9
+        dispatch_no_arg_add(noda),                 // 10
+        dispatch_no_arg_add(encryptedduplication), // 11
+        dispatch_reserved(12),                     // 12
+        dispatch_reserved(13),                     // 13
+        dispatch_reserved(14),                     // 14
+        dispatch_reserved(15),                     // 15
+        dispatch_no_arg_add(restricted),           // 16
+        dispatch_no_arg_add(decrypt),              // 17
+        dispatch_no_arg_add(sign),                 // 18
+        dispatch_reserved(19),                     // 19
+        dispatch_reserved(20),                     // 20
+        dispatch_reserved(21),                     // 21
+        dispatch_reserved(22),                     // 22
+        dispatch_reserved(23),                     // 23
+        dispatch_reserved(24),                     // 24
+        dispatch_reserved(25),                     // 25
+        dispatch_reserved(26),                     // 26
+        dispatch_reserved(27),                     // 27
+        dispatch_reserved(28),                     // 28
+        dispatch_reserved(29),                     // 29
+        dispatch_reserved(30),                     // 30
+        dispatch_reserved(31),                     // 31
+};
+
+static bool token_match(const char *name, const char *token, bool has_arg, char **sep) {
+
+    /* if it has an argument, we expect a separator */
+    size_t match_len = strlen(token);
+    if (has_arg) {
+        *sep = strchr(token, '=');
+        if (*sep) {
+            match_len = *sep - token;
+        }
+    }
+
+    return !strncmp(name, token, match_len);
+}
+
+static dispatch_error handle_dispatch(dispatch_table *d, char *token,
+        TPMA_NV *nvattrs) {
+
+    char *name = d->name;
+    action cb = d->callback;
+    bool has_arg = d->width > 1;
+
+    /* if no callback, then its a reserved block, just skip it */
+    if (!cb) {
+        return dispatch_no_match;
+    }
+
+    char *sep = NULL;
+    bool match = token_match(name, token, has_arg, &sep);
+    if (!match) {
+        return dispatch_no_match;
+    }
+
+    /*
+     * If it has an argument, match should have found the seperator.
+     */
+    char *arg = NULL;
+    if (has_arg) {
+        if (!sep) {
+            LOG_ERR("Expected argument for \"%s\", got none.", token);
+            return dispatch_err;
+        }
+
+        /* split token on = */
+        *sep = '\0';
+        sep++;
+        if (!*sep) {
+            LOG_ERR("Expected argument for \"%s\", got none.", token);
+            return dispatch_err;
+        }
+
+        /* valid argument string, assign */
+        arg = sep;
+    }
+
+    bool result = cb(nvattrs, arg);
+    return result ? dispatch_ok : dispatch_err;
+}
+
+static bool common_strtoattr(char *attribute_list, void *attrs, dispatch_table *table, size_t size) {
+
+    char *token;
+    char *save;
+
+    /*
+     * This check is soley to prevent GCC from complaining on:
+     * error: ‘attribute_list’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
+     * Might as well check nvattrs as well.
+     */
+    if (!attribute_list || !attrs) {
+        LOG_ERR("attribute list or attributes structure is NULL");
+        return false;
+    }
+
+    while ((token = strtok_r(attribute_list, "|", &save))) {
+        attribute_list = NULL;
+
+        bool did_dispatch = false;
+
+        size_t i;
+        for (i = 0; i < size; i++) {
+            dispatch_table *d = &table[i];
+
+            dispatch_error err = handle_dispatch(d, token, attrs);
+            if (err == dispatch_ok) {
+                did_dispatch = true;
+                break;
+            } else if (err == dispatch_err) {
+                return false;
+            }
+            /* dispatch_no_match --> keep looking */
+        }
+
+        /* did we dispatch?, If not log error and return */
+        if (!did_dispatch) {
+            char *tmp = strchr(token, '=');
+            if (tmp) {
+                *tmp = '\0';
+            }
+            LOG_ERR("Unknown token: \"%s\" found.", token);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool tpm2_attr_util_nv_strtoattr(char *attribute_list, TPMA_NV *nvattrs) {
+
+    return common_strtoattr(attribute_list, nvattrs, nv_attr_table, ARRAY_LEN(nv_attr_table));
+}
+
+bool tpm2_attr_util_obj_strtoattr(char *attribute_list, TPMA_OBJECT *objattrs) {
+
+    return common_strtoattr(attribute_list, objattrs, obj_attr_table, ARRAY_LEN(obj_attr_table));
+}
+
+
+static UINT8 find_first_set(UINT32 bits) {
+
+    UINT8 n = 0;
+
+    if (!bits) {
+        return n;
+    }
+
+    if (!(bits & 0x0000FFFF)) { n += 16; bits >>= 16; }
+    if (!(bits & 0x000000FF)) { n +=  8; bits >>=  8; }
+    if (!(bits & 0x0000000F)) { n +=  4; bits >>=  4; }
+    if (!(bits & 0x00000003)) { n +=  2; bits >>=  2; }
+    if (!(bits & 0x00000001))   n +=  1;
+
+    return n;
+}
+
+static char *tpm2_attr_util_common_attrtostr(UINT32 attrs, dispatch_table *table, size_t size) {
+
+    if (attrs == 0) {
+        return strdup("<none>");
+    }
+
+    /*
+     * Get how many bits are set in the attributes and then find the longest
+     * "name".
+     *
+     * pop_cnt * max_name_len + pop_cnt - 1 (for the | separators) + 4
+     * (for nv field equals in hex) + 1 for null byte.
+     *
+     * This will provide us an ample buffer size for generating the string
+     * in without having to constantly realloc.
+     */
+    UINT32 pop_cnt = tpm2_util_pop_count(attrs);
+
+    size_t i;
+    size_t max_name_len = 0;
+    for (i=0; i < size; i++) {
+        dispatch_table *d = &table[i];
+        size_t name_len = strlen(d->name);
+        max_name_len = name_len > max_name_len ? name_len : max_name_len;
+    }
+
+    size_t length = pop_cnt * max_name_len + pop_cnt - 1 + 3;
+
+    char *str = calloc(length, 1);
+    if (!str) {
+        return NULL;
+    }
+
+
+    size_t string_index = 0;
+
+    /*
+     * Start at the lowest, first bit set, index into the array,
+     * grab the data needed, and move on.
+     */
+    while (attrs) {
+        UINT8 bit_index = find_first_set(attrs);
+
+        dispatch_table *d = &table[bit_index];
+
+        const char *name = d->name;
+        unsigned w = d->width;
+
+        /* current position and size left of the string */
+        char *s = &str[string_index];
+        size_t left = length - string_index;
+
+        /* this is a mask that is field width wide */
+        UINT8 mask = ((UINT32)1 << w) - 1;
+
+        /* get the value in the field before clearing attrs out */
+        UINT8 field_values = (attrs & mask << bit_index) >> bit_index;
+
+        /*
+         * turn off the parsed bit(s) index, using width to turn off everything in a
+         * field
+         */
+        attrs &= ~(mask << bit_index);
+
+        /*
+         * if the callback is NULL, we are either in a field middle or reserved
+         * section which is weird, just add the name in. In the case of being
+         * in the middle of the field, we will add a bunch of errors to the string,
+         * but it would be better to attempt to show all the data in string form,
+         * rather than bail.
+         *
+         * Fields are either 1 or > 1.
+         */
+        if (w == 1) {
+            /*
+             * set the format to a middle output, unless we're parsing
+             * the first or last. Let the format be static with the routine
+             * so the compiler can do printf style format specifier checking.
+             */
+            if (!string_index) {
+                /* on the first write, if we are already done, no pipes */
+                string_index += !attrs ? snprintf(s, left, "%s", name) :
+                        snprintf(s, left, "%s|", name);
+            } else if (!attrs) {
+                string_index += snprintf(s, left, "%s", name);
+            } else {
+                string_index += snprintf(s, left, "%s|", name);
+            }
+        } else {
+            /* deal with the field */
+            if (!string_index) {
+                /* on the first write, if we are already done, no pipes */
+                string_index += !attrs ? snprintf(s, left, "%s=0x%X", name, field_values) :
+                        snprintf(s, left, "%s=0x%X|", name, field_values);
+            } else if (!attrs) {
+                string_index += snprintf(s, left, "%s=0x%X", name, field_values);
+            } else {
+                string_index += snprintf(s, left, "%s=0x%X|", name, field_values);
+            }
+        }
+    }
+
+    return str;
+}
+
+char *tpm2_attr_util_nv_attrtostr(TPMA_NV nvattrs) {
+    return tpm2_attr_util_common_attrtostr(nvattrs, nv_attr_table, ARRAY_LEN(nv_attr_table));
+}
+
+char *tpm2_attr_util_obj_attrtostr(TPMA_OBJECT objattrs) {
+    return tpm2_attr_util_common_attrtostr(objattrs, obj_attr_table, ARRAY_LEN(obj_attr_table));
+}
+
+bool tpm2_attr_util_obj_from_optarg(char *argvalue, TPMA_OBJECT *objattrs) {
+
+    bool res = tpm2_util_string_to_uint32(argvalue, objattrs);
+    if (!res) {
+        res = tpm2_attr_util_obj_strtoattr(argvalue, objattrs);
+    }
+
+    return res;
+}
diff --git a/TPM2-Plugin/lib/tpm2_error.c b/TPM2-Plugin/lib/tpm2_error.c
new file mode 100644
index 0000000..7bc024d
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_error.c
@@ -0,0 +1,870 @@
+//**********************************************************************;
+// Copyright (c) 2018, 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 <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <sapi/tpm20.h>
+
+#include "tpm2_error.h"
+#include "tpm2_util.h"
+
+/**
+ * The maximum size of a layer name.
+ */
+#define TSS2_ERR_LAYER_NAME_MAX  4
+
+/**
+ * The maximum size for layer specific error strings.
+ */
+#define TSS2_ERR_LAYER_ERROR_STR_MAX  512
+
+/**
+ * Concatenates (safely) onto a static buffer given a format and varaidic
+ * arguments similar to sprintf.
+ * @param b
+ *   The static buffer to concatenate onto.
+ * @param fmt
+ *   The format specifier as understood by printf followed by the variadic
+ *   parameters for the specifier.
+ */
+#define catbuf(b, fmt, ...) _catbuf(b, sizeof(b), fmt, ##__VA_ARGS__)
+
+/**
+ * Clears out a static buffer by setting index 0 to the null byte.
+ * @param buffer
+ *  The buffer to clear out.
+ */
+static void clearbuf(char *buffer) {
+    buffer[0] = '\0';
+}
+
+/**
+ * Prints to a buffer using snprintf(3) using the supplied fmt
+ * and varaiadic arguments.
+ * @param buf
+ *  The buffer to print into.
+ * @param len
+ *  The length of that buffer.
+ * @param fmt
+ *  The format string
+ * @warning
+ *  DO NOT CALL DIRECTLY, use the catbuf() macro.
+ */
+static void COMPILER_ATTR(format (printf, 3, 4))
+_catbuf(char *buf, size_t len, const char *fmt, ...) {
+    va_list argptr;
+    va_start(argptr, fmt);
+    size_t offset = strlen(buf);
+    vsnprintf(&buf[offset], len - offset, fmt, argptr);
+    va_end(argptr);
+}
+
+/**
+ * Retrieves the layer number. The layer number is in the 3rd
+ * octet and is thus 1 byte big.
+ *
+ * @param rc
+ *  The rc to query for the layer number.
+ * @return
+ *  The layer number.
+ */
+static inline UINT8 tss2_rc_layer_number_get(TSS2_RC rc) {
+    return ((rc & TSS2_RC_LAYER_MASK) >> TSS2_RC_LAYER_SHIFT);
+}
+
+/**
+ * Queries a TPM format 1 error codes N field. The N field
+ * is a 4 bit field located at bits 8:12.
+ * @param rc
+ *  The rc to query the N field for.
+ * @return
+ *  The N field value.
+ */
+static inline UINT8 tpm2_rc_fmt1_N_get(TPM2_RC rc) {
+    return ((rc & (0xF << 8)) >> 8);
+}
+
+/**
+ * Queries the index bits out of the N field contained in a TPM format 1
+ * error code. The index bits are the low 3 bits of the N field.
+ * @param rc
+ *  The TPM format 1 error code to query for the index bits.
+ * @return
+ *  The index bits from the N field.
+ */
+static inline UINT8 tpm2_rc_fmt1_N_index_get(TPM2_RC rc) {
+    return (tpm2_rc_fmt1_N_get(rc) & 0x7);
+}
+
+/**
+ * Determines if the N field in a TPM format 1 error code is
+ * a handle or not.
+ * @param rc
+ *  The TPM format 1 error code to query.
+ * @return
+ *  True if it is a handle, false otherwise.
+ */
+static inline bool tpm2_rc_fmt1_N_is_handle(TPM2_RC rc) {
+    return ((tpm2_rc_fmt1_N_get(rc) & 0x8) == 0);
+}
+
+static inline UINT8 tpm2_rc_fmt1_P_get(TPM2_RC rc) {
+    return ((rc & (1 << 6)) >> 6);
+}
+
+static inline UINT16 tpm2_rc_fmt1_error_get(TPM2_RC rc) {
+    return (rc & 0x3F);
+}
+
+static inline UINT16 tpm2_rc_fmt0_error_get(TPM2_RC rc) {
+    return (rc & 0x7F);
+}
+
+static inline UINT8 tpm2_rc_tpm_fmt0_V_get(TPM2_RC rc) {
+    return ((rc & (1 << 8)) >> 8);
+}
+
+static inline UINT8 tpm2_rc_fmt0_T_get(TPM2_RC rc) {
+    return ((rc & (1 << 10)) >> 8);
+}
+
+static inline UINT8 tpm2_rc_fmt0_S_get(TSS2_RC rc) {
+    return ((rc & (1 << 11)) >> 8);
+}
+
+/**
+ * Helper macro for adding a layer handler to the layer
+ * registration array.
+ */
+#define ADD_HANDLER(name, handler) \
+    { name, handler }
+
+/**
+ * Same as ADD_HANDLER but sets it to NULL. Used as a placeholder
+ * for non-registered indexes into the handler array.
+ */
+#define ADD_NULL_HANDLER ADD_HANDLER(NULL, NULL)
+
+static const char *tpm2_err_handler_fmt1(TPM2_RC rc) {
+
+    /*
+     * format 1 error codes start at 1, so
+     * add a NULL entry to index 0.
+     */
+    static const char *fmt1_err_strs[] = {
+        // 0x0 - EMPTY
+        NULL,
+        // 0x1 - TPM2_RC_ASYMMETRIC
+        "asymmetric algorithm not supported or not correct",
+        // 0x2 - TPM2_RC_ATTRIBUTES
+        "inconsistent attributes",
+        // 0x3 - TPM2_RC_HASH
+        "hash algorithm not supported or not appropriate",
+        // 0x4 - TPM2_RC_VALUE
+        "value is out of range or is not correct for the context",
+        // 0x5 - TPM2_RC_HIERARCHY
+        "hierarchy is not enabled or is not correct for the use",
+        // 0x6 - EMPTY
+        NULL,
+        // 0x7 - TPM2_RC_KEY_SIZE
+        "key size is not supported",
+        // 0x8 - TPM2_RC_MGF
+        "mask generation function not supported",
+        // 0x9 - TPM2_RC_MODE
+        "mode of operation not supported",
+        // 0xA - TPM2_RC_TYPE
+        "the type of the value is not appropriate for the use",
+        // 0xB - TPM2_RC_HANDLE
+        "the handle is not correct for the use",
+        // 0xC - TPM2_RC_KDF
+        "unsupported key derivation function or function not appropriate for "
+        "use",
+        // 0xD - TPM2_RC_RANGE
+        "value was out of allowed range",
+        // 0xE - TPM2_RC_AUTH_FAIL
+        "the authorization HMAC check failed and DA counter incremented",
+        // 0xF - TPM2_RC_NONCE
+        "invalid nonce size or nonce value mismatch",
+        // 0x10 - TPM2_RC_PP
+        "authorization requires assertion of PP",
+        // 0x11 - EMPTY
+        NULL,
+        // 0x12 - TPM2_RC_SCHEME
+        "unsupported or incompatible scheme",
+        // 0x13 - EMPTY
+        NULL,
+        // 0x14 - EMPTY
+        NULL,
+        // 0x15 - TPM2_RC_SIZE
+        "structure is the wrong size",
+        // 0x16 - TPM2_RC_SYMMETRIC
+        "unsupported symmetric algorithm or key size, or not appropriate for"
+        " instance",
+        // 0x17 - TPM2_RC_TAG
+        "incorrect structure tag",
+        // 0x18 - TPM2_RC_SELECTOR
+        "union selector is incorrect",
+        // 0x19 - EMPTY
+        NULL,
+        // 0x1A - TPM2_RC_INSUFFICIENT
+        "the TPM was unable to unmarshal a value because there were not enough"
+        " octets in the input buffer",
+        // 0x1B - TPM2_RC_SIGNATURE
+        "the signature is not valid",
+        // 0x1C - TPM2_RC_KEY
+        "key fields are not compatible with the selected use",
+        // 0x1D - TPM2_RC_POLICY_FAIL
+        "a policy check failed",
+        // 0x1E - EMPTY
+        NULL,
+        // 0x1F - TPM2_RC_INTEGRITY
+        "integrity check failed",
+        // 0x20 - TPM2_RC_TICKET
+        "invalid ticket",
+        // 0x21 - TPM2_RC_RESERVED_BITS
+        "reserved bits not set to zero as required",
+        // 0x22 - TPM2_RC_BAD_AUTH
+        "authorization failure without DA implications",
+        // 0x23 - TPM2_RC_EXPIRED
+        "the policy has expired",
+        // 0x24 - TPM2_RC_POLICY_CC
+        "the commandCode in the policy is not the commandCode of the command"
+        " or the command code in a policy command references a command that"
+        " is not implemented",
+        // 0x25 - TPM2_RC_BINDING
+        "public and sensitive portions of an object are not cryptographically bound",
+        // 0x26 - TPM2_RC_CURVE
+        "curve not supported",
+        // 0x27 - TPM2_RC_ECC_POINT
+        "point is not on the required curve",
+    };
+
+    static char buf[TSS2_ERR_LAYER_ERROR_STR_MAX + 1];
+
+    clearbuf(buf);
+
+    /* Print whether or not the error is caused by a bad
+     * handle or parameter. On the case of a Handle (P == 0)
+     * then the N field top bit will be set. Un-set this bit
+     * to get the handle index by subtracting 8 as N is a 4
+     * bit field.
+     *
+     * the lower 3 bits of N indicate index, and the high bit
+     * indicates
+     */
+    UINT8 index = tpm2_rc_fmt1_N_index_get(rc);
+
+    bool is_handle = tpm2_rc_fmt1_N_is_handle(rc);
+    const char *m = tpm2_rc_fmt1_P_get(rc) ? "parameter" :
+                    is_handle ? "handle" : "session";
+    catbuf(buf, "%s", m);
+
+    if (index) {
+        catbuf(buf, "(%u):", index);
+    } else {
+        catbuf(buf, "%s", "(unk):");
+    }
+
+    UINT8 errnum = tpm2_rc_fmt1_error_get(rc);
+    if (errnum < ARRAY_LEN(fmt1_err_strs)) {
+        m = fmt1_err_strs[errnum];
+        catbuf(buf, "%s", m);
+    } else {
+        catbuf(buf, "unknown error num: 0x%X", errnum);
+    }
+
+    return buf;
+}
+
+static const char *tpm2_err_handler_fmt0(TSS2_RC rc) {
+
+    /*
+     * format 0 error codes start at 1, so
+     * add a NULL entry to index 0.
+     * Thus, no need to offset the error bits
+     * and fmt0 and fmt1 arrays can be used
+     * in-place of each other for lookups.
+     */
+    static const char *fmt0_warn_strs[] = {
+            // 0x0 - EMPTY
+            NULL,
+            // 0x1 - TPM2_RC_CONTEXT_GAP
+            "gap for context ID is too large",
+            // 0x2 - TPM2_RC_OBJECT_MEMORY
+            "out of memory for object contexts",
+            // 0x3 - TPM2_RC_SESSION_MEMORY
+            "out of memory for session contexts",
+            // 0x4 - TPM2_RC_MEMORY
+            "out of shared object/session memory or need space for internal"
+            " operations",
+            // 0x5 - TPM2_RC_SESSION_HANDLES
+            "out of session handles",
+            // 0x6 - TPM2_RC_OBJECT_HANDLES
+            "out of object handles",
+            // 0x7 - TPM2_RC_LOCALITY
+            "bad locality",
+            // 0x8 - TPM2_RC_YIELDED
+            "the TPM has suspended operation on the command; forward progress"
+            " was made and the command may be retried",
+            // 0x9 - TPM2_RC_CANCELED
+            "the command was canceled",
+            // 0xA - TPM2_RC_TESTING
+            "TPM is performing self-tests",
+            // 0xB - EMPTY
+            NULL,
+            // 0xC - EMPTY
+            NULL,
+            // 0xD - EMPTY
+            NULL,
+            // 0xE - EMPTY
+            NULL,
+            // 0xF - EMPTY
+            NULL,
+            // 0x10 - TPM2_RC_REFERENCE_H0
+            "the 1st handle in the handle area references a transient object"
+            " or session that is not loaded",
+            // 0x11 - TPM2_RC_REFERENCE_H1
+            "the 2nd handle in the handle area references a transient object"
+            " or session that is not loaded",
+            // 0x12 - TPM2_RC_REFERENCE_H2
+            "the 3rd handle in the handle area references a transient object"
+            " or session that is not loaded",
+            // 0x13 - TPM2_RC_REFERENCE_H3
+            "the 4th handle in the handle area references a transient object"
+            " or session that is not loaded",
+            // 0x14 - TPM2_RC_REFERENCE_H4
+            "the 5th handle in the handle area references a transient object"
+            " or session that is not loaded",
+            // 0x15 - TPM2_RC_REFERENCE_H5
+            "the 6th handle in the handle area references a transient object"
+            " or session that is not loaded",
+            // 0x16 - TPM2_RC_REFERENCE_H6
+            "the 7th handle in the handle area references a transient object"
+            " or session that is not loaded",
+            // 0x17 - EMPTY,
+            // 0x18 - TPM2_RC_REFERENCE_S0
+            "the 1st authorization session handle references a session that"
+            " is not loaded",
+            // 0x19 - TPM2_RC_REFERENCE_S1
+            "the 2nd authorization session handle references a session that"
+            " is not loaded",
+            // 0x1A - TPM2_RC_REFERENCE_S2
+            "the 3rd authorization session handle references a session that"
+            " is not loaded",
+            // 0x1B - TPM2_RC_REFERENCE_S3
+            "the 4th authorization session handle references a session that"
+            " is not loaded",
+            // 0x1C - TPM2_RC_REFERENCE_S4
+            "the 5th authorization session handle references a session that"
+            " is not loaded",
+            // 0x1D - TPM2_RC_REFERENCE_S5
+            "the 6th authorization session handle references a session that"
+            " is not loaded",
+            // 0x1E - TPM2_RC_REFERENCE_S6
+            "the 7th authorization session handle references a session that"
+            " is not loaded",
+            // 0x20 -TPM2_RC_NV_RATE
+            "the TPM is rate-limiting accesses to prevent wearout of NV",
+            // 0x21 - TPM2_RC_LOCKOUT
+            "authorizations for objects subject to DA protection are not"
+            " allowed at this time because the TPM is in DA lockout mode",
+            // 0x22 - TPM2_RC_RETRY
+            "the TPM was not able to start the command",
+            // 0x23 - TPM2_RC_NV_UNAVAILABLE
+            "the command may require writing of NV and NV is not current"
+            " accessible",
+    };
+
+    /*
+     * format 1 error codes start at 0, so
+     * no need to offset the error bits.
+     */
+    static const char *fmt0_err_strs[] = {
+        // 0x0 - TPM2_RC_INITIALIZE
+        "TPM not initialized by TPM2_Startup or already initialized",
+        // 0x1 - TPM2_RC_FAILURE
+        "commands not being accepted because of a TPM failure",
+        // 0x2 - EMPTY
+        NULL,
+        // 0x3 - TPM2_RC_SEQUENCE
+        "improper use of a sequence handle",
+        // 0x4 - EMPTY
+        NULL,
+        // 0x5 - EMPTY
+        NULL,
+        // 0x6 - EMPTY
+        NULL,
+        // 0x7 - EMPTY
+        NULL,
+        // 0x8 - EMPTY
+        NULL,
+        // 0x9 - EMPTY
+        NULL,
+        // 0xA - EMPTY
+        NULL,
+        // 0xB - TPM2_RC_PRIVATE
+        "not currently used",
+        // 0xC - EMPTY
+        NULL,
+        // 0xD - EMPTY
+        NULL,
+        // 0xE - EMPTY
+        NULL,
+        // 0xF - EMPTY
+        NULL,
+        // 0x10 - EMPTY
+        NULL,
+        // 0x11 - EMPTY
+        NULL,
+        // 0x12 - EMPTY
+        NULL,
+        // 0x13 - EMPTY
+        NULL,
+        // 0x14 - EMPTY
+        NULL,
+        // 0x15 - EMPTY
+        NULL,
+        // 0x16 - EMPTY
+        NULL,
+        // 0x17 - EMPTY
+        NULL,
+        // 0x18 - EMPTY
+        NULL,
+        // 0x19 - TPM2_RC_HMAC
+        "not currently used",
+        // 0x1A - EMPTY
+        NULL,
+        // 0x1B - EMPTY
+        NULL,
+        // 0x1C - EMPTY
+        NULL,
+        // 0x1D - EMPTY
+        NULL,
+        // 0x1E - EMPTY
+        NULL,
+        // 0x1F - EMPTY
+        NULL,
+        // 0x20 - TPM2_RC_DISABLED
+        "the command is disabled",
+        // 0x21 - TPM2_RC_EXCLUSIVE
+        "command failed because audit sequence required exclusivity",
+        // 0x22 - EMPTY
+        NULL,
+        // 0x23 - EMPTY,
+        NULL,
+        // 0x24 - TPM2_RC_AUTH_TYPE
+        "authorization handle is not correct for command",
+        // 0x25 - TPM2_RC_AUTH_MISSING
+        "command requires an authorization session for handle and it is"
+        " not present",
+        // 0x26 - TPM2_RC_POLICY
+        "policy failure in math operation or an invalid authPolicy value",
+        // 0x27 - TPM2_RC_PCR
+        "PCR check fail",
+        // 0x28 - TPM2_RC_PCR_CHANGED
+        "PCR have changed since checked",
+        // 0x29 - EMPTY
+        NULL,
+        // 0x2A - EMPTY
+        NULL,
+        // 0x2B - EMPTY
+        NULL,
+        // 0x2C - EMPTY
+        NULL,
+        // 0x2D - TPM2_RC_UPGRADE
+        "TPM is in field upgrade mode unless called via"
+        " TPM2_FieldUpgradeData(), then it is not in field upgrade mode",
+        // 0x2E - TPM2_RC_TOO_MANY_CONTEXTS
+        "context ID counter is at maximum",
+        // 0x2F - TPM2_RC_AUTH_UNAVAILABLE
+        "authValue or authPolicy is not available for selected entity",
+        // 0x30 - TPM2_RC_REBOOT
+        "a _TPM_Init and Startup(CLEAR) is required before the TPM can"
+        " resume operation",
+        // 0x31 - TPM2_RC_UNBALANCED
+        "the protection algorithms (hash and symmetric) are not reasonably"
+        " balanced. The digest size of the hash must be larger than the key"
+        " size of the symmetric algorithm.",
+        // 0x32 - EMPTY
+        NULL,
+        // 0x33 - EMPTY
+        NULL,
+        // 0x34 - EMPTY
+        NULL,
+        // 0x35 - EMPTY
+        NULL,
+        // 0x36 - EMPTY
+        NULL,
+        // 0x37 - EMPTY
+        NULL,
+        // 0x38 - EMPTY
+        NULL,
+        // 0x39 - EMPTY
+        NULL,
+        // 0x3A - EMPTY
+        NULL,
+        // 0x3B - EMPTY
+        NULL,
+        // 0x3C - EMPTY
+        NULL,
+        // 0x3D - EMPTY
+        NULL,
+        // 0x3E - EMPTY
+        NULL,
+        // 0x3F - EMPTY
+        NULL,
+        // 0x40 - EMPTY
+        NULL,
+        // 0x41 - EMPTY
+        NULL,
+        // 0x42 - TPM2_RC_COMMAND_SIZE
+        "command commandSize value is inconsistent with contents of the"
+        " command buffer; either the size is not the same as the octets"
+        " loaded by the hardware interface layer or the value is not large"
+        " enough to hold a command header",
+        // 0x43 - TPM2_RC_COMMAND_CODE
+        "command code not supported",
+        // 0x44 - TPM2_RC_AUTHSIZE
+        "the value of authorizationSize is out of range or the number of"
+        " octets in the Authorization Area is greater than required",
+        // 0x45 - TPM2_RC_AUTH_CONTEXT
+        "use of an authorization session with a context command or another"
+        " command that cannot have an authorization session",
+        // 0x46 - TPM2_RC_NV_RANGE
+        "NV offset+size is out of range",
+        // 0x47 - TPM2_RC_NV_SIZE
+        "Requested allocation size is larger than allowed",
+        // 0x48 - TPM2_RC_NV_LOCKED
+        "NV access locked",
+        // 0x49 - TPM2_RC_NV_AUTHORIZATION
+        "NV access authorization fails in command actions",
+        // 0x4A - TPM2_RC_NV_UNINITIALIZED
+        "an NV Index is used before being initialized or the state saved"
+        " by TPM2_Shutdown(STATE) could not be restored",
+        // 0x4B - TPM2_RC_NV_SPACE
+        "insufficient space for NV allocation",
+        // 0x4C - TPM2_RC_NV_DEFINED
+        "NV Index or persistent object already defined",
+        // 0x4D - EMPTY
+        NULL,
+        // 0x4E - EMPTY
+        NULL,
+        // 0x4F - EMPTY
+        NULL,
+        // 0x50 - TPM2_RC_BAD_CONTEXT
+        "context in TPM2_ContextLoad() is not valid",
+        // 0x51 - TPM2_RC_CPHASH
+        "cpHash value already set or not correct for use",
+        // 0x52 - TPM2_RC_PARENT
+        "handle for parent is not a valid parent",
+        // 0x53 - TPM2_RC_NEEDS_TEST
+        "some function needs testing",
+        // 0x54 - TPM2_RC_NO_RESULT
+        "returned when an internal function cannot process a request due to"
+        " an unspecified problem. This code is usually related to invalid"
+        " parameters that are not properly filtered by the input"
+        " unmarshaling code",
+        // 0x55 - TPM2_RC_SENSITIVE
+        "the sensitive area did not unmarshal correctly after decryption",
+    };
+
+    static char buf[TSS2_ERR_LAYER_ERROR_STR_MAX + 1];
+
+    clearbuf(buf);
+
+    char *e = tpm2_rc_fmt0_S_get(rc) ? "warn" : "error";
+    char *v = tpm2_rc_tpm_fmt0_V_get(rc) ? "2.0" : "1.2";
+    catbuf(buf, "%s(%s): ", e, v);
+
+    UINT8 errnum = tpm2_rc_fmt0_error_get(rc);
+    /* We only have version 2.0 spec codes defined */
+    if (tpm2_rc_tpm_fmt0_V_get(rc)) {
+        /* TCG specific error code */
+        if (tpm2_rc_fmt0_T_get(rc)) {
+            catbuf(buf, "Vendor specific error: 0x%X", errnum);
+            return buf;
+        }
+
+        /* is it a warning (version 2 error string) or is it a 1.2 error? */
+        size_t len =
+                tpm2_rc_fmt0_S_get(rc) ?
+                        ARRAY_LEN(fmt0_warn_strs) : ARRAY_LEN(fmt0_err_strs);
+        const char **selection =
+                tpm2_rc_fmt0_S_get(rc) ? fmt0_warn_strs : fmt0_err_strs;
+        if (errnum >= len) {
+            return NULL;
+        }
+
+        const char *m = selection[errnum];
+        if (!m) {
+            return NULL;
+        }
+
+        catbuf(buf, "%s", m);
+        return buf;
+    }
+
+    catbuf(buf, "%s", "unknown version 1.2 error code");
+
+    return buf;
+}
+
+/**
+ * Retrieves the layer field from a TSS2_RC code.
+ * @param rc
+ *  The rc to query the layer index of.
+ * @return
+ *  The layer index.
+ */
+static inline UINT8 tss2_rc_layer_format_get(TSS2_RC rc) {
+
+    return ((rc & (1 << 7)) >> 7);
+}
+
+/**
+ * Handler for tpm2 error codes. ie codes
+ * coming from the tpm layer aka layer 0.
+ * @param rc
+ *  The rc to decode.
+ * @return
+ *  An error string.
+ */
+static const char *tpm2_ehandler(TSS2_RC rc) {
+
+    bool is_fmt_1 = tss2_rc_layer_format_get(rc);
+
+    return is_fmt_1 ? tpm2_err_handler_fmt1(rc) : tpm2_err_handler_fmt0(rc);
+}
+
+/**
+ * The default system code handler. This handles codes
+ * from the RM (itself and simlated tpm responses), the marshaling
+ * library (mu), and the tcti layers.
+ * @param rc
+ *  The rc to decode.
+ * @return
+ *  An error string.
+ */
+static const char *sys_err_handler (TSS2_RC rc) {
+    UNUSED(rc);
+
+    /*
+     * subtract 1 from the error number
+     * before indexing into this array.
+     *
+     * Commented offsets are for the corresponding
+     * error number *before* subtraction. Ie error
+     * number 4 is at array index 3.
+     */
+    static const char *errors[] =   {
+        // 1 - TSS2_BASE_RC_GENERAL_FAILURE
+        "Catch all for all errors not otherwise specified",
+        // 2 - TSS2_BASE_RC_NOT_IMPLEMENTED
+        "If called functionality isn't implemented",
+        // 3 - TSS2_BASE_RC_BAD_CONTEXT
+        "A context structure is bad",
+        // 4 - TSS2_BASE_RC_ABI_MISMATCH
+        "Passed in ABI version doesn't match called module's ABI version",
+        // 5 - TSS2_BASE_RC_BAD_REFERENCE
+        "A pointer is NULL that isn't allowed to be NULL.",
+        // 6 - TSS2_BASE_RC_INSUFFICIENT_BUFFER
+        "A buffer isn't large enough",
+        // 7 - TSS2_BASE_RC_BAD_SEQUENCE
+        "Function called in the wrong order",
+        // 8 - TSS2_BASE_RC_NO_CONNECTION
+        "Fails to connect to next lower layer",
+        // 9 - TSS2_BASE_RC_TRY_AGAIN
+        "Operation timed out; function must be called again to be completed",
+        // 10 - TSS2_BASE_RC_IO_ERROR
+        "IO failure",
+        // 11 - TSS2_BASE_RC_BAD_VALUE
+        "A parameter has a bad value",
+        // 12 - TSS2_BASE_RC_NOT_PERMITTED
+        "Operation not permitted.",
+        // 13 - TSS2_BASE_RC_INVALID_SESSIONS
+        "Session structures were sent, but command doesn't use them or doesn't"
+        " use the specified number of them",
+        // 14 - TSS2_BASE_RC_NO_DECRYPT_PARAM
+        "If function called that uses decrypt parameter, but command doesn't"
+        " support decrypt parameter.",
+        // 15 - TSS2_BASE_RC_NO_ENCRYPT_PARAM
+        "If function called that uses encrypt parameter, but command doesn't"
+        " support decrypt parameter.",
+        // 16 - TSS2_BASE_RC_BAD_SIZE
+        "If size of a parameter is incorrect",
+        // 17 - TSS2_BASE_RC_MALFORMED_RESPONSE
+        "Response is malformed",
+        // 18 - TSS2_BASE_RC_INSUFFICIENT_CONTEXT
+        "Context not large enough",
+        // 19 - TSS2_BASE_RC_INSUFFICIENT_RESPONSE
+        "Response is not long enough",
+        // 20 - TSS2_BASE_RC_INCOMPATIBLE_TCTI
+        "Unknown or unusable TCTI version",
+        // 21 - TSS2_BASE_RC_NOT_SUPPORTED
+        "Functionality not supported",
+        // 22 - TSS2_BASE_RC_BAD_TCTI_STRUCTURE
+        "TCTI context is bad"
+  };
+
+    return (rc - 1u < ARRAY_LEN(errors)) ? errors[rc - 1u] : NULL;
+}
+
+
+static struct {
+    const char *name;
+    tpm2_error_handler handler;
+} layer_handler[TPM2_ERROR_TSS2_RC_LAYER_COUNT] = {
+    ADD_HANDLER("tpm" , tpm2_ehandler),
+    ADD_NULL_HANDLER,                       // layer 1  is unused
+    ADD_NULL_HANDLER,                       // layer 2  is unused
+    ADD_NULL_HANDLER,                       // layer 3  is unused
+    ADD_NULL_HANDLER,                       // layer 4  is unused
+    ADD_NULL_HANDLER,                       // layer 5  is unused
+    ADD_NULL_HANDLER,                       // layer 6  is the feature rc
+    ADD_HANDLER("fapi", NULL),              // layer 7  is the esapi rc
+    ADD_HANDLER("sys", sys_err_handler),    // layer 8  is the sys rc
+    ADD_HANDLER("mu",  sys_err_handler),    // layer 9  is the mu rc
+                                            // Defaults to the system handler
+    ADD_HANDLER("tcti", sys_err_handler),   // layer 10 is the tcti rc
+                                            // Defaults to the system handler
+    ADD_HANDLER("rmt", tpm2_ehandler),      // layer 11 is the resource manager TPM RC
+                                            // The RM usually duplicates TPM responses
+                                            // So just default the handler to tpm2.
+    ADD_HANDLER("rm", NULL),                // layer 12 is the rm rc
+    ADD_HANDLER("drvr", NULL),              // layer 13 is the driver rc
+};
+
+/**
+ * Determines if the layer allowed to be registered to.
+ * @param layer
+ *  The layer to determine handler assignment eligibility of.
+ * @return
+ *  True if it is reserved and thus non-assignable, false otherwise.
+ */
+static bool is_reserved_layer(UINT8 layer) {
+    return layer == 0;
+}
+
+/**
+ * If a layer has no handler registered, default to this
+ * handler that prints the error number in hex.
+ * @param rc
+ *  The rc to print the error number of.
+ * @return
+ *  The string.
+ */
+static const char *unkown_layer_handler(TSS2_RC rc) {
+    UNUSED(rc);
+
+    static char buf[32];
+
+    clearbuf(buf);
+    catbuf(buf, "0x%X", tpm2_error_get(rc));
+
+    return buf;
+}
+
+/**
+ * Register or unregister a custom layer error handler.
+ * @param layer
+ *  The layer in which to register a handler for. It is an error
+ *  to register for the following reserved layers:
+ *    - TSS2_TPM_RC_LAYER  - layer  0
+ *    - TSS2_SYS_RC_LAYER  - layer  8
+ *    - TSS2_MU_RC_LAYER   - layer  9
+ *    - TSS2_TCTI_RC_LAYER - layer 10
+ * @param name
+ *  A friendly layer name. It is an error for the name to be of
+ *  length 0 or greater than 4.
+ * @param handler
+ *  The handler function to register or NULL to unregister.
+ * @return
+ *  True on success or False on error.
+ */
+bool tpm2_error_set_handler(UINT8 layer, const char *name,
+        tpm2_error_handler handler) {
+
+    /* don't allow setting reserved layers */
+    if (is_reserved_layer(layer)) {
+        return false;
+    }
+
+    /*
+     * if they are clearing the handler, name doesn't matter
+     * clear it too.
+     */
+    if (!handler) {
+        name = NULL;
+    }
+
+    /* Perform a zero and max-name length check if name is being set */
+    if (name) {
+        size_t len = name ? strlen(name) : 0;
+        if (!len || len > TSS2_ERR_LAYER_NAME_MAX)
+            return false;
+    }
+
+    layer_handler[layer].handler = handler;
+    layer_handler[layer].name = name;
+
+    return true;
+}
+
+const char * tpm2_error_str(TSS2_RC rc) {
+
+    static char buf[TSS2_ERR_LAYER_NAME_MAX + TSS2_ERR_LAYER_ERROR_STR_MAX + 1];
+
+    clearbuf(buf);
+
+    UINT8 layer = tss2_rc_layer_number_get(rc);
+
+    tpm2_error_handler handler = layer_handler[layer].handler;
+    const char *lname = layer_handler[layer].name;
+
+    if (lname) {
+        catbuf(buf, "%s:", lname);
+    } else {
+        catbuf(buf, "%u:", layer);
+    }
+
+    handler = !handler ? unkown_layer_handler : handler;
+
+    // Handlers only need the error bits. This way they don't
+    // need to concern themselves with masking off the layer
+    // bits or anything else.
+    UINT16 err_bits = tpm2_error_get(rc);
+    const char *e = err_bits ? handler(err_bits) : "success";
+    if (e) {
+        catbuf(buf, "%s", e);
+    } else {
+        catbuf(buf, "0x%X", err_bits);
+    }
+
+    return buf;
+}
diff --git a/TPM2-Plugin/lib/tpm2_hash.c b/TPM2-Plugin/lib/tpm2_hash.c
new file mode 100644
index 0000000..ecf3a72
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_hash.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.
+//
+// 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 <errno.h>
+#include <string.h>
+
+#include <sapi/tpm20.h>
+
+#include "log.h"
+#include "files.h"
+#include "tpm2_hash.h"
+#include "tpm2_util.h"
+
+bool tpm2_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH halg,
+        TPMI_RH_HIERARCHY hierarchy, BYTE *buffer, UINT16 length,
+        TPM2B_DIGEST *result, TPMT_TK_HASHCHECK *validation) {
+
+    FILE *mem = fmemopen(buffer, length, "rb");
+    if (!mem) {
+        LOG_ERR("Error converting buffer to memory stream: %s",
+                strerror(errno));
+        return false;
+    }
+
+    return tpm2_hash_file(sapi_context, halg, hierarchy, mem, result, validation);
+}
+
+bool tpm2_hash_file(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH halg,
+        TPMI_RH_HIERARCHY hierarchy, FILE *input, TPM2B_DIGEST *result,
+        TPMT_TK_HASHCHECK *validation) {
+
+    TPM2B_AUTH nullAuth = TPM2B_EMPTY_INIT;
+    TPMI_DH_OBJECT sequenceHandle;
+
+    TSS2L_SYS_AUTH_COMMAND cmdAuthArray = { 1, {{.sessionHandle = TPM2_RS_PW, 
+            .nonce = TPM2B_EMPTY_INIT, .hmac = TPM2B_EMPTY_INIT,
+            .sessionAttributes = 0, }}};
+    unsigned long file_size = 0;
+
+    /* Suppress error reporting with NULL path */
+    bool res = files_get_file_size(input, &file_size, NULL);
+
+    /* If we can get the file size and its less than 1024, just do it in one hash invocation */
+    if (res && file_size <= TPM2_MAX_DIGEST_BUFFER) {
+
+        TPM2B_MAX_BUFFER buffer = { .size = file_size };
+
+        res = files_read_bytes(input, buffer.buffer, buffer.size);
+        if (!res) {
+            LOG_ERR("Error reading input file!");
+            return false;
+        }
+
+        TSS2_RC rval = TSS2_RETRY_EXP(Tss2_Sys_Hash(sapi_context, NULL, &buffer, halg,
+            hierarchy, result, validation, NULL));
+        if (rval != TSS2_RC_SUCCESS) {
+            LOG_PERR(Tss2_Sys_Hash, rval);
+            return false;
+        }
+
+        return true;
+    }
+
+    /*
+     * Size is either unkown because the FILE * is a fifo, or it's too big
+     * to do in a single hash call. Based on the size figure out the chunks
+     * to loop over, if possible. This way we can call Complete with data.
+     */
+    TSS2_RC rval = TSS2_RETRY_EXP(Tss2_Sys_HashSequenceStart(sapi_context, NULL, &nullAuth,
+            halg, &sequenceHandle, NULL));
+    if (rval != TPM2_RC_SUCCESS) {
+        LOG_PERR(Tss2_Sys_HashSequenceStart, rval);
+        return rval;
+    }
+
+    /* If we know the file size, we decrement the amount read and terminate the loop
+     * when 1 block is left, else we go till feof.
+     */
+    size_t left = file_size;
+    bool use_left = !!res;
+
+    TPM2B_MAX_BUFFER data;
+
+    bool done = false;
+    while (!done) {
+
+        size_t bytes_read = fread(data.buffer, 1,
+                BUFFER_SIZE(typeof(data), buffer), input);
+        if (ferror(input)) {
+            LOG_ERR("Error reading from input file");
+            return false;
+        }
+
+        data.size = bytes_read;
+
+        /* if data was read, update the sequence */
+        rval = TSS2_RETRY_EXP(Tss2_Sys_SequenceUpdate(sapi_context, sequenceHandle,
+                &cmdAuthArray, &data, NULL));
+        if (rval != TPM2_RC_SUCCESS) {
+            LOG_PERR(Tss2_Sys_SequenceUpdate, rval);
+            return false;
+        }
+
+        if (use_left) {
+            left -= bytes_read;
+            if (left <= TPM2_MAX_DIGEST_BUFFER) {
+                done = true;
+                continue;
+            }
+        } else if (feof(input)) {
+            done = true;
+        }
+    } /* end file read/hash update loop */
+
+    if (use_left) {
+        data.size = left;
+        bool res = files_read_bytes(input, data.buffer, left);
+        if (!res) {
+            LOG_ERR("Error reading from input file.");
+            return false;
+        }
+    } else {
+        data.size = 0;
+    }
+
+    rval = TSS2_RETRY_EXP(Tss2_Sys_SequenceComplete(sapi_context, sequenceHandle,
+            &cmdAuthArray, &data, hierarchy, result, validation,
+            NULL));
+    if (rval != TSS2_RC_SUCCESS) {
+        LOG_PERR(Tss2_Sys_SequenceComplete, rval);
+        return false;
+    }
+
+    return true;
+}
diff --git a/TPM2-Plugin/lib/tpm2_plugin_api.c b/TPM2-Plugin/lib/tpm2_plugin_api.c
new file mode 100644
index 0000000..adc8cf7
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_plugin_api.c
@@ -0,0 +1,176 @@
+//**********************************************************************;
+// 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 <sapi/tpm20.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include "tpm2_plugin_api.h"
+#include "log.h"
+#include "tpm2_tcti_ldr.h"
+
+
+const char *tcti_path="libtcti-device.so";
+
+static void tcti_teardown (TSS2_TCTI_CONTEXT *tcti_context)
+{
+
+    Tss2_Tcti_Finalize (tcti_context);
+    free (tcti_context);
+}
+
+static void sapi_teardown (TSS2_SYS_CONTEXT *sapi_context)
+{
+
+    if (sapi_context == NULL)
+        return;
+    Tss2_Sys_Finalize (sapi_context);
+    free (sapi_context);
+}
+
+static void sapi_teardown_full (TSS2_SYS_CONTEXT *sapi_context)
+{
+
+    TSS2_TCTI_CONTEXT *tcti_context = NULL;
+    TSS2_RC rc;
+
+    rc = Tss2_Sys_GetTctiContext (sapi_context, &tcti_context);
+    if (rc != TPM2_RC_SUCCESS)
+        return;
+    sapi_teardown (sapi_context);
+    tcti_teardown (tcti_context);
+}
+
+static TSS2_SYS_CONTEXT* sapi_ctx_init(TSS2_TCTI_CONTEXT *tcti_ctx)
+{
+
+    TSS2_ABI_VERSION abi_version = {
+            .tssCreator = TSSWG_INTEROP,
+            .tssFamily = TSS_SAPI_FIRST_FAMILY,
+            .tssLevel = TSS_SAPI_FIRST_LEVEL,
+            .tssVersion = TSS_SAPI_FIRST_VERSION,
+    };
+
+    size_t size = Tss2_Sys_GetContextSize(0);
+    TSS2_SYS_CONTEXT *sapi_ctx = (TSS2_SYS_CONTEXT*) calloc(1, size);
+    if (sapi_ctx == NULL) {
+        LOG_ERR("Failed to allocate 0x%zx bytes for the SAPI context\n",
+                size);
+        return NULL;
+    }
+
+    TSS2_RC rval = Tss2_Sys_Initialize(sapi_ctx, size, tcti_ctx, &abi_version);
+    if (rval != TPM2_RC_SUCCESS) {
+        LOG_PERR(Tss2_Sys_Initialize, rval);
+        free(sapi_ctx);
+        return NULL;
+    }
+
+    return sapi_ctx;
+}
+int tpm2_rsa_sign_init(
+        unsigned long mechanish,
+        void *param,
+        size_t len,
+        void *ctx)
+{
+    printf("executing tpm2_rsa_sign_init in tpm2_plugin... \n");
+    return 0;
+}
+
+int tpm2_tool_sign(TSS2_SYS_CONTEXT *sapi_context)
+{
+    return 0;
+}
+
+int tpm2_rsa_sign(
+        void  *ctx,
+        unsigned char *msg,
+        int msg_len,
+        unsigned char *sig,
+        int *sig_len)
+{
+    int ret = 1;
+    TSS2_TCTI_CONTEXT *tcti;
+    tcti = tpm2_tcti_ldr_load(tcti_path, NULL);
+    if (!tcti) {
+        LOG_ERR("Could not load tcti, got: \"%s\"", tcti_path);
+        return -1;
+    }
+    
+    TSS2_SYS_CONTEXT *sapi_context = NULL;
+    if (tcti) {
+        sapi_context = sapi_ctx_init(tcti);
+        if (!sapi_context) {
+            goto free_tcti;
+        }
+    }
+    
+    ret = tpm2_tool_sign(sapi_context);
+    if (ret != 0) {
+        LOG_ERR("Unable to run tpm2_tool_sign");
+    sapi_teardown_full(sapi_context);
+
+free_tcti:
+    tpm2_tcti_ldr_unload();
+    return ret;
+}
+}
+
+int tpm2_rsa_create_object(
+                        unsigned long appHandle,
+                        //DhsmWPKRSAFormat* wpk,
+                        void *wpk,
+                        unsigned char* swk,
+                        int swk_len,
+                        unsigned char* iv,
+                        int iv_len,
+                        int tag_len,
+                        void **cb_object)
+{
+    return 0;
+}
+
+int tpm2_rsa_delete_object(void *cb_object)
+{
+    return 0;
+}
+
+int tpm2_import_object(unsigned long appHandle, 
+                       unsigned char* tlvbuffer, 
+                       int buflen, 
+                       unsigned char* iv, 
+                       int iv_len, 
+                       unsigned char* tpm_pwd, 
+                       int tpm_pwd_len)
+
+{
+    return 0;
+}
diff --git a/TPM2-Plugin/lib/tpm2_plugin_init.c b/TPM2-Plugin/lib/tpm2_plugin_init.c
new file mode 100644
index 0000000..5ef0fce
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_plugin_init.c
@@ -0,0 +1,77 @@
+//**********************************************************************;
+// 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 <stdio.h>
+
+#include "plugin_register.h"
+
+#include "tpm2_plugin_api.h"
+
+int __plugin_init(char* configPath)
+{
+// if tpm_plugin, do this
+   printf("Init module done for TPM plug-in mode ! \n");
+// if SGX_plugin, do this
+
+	return 0;
+}
+
+int __plugin_finialize()
+{
+// if tpm_plugin, do this
+	printf("Finalize module done for SW mode ! \n");
+// if SGX_plugin, do this
+
+	return 0;
+}
+
+int __plugin_functions_mapping(plugin_register *plugin_fp)
+{
+    printf("%s(): Assigning Function pointers for TPM (dTPM or PTT) mode \n", __func__);
+    plugin_fp->cb_crypto_rsa_decrypt_init     = NULL;
+    plugin_fp->cb_crypto_rsa_decrypt          = NULL;
+    plugin_fp->cb_crypto_rsa_sign_init        = &tpm2_rsa_sign_init;
+    plugin_fp->cb_crypto_rsa_sign             = &tpm2_rsa_sign;
+    plugin_fp->cb_crypto_rsa_sign_update      = NULL;
+    plugin_fp->cb_crypto_rsa_sign_final       = NULL;
+    plugin_fp->cb_crypto_ecdsa_sign           = NULL;
+    plugin_fp->cb_crypto_ecdsa_verify         = NULL;
+    plugin_fp->cb_crypto_del_apphandle        = NULL;
+    plugin_fp->cb_crypto_swk_getParentKey     = NULL;
+    plugin_fp->cb_crypto_swk_import   	      = &tpm2_import_object;
+    plugin_fp->cb_crypto_rsa_create_object    = &tpm2_rsa_create_object;
+    plugin_fp->cb_crypto_rsa_delete_object    = &tpm2_rsa_delete_object;
+    plugin_fp->cb_crypto_ecdsa_create_object  = NULL;
+    plugin_fp->cb_crypto_ecdsa_delete_object  = NULL;
+
+    return 0;
+}
+
diff --git a/TPM2-Plugin/lib/tpm2_tcti_ldr.c b/TPM2-Plugin/lib/tpm2_tcti_ldr.c
new file mode 100644
index 0000000..9f25188
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_tcti_ldr.c
@@ -0,0 +1,124 @@
+//**********************************************************************;
+// Copyright (c) 2018, 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 <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+#include <sapi/tpm20.h>
+
+#include "log.h"
+#include "tpm2_tcti_ldr.h"
+
+static void *handle;
+static const TSS2_TCTI_INFO *info;
+
+void tpm2_tcti_ldr_unload(void) {
+    if (handle) {
+#ifndef DISABLE_DLCLOSE
+        dlclose(handle);
+#endif
+        handle = NULL;
+        info = NULL;
+    }
+}
+
+const TSS2_TCTI_INFO *tpm2_tcti_ldr_getinfo(void) {
+    return info;
+}
+
+TSS2_TCTI_CONTEXT *tpm2_tcti_ldr_load(const char *path, const char *opts) {
+
+    TSS2_TCTI_CONTEXT *tcti_ctx = NULL;
+
+    if (handle) {
+        LOG_ERR("Attempting to load multiple tcti's simultaneously is not supported!");
+        return NULL;
+    }
+
+    /*
+     * Try what they gave us, if it doesn't load up, try
+     * libtcti-xxx.so replacing xxx with what they gave us.
+     */
+    handle = dlopen (path, RTLD_LAZY);
+    if (!handle) {
+
+        char buf[PATH_MAX];
+        size_t size = snprintf(buf, sizeof(buf), "libtcti-%s.so", path);
+        if (size >= sizeof(buf)) {
+            LOG_ERR("Truncated friendly name conversion, got: \"%s\", made: \"%s\"",
+                    path, buf);
+            return NULL;
+        }
+
+        handle = dlopen (buf, RTLD_LAZY);
+        if (!handle) {
+            LOG_ERR("Could not dlopen library: \"%s\"", buf);
+            return NULL;
+        }
+    }
+
+    TSS2_TCTI_INFO_FUNC infofn = (TSS2_TCTI_INFO_FUNC)dlsym(handle, TSS2_TCTI_INFO_SYMBOL);
+    if (!infofn) {
+        LOG_ERR("Symbol \"%s\"not found in library: \"%s\"",
+                TSS2_TCTI_INFO_SYMBOL, path);
+        goto err;
+    }
+
+    info = infofn();
+
+    TSS2_TCTI_INIT_FUNC init = info->init;
+
+    size_t size;
+    TSS2_RC rc = init(NULL, &size, opts);
+    if (rc != TPM2_RC_SUCCESS) {
+        LOG_ERR("tcti init setup routine failed for library: \"%s\""
+                " options: \"%s\"", path, opts);
+        goto err;
+    }
+
+    tcti_ctx = (TSS2_TCTI_CONTEXT*) calloc(1, size);
+    if (tcti_ctx == NULL) {
+        LOG_ERR("oom");
+        goto err;
+    }
+
+    rc = init(tcti_ctx, &size, opts);
+    if (rc != TPM2_RC_SUCCESS) {
+        LOG_ERR("tcti init allocation routine failed for library: \"%s\""
+                " options: \"%s\"", path, opts);
+        goto err;
+    }
+
+    return tcti_ctx;
+
+err:
+    free(tcti_ctx);
+    dlclose(handle);
+    return NULL;
+}
diff --git a/TPM2-Plugin/lib/tpm2_util.c b/TPM2-Plugin/lib/tpm2_util.c
new file mode 100644
index 0000000..7a42df7
--- /dev/null
+++ b/TPM2-Plugin/lib/tpm2_util.c
@@ -0,0 +1,392 @@
+//**********************************************************************;
+// 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 "log.h"
+#include "files.h"
+#include "tpm2_alg_util.h"
+#include "tpm2_attr_util.h"
+#include "tpm2_util.h"
+bool output_enabled;
+bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append) {
+
+    if (!result || !append) {
+        return false;
+    }
+
+    if ((result->size + append->size) < result->size) {
+        return false;
+    }
+
+    if ((result->size + append->size) > TPM2_MAX_DIGEST_BUFFER) {
+        return false;
+    }
+
+    memcpy(&result->buffer[result->size], append->buffer, append->size);
+    result->size += append->size;
+
+    return true;
+}
+
+bool tpm2_util_string_to_uint16(const char *str, uint16_t *value) {
+
+    uint32_t tmp;
+    bool result = tpm2_util_string_to_uint32(str, &tmp);
+    if (!result) {
+        return false;
+    }
+
+    /* overflow on 16 bits? */
+    if (tmp > UINT16_MAX) {
+        return false;
+    }
+
+    *value = (uint16_t) tmp;
+    return true;
+}
+
+bool tpm2_util_string_to_uint32(const char *str, uint32_t *value) {
+
+    char *endptr;
+
+    if (str == NULL || *str == '\0') {
+        return false;
+    }
+
+    /* clear errno before the call, should be 0 afterwards */
+    errno = 0;
+    uint32_t tmp = strtoul(str, &endptr, 0);
+    if (errno) {
+        return false;
+    }
+
+    /*
+     * The entire string should be able to be converted or fail
+     * We already checked that str starts with a null byte, so no
+     * need to check that again per the man page.
+     */
+    if (*endptr != '\0') {
+        return false;
+    }
+
+    *value = tmp;
+    return true;
+}
+
+int tpm2_util_hex_to_byte_structure(const char *inStr, UINT16 *byteLength,
+        BYTE *byteBuffer) {
+    int strLength; //if the inStr likes "1a2b...", no prefix "0x"
+    int i = 0;
+    if (inStr == NULL || byteLength == NULL || byteBuffer == NULL)
+        return -1;
+    strLength = strlen(inStr);
+    if (strLength % 2)
+        return -2;
+    for (i = 0; i < strLength; i++) {
+        if (!isxdigit(inStr[i]))
+            return -3;
+    }
+
+    if (*byteLength < strLength / 2)
+        return -4;
+
+    *byteLength = strLength / 2;
+
+    for (i = 0; i < *byteLength; i++) {
+        char tmpStr[4] = { 0 };
+        tmpStr[0] = inStr[i * 2];
+        tmpStr[1] = inStr[i * 2 + 1];
+        byteBuffer[i] = strtol(tmpStr, NULL, 16);
+    }
+    return 0;
+}
+
+void tpm2_util_hexdump(const BYTE *data, size_t len, bool plain) {
+
+    if (!output_enabled) {
+        return;
+    }
+
+    if (plain) {
+        size_t i;
+        for (i=0; i < len; i++) {
+            printf("%02x", data[i]);
+        }
+        return;
+    }
+
+    size_t i;
+    size_t j;
+    for (i = 0; i < len; i += 16) {
+        printf("%06zx: ", i);
+
+        for (j = 0; j < 16; j++) {
+            if (i + j < len) {
+                printf("%02x ", data[i + j]);
+            } else {
+                printf("   ");
+            }
+        }
+
+        printf(" ");
+
+        for (j = 0; j < 16; j++) {
+            if (i + j < len) {
+                printf("%c", isprint(data[i + j]) ? data[i + j] : '.');
+            }
+        }
+        printf("\n");
+    }
+}
+
+bool tpm2_util_hexdump_file(FILE *fd, size_t len, bool plain) {
+    BYTE* buff = (BYTE*)malloc(len);
+    if (!buff) {
+        LOG_ERR("malloc() failed");
+        return false;
+    }
+
+    bool res = files_read_bytes(fd, buff, len);
+    if (!res) {
+        LOG_ERR("Failed to read file");
+        free(buff);
+        return false;
+    }
+
+    tpm2_util_hexdump(buff, len, plain);
+
+    free(buff);
+    return true;
+}
+
+bool tpm2_util_print_tpm2b_file(FILE *fd)
+{
+    UINT16 len;
+    bool res = files_read_16(fd, &len);
+    if(!res) {
+        LOG_ERR("File read failed");
+        return false;
+    }
+    return tpm2_util_hexdump_file(fd, len, true);
+}
+
+/* TODO OPTIMIZE ME */
+UINT16 tpm2_util_copy_tpm2b(TPM2B *dest, TPM2B *src) {
+    int i;
+    UINT16 rval = 0;
+
+    if (dest != 0) {
+        if (src == 0) {
+            dest->size = 0;
+            rval = 0;
+        } else {
+            dest->size = src->size;
+            for (i = 0; i < src->size; i++)
+                dest->buffer[i] = src->buffer[i];
+            rval = (sizeof(UINT16) + src->size);
+        }
+    } else {
+        rval = 0;
+    }
+
+    return rval;
+}
+
+bool tpm2_util_is_big_endian(void) {
+
+    uint32_t test_word;
+    uint8_t *test_byte;
+
+    test_word = 0xFF000000;
+    test_byte = (uint8_t *) (&test_word);
+
+    return test_byte[0] == 0xFF;
+}
+
+#define STRING_BYTES_ENDIAN_CONVERT(size) \
+    UINT##size tpm2_util_endian_swap_##size(UINT##size data) { \
+    \
+        UINT##size converted; \
+        UINT8 *bytes = (UINT8 *)&data; \
+        UINT8 *tmp = (UINT8 *)&converted; \
+    \
+        size_t i; \
+        for(i=0; i < sizeof(UINT##size); i ++) { \
+            tmp[i] = bytes[sizeof(UINT##size) - i - 1]; \
+        } \
+        \
+        return converted; \
+    }
+
+STRING_BYTES_ENDIAN_CONVERT(16)
+STRING_BYTES_ENDIAN_CONVERT(32)
+STRING_BYTES_ENDIAN_CONVERT(64)
+
+#define STRING_BYTES_ENDIAN_HTON(size) \
+    UINT##size tpm2_util_hton_##size(UINT##size data) { \
+    \
+        bool is_big_endian = tpm2_util_is_big_endian(); \
+        if (is_big_endian) { \
+           return data; \
+        } \
+    \
+        return tpm2_util_endian_swap_##size(data); \
+    }
+
+STRING_BYTES_ENDIAN_HTON(16)
+STRING_BYTES_ENDIAN_HTON(32)
+STRING_BYTES_ENDIAN_HTON(64)
+
+/*
+ * Converting from host-to-network (hton) or network-to-host (ntoh) is
+ * the same operation: if endianess differs between host and data, swap
+ * endianess. Thus we can just call the hton routines, but have some nice
+ * names for folks.
+ */
+UINT16 tpm2_util_ntoh_16(UINT16 data) {
+    return tpm2_util_hton_16(data);
+}
+
+UINT32 tpm2_util_ntoh_32(UINT32 data) {
+    return tpm2_util_hton_32(data);
+}
+UINT64 tpm2_util_ntoh_64(UINT64 data) {
+    return tpm2_util_hton_64(data);
+}
+
+UINT32 tpm2_util_pop_count(UINT32 data) {
+
+    static const UINT8 bits_per_nibble[] =
+        {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
+
+    UINT8 count = 0;
+    UINT8 *d = (UINT8 *)&data;
+
+    size_t i;
+    for (i=0; i < sizeof(data); i++) {
+        count += bits_per_nibble[d[i] & 0x0f];
+        count += bits_per_nibble[d[i] >> 4];
+    }
+
+    return count;
+}
+
+#define TPM2_UTIL_KEYDATA_INIT { .len = 0 };
+
+typedef struct tpm2_util_keydata tpm2_util_keydata;
+struct tpm2_util_keydata {
+    UINT16 len;
+    struct {
+        const char *name;
+        TPM2B *value;
+    } entries[2];
+};
+
+static void tpm2_util_public_to_keydata(TPM2B_PUBLIC *public, tpm2_util_keydata *keydata) {
+
+    switch (public->publicArea.type) {
+    case TPM2_ALG_RSA:
+        keydata->len = 1;
+        keydata->entries[0].name = tpm2_alg_util_algtostr(public->publicArea.type);
+        keydata->entries[0].value = (TPM2B *)&public->publicArea.unique.rsa;
+        return;
+    case TPM2_ALG_KEYEDHASH:
+        keydata->len = 1;
+        keydata->entries[0].name = tpm2_alg_util_algtostr(public->publicArea.type);
+        keydata->entries[0].value = (TPM2B *)&public->publicArea.unique.keyedHash;
+        return;
+    case TPM2_ALG_SYMCIPHER:
+        keydata->len = 1;
+        keydata->entries[0].name = tpm2_alg_util_algtostr(public->publicArea.type);
+        keydata->entries[0].value = (TPM2B *)&public->publicArea.unique.sym;
+        return;
+    case TPM2_ALG_ECC:
+        keydata->len = 2;
+        keydata->entries[0].name = "x";
+        keydata->entries[0].value = (TPM2B *)&public->publicArea.unique.ecc.x;
+        keydata->entries[1].name = "y";
+        keydata->entries[1].value = (TPM2B *)&public->publicArea.unique.ecc.y;
+        return;
+    default:
+        LOG_WARN("The algorithm type(0x%4.4x) is not supported",
+                public->publicArea.type);
+    }
+
+    return;
+}
+
+void print_yaml_indent(size_t indent_count) {
+    while (indent_count--) {
+        tpm2_tool_output("  ");
+    }
+}
+
+void tpm2_util_tpma_object_to_yaml(TPMA_OBJECT obj) {
+
+    char *attrs = tpm2_attr_util_obj_attrtostr(obj);
+    tpm2_tool_output("attributes:\n");
+    tpm2_tool_output("  value: %s\n", attrs);
+    tpm2_tool_output("  raw: 0x%x\n", obj);
+    free(attrs);
+}
+
+void tpm2_util_public_to_yaml(TPM2B_PUBLIC *public) {
+
+    tpm2_tool_output("algorithm:\n");
+    tpm2_tool_output("  value: %s\n", tpm2_alg_util_algtostr(public->publicArea.nameAlg));
+    tpm2_tool_output("  raw: 0x%x\n", public->publicArea.nameAlg);
+
+    tpm2_util_tpma_object_to_yaml(public->publicArea.objectAttributes);
+
+    tpm2_tool_output("type: \n");
+    tpm2_tool_output("  value: %s\n", tpm2_alg_util_algtostr(public->publicArea.type));
+    tpm2_tool_output("  raw: 0x%x\n", public->publicArea.type);
+
+    tpm2_util_keydata keydata = TPM2_UTIL_KEYDATA_INIT;
+    tpm2_util_public_to_keydata(public, &keydata);
+
+    UINT16 i;
+    /* if no keydata len will be 0 and it wont print */
+    for (i=0; i < keydata.len; i++) {
+        tpm2_tool_output("  %s: ", keydata.entries[i].name);
+        tpm2_util_print_tpm2b(keydata.entries[i].value);
+        tpm2_tool_output("\n");
+    }
+
+    if (public->publicArea.authPolicy.size) {
+        tpm2_tool_output("authorization policy: ");
+        tpm2_util_hexdump(public->publicArea.authPolicy.buffer,
+                public->publicArea.authPolicy.size, true);
+        tpm2_tool_output("\n");
+    }
+}