Mailing List Archive

[VTPM v7 1/8] add vtpm-stubdom code
Add the code base for vtpm-stubdom to the stubdom
heirarchy. Makefile changes in later patch.

Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
stubdom/vtpm/Makefile | 37 +++++
stubdom/vtpm/minios.cfg | 14 ++
stubdom/vtpm/vtpm.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
stubdom/vtpm/vtpm.h | 36 +++++
stubdom/vtpm/vtpm_cmd.c | 256 +++++++++++++++++++++++++++++
stubdom/vtpm/vtpm_cmd.h | 31 ++++
stubdom/vtpm/vtpm_pcrs.c | 43 +++++
stubdom/vtpm/vtpm_pcrs.h | 53 ++++++
stubdom/vtpm/vtpmblk.c | 307 +++++++++++++++++++++++++++++++++++
stubdom/vtpm/vtpmblk.h | 31 ++++
10 files changed, 1212 insertions(+)
create mode 100644 stubdom/vtpm/Makefile
create mode 100644 stubdom/vtpm/minios.cfg
create mode 100644 stubdom/vtpm/vtpm.c
create mode 100644 stubdom/vtpm/vtpm.h
create mode 100644 stubdom/vtpm/vtpm_cmd.c
create mode 100644 stubdom/vtpm/vtpm_cmd.h
create mode 100644 stubdom/vtpm/vtpm_pcrs.c
create mode 100644 stubdom/vtpm/vtpm_pcrs.h
create mode 100644 stubdom/vtpm/vtpmblk.c
create mode 100644 stubdom/vtpm/vtpmblk.h

diff --git a/stubdom/vtpm/Makefile b/stubdom/vtpm/Makefile
new file mode 100644
index 0000000..686c0ea
--- /dev/null
+++ b/stubdom/vtpm/Makefile
@@ -0,0 +1,37 @@
+# Copyright (c) 2010-2012 United States Government, as represented by
+# the Secretary of Defense. All rights reserved.
+#
+# THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+# ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+# INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+# FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+# DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+# SOFTWARE.
+#
+
+XEN_ROOT=../..
+
+PSSL_DIR=../polarssl-$(XEN_TARGET_ARCH)/library
+PSSL_OBJS=aes.o sha1.o entropy.o ctr_drbg.o sha4.o
+
+TARGET=vtpm.a
+OBJS=vtpm.o vtpm_cmd.o vtpmblk.o vtpm_pcrs.o
+
+
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/build
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/tpm
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/crypto
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)
+
+$(TARGET): $(OBJS)
+ ar -cr $@ $(OBJS) $(TPMEMU_OBJS) $(foreach obj,$(PSSL_OBJS),$(PSSL_DIR)/$(obj))
+
+$(OBJS): vtpm_manager.h
+
+vtpm_manager.h:
+ ln -s ../vtpmmgr/vtpm_manager.h vtpm_manager.h
+
+clean:
+ -rm $(TARGET) $(OBJS) vtpm_manager.h
+
+.PHONY: clean
diff --git a/stubdom/vtpm/minios.cfg b/stubdom/vtpm/minios.cfg
new file mode 100644
index 0000000..31652ee
--- /dev/null
+++ b/stubdom/vtpm/minios.cfg
@@ -0,0 +1,14 @@
+CONFIG_TPMFRONT=y
+CONFIG_TPM_TIS=n
+CONFIG_TPMBACK=y
+CONFIG_START_NETWORK=n
+CONFIG_TEST=n
+CONFIG_PCIFRONT=n
+CONFIG_BLKFRONT=y
+CONFIG_NETFRONT=n
+CONFIG_FBFRONT=n
+CONFIG_KBDFRONT=n
+CONFIG_CONSFRONT=n
+CONFIG_XENBUS=y
+CONFIG_LWIP=n
+CONFIG_XC=n
diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
new file mode 100644
index 0000000..71aef78
--- /dev/null
+++ b/stubdom/vtpm/vtpm.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <xen/xen.h>
+#include <tpmback.h>
+#include <tpmfront.h>
+
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+
+#include "tpm/tpm_emulator_extern.h"
+#include "tpm/tpm_marshalling.h"
+#include "vtpm.h"
+#include "vtpm_cmd.h"
+#include "vtpm_pcrs.h"
+#include "vtpmblk.h"
+
+#define TPM_LOG_INFO LOG_INFO
+#define TPM_LOG_ERROR LOG_ERR
+#define TPM_LOG_DEBUG LOG_DEBUG
+
+/* Global commandline options - default values */
+struct Opt_args opt_args = {
+ .startup = ST_CLEAR,
+ .loglevel = TPM_LOG_INFO,
+ .hwinitpcrs = VTPM_PCRNONE,
+ .tpmconf = 0,
+ .enable_maint_cmds = false,
+};
+
+static uint32_t badords[32];
+static unsigned int n_badords = 0;
+
+entropy_context entropy;
+ctr_drbg_context ctr_drbg;
+
+struct tpmfront_dev* tpmfront_dev;
+
+void vtpm_get_extern_random_bytes(void *buf, size_t nbytes)
+{
+ ctr_drbg_random(&ctr_drbg, buf, nbytes);
+}
+
+int vtpm_read_from_file(uint8_t **data, size_t *data_length) {
+ return read_vtpmblk(tpmfront_dev, data, data_length);
+}
+
+int vtpm_write_to_file(uint8_t *data, size_t data_length) {
+ return write_vtpmblk(tpmfront_dev, data, data_length);
+}
+
+int vtpm_extern_init_fake(void) {
+ return 0;
+}
+
+void vtpm_extern_release_fake(void) {
+}
+
+
+void vtpm_log(int priority, const char *fmt, ...)
+{
+ if(opt_args.loglevel >= priority) {
+ va_list v;
+ va_start(v, fmt);
+ vprintf(fmt, v);
+ va_end(v);
+ }
+}
+
+static uint64_t vtpm_get_ticks(void)
+{
+ static uint64_t old_t = 0;
+ uint64_t new_t, res_t;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ new_t = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
+ res_t = (old_t > 0) ? new_t - old_t : 0;
+ old_t = new_t;
+ return res_t;
+}
+
+
+static int tpm_entropy_source(void* dummy, unsigned char* data, size_t len, size_t* olen) {
+ UINT32 sz = len;
+ TPM_RESULT rc = VTPM_GetRandom(tpmfront_dev, data, &sz);
+ *olen = sz;
+ return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+}
+
+int init_random(void) {
+ /* Initialize the rng */
+ entropy_init(&entropy);
+ entropy_add_source(&entropy, tpm_entropy_source, NULL, 0);
+ entropy_gather(&entropy);
+ ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, NULL, 0);
+ ctr_drbg_set_prediction_resistance( &ctr_drbg, CTR_DRBG_PR_OFF );
+
+ return 0;
+}
+
+int check_ordinal(tpmcmd_t* tpmcmd) {
+ TPM_COMMAND_CODE ord;
+ UINT32 len = 4;
+ BYTE* ptr;
+ unsigned int i;
+
+ if(tpmcmd->req_len < 10) {
+ return true;
+ }
+
+ ptr = tpmcmd->req + 6;
+ tpm_unmarshal_UINT32(&ptr, &len, &ord);
+
+ for(i = 0; i < n_badords; ++i) {
+ if(ord == badords[i]) {
+ error("Disabled command ordinal (%" PRIu32") requested!\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+static void main_loop(void) {
+ tpmcmd_t* tpmcmd = NULL;
+ domid_t domid; /* Domid of frontend */
+ unsigned int handle; /* handle of frontend */
+ int res = -1;
+
+ info("VTPM Initializing\n");
+
+ /* Set required tpm config args */
+ opt_args.tpmconf |= TPM_CONF_STRONG_PERSISTENCE;
+ opt_args.tpmconf &= ~TPM_CONF_USE_INTERNAL_PRNG;
+ opt_args.tpmconf |= TPM_CONF_GENERATE_EK;
+ opt_args.tpmconf |= TPM_CONF_GENERATE_SEED_DAA;
+
+ /* Initialize the emulator */
+ tpm_emulator_init(opt_args.startup, opt_args.tpmconf);
+
+ /* Initialize any requested PCRs with hardware TPM values */
+ if(vtpm_initialize_hw_pcrs(tpmfront_dev, opt_args.hwinitpcrs) != TPM_SUCCESS) {
+ error("Failed to initialize PCRs with hardware TPM values");
+ goto abort_postpcrs;
+ }
+
+ /* Wait for the frontend domain to connect */
+ info("Waiting for frontend domain to connect..");
+ if(tpmback_wait_for_frontend_connect(&domid, &handle) == 0) {
+ info("VTPM attached to Frontend %u/%u", (unsigned int) domid, handle);
+ } else {
+ error("Unable to attach to a frontend");
+ }
+
+ tpmcmd = tpmback_req(domid, handle);
+ while(tpmcmd) {
+ /* Handle the request */
+ if(tpmcmd->req_len) {
+ tpmcmd->resp = NULL;
+ tpmcmd->resp_len = 0;
+
+ /* First check for disabled ordinals */
+ if(!check_ordinal(tpmcmd)) {
+ create_error_response(tpmcmd, TPM_BAD_ORDINAL);
+ }
+ /* If not disabled, do the command */
+ else {
+ if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
+ error("tpm_handle_command() failed");
+ create_error_response(tpmcmd, TPM_FAIL);
+ }
+ }
+ }
+
+ /* Send the response */
+ tpmback_resp(tpmcmd);
+
+ /* Wait for the next request */
+ tpmcmd = tpmback_req(domid, handle);
+
+ }
+
+abort_postpcrs:
+ info("VTPM Shutting down\n");
+
+ tpm_emulator_shutdown();
+}
+
+int parse_cmd_line(int argc, char** argv)
+{
+ char sval[25];
+ char* logstr = NULL;
+ /* Parse the command strings */
+ for(unsigned int i = 1; i < argc; ++i) {
+ if (sscanf(argv[i], "loglevel=%25s", sval) == 1){
+ if (!strcmp(sval, "debug")) {
+ opt_args.loglevel = TPM_LOG_DEBUG;
+ logstr = "debug";
+ }
+ else if (!strcmp(sval, "info")) {
+ logstr = "info";
+ opt_args.loglevel = TPM_LOG_INFO;
+ }
+ else if (!strcmp(sval, "error")) {
+ logstr = "error";
+ opt_args.loglevel = TPM_LOG_ERROR;
+ }
+ }
+ else if (!strcmp(argv[i], "clear")) {
+ opt_args.startup = ST_CLEAR;
+ }
+ else if (!strcmp(argv[i], "save")) {
+ opt_args.startup = ST_SAVE;
+ }
+ else if (!strcmp(argv[i], "deactivated")) {
+ opt_args.startup = ST_DEACTIVATED;
+ }
+ else if (!strncmp(argv[i], "maintcmds=", 10)) {
+ if(!strcmp(argv[i] + 10, "1")) {
+ opt_args.enable_maint_cmds = true;
+ } else if(!strcmp(argv[i] + 10, "0")) {
+ opt_args.enable_maint_cmds = false;
+ }
+ }
+ else if(!strncmp(argv[i], "hwinitpcr=", 10)) {
+ char *pch = argv[i] + 10;
+ unsigned int v1, v2;
+ pch = strtok(pch, ",");
+ while(pch != NULL) {
+ if(!strcmp(pch, "all")) {
+ //Set all
+ opt_args.hwinitpcrs = VTPM_PCRALL;
+ } else if(!strcmp(pch, "none")) {
+ //Set none
+ opt_args.hwinitpcrs = VTPM_PCRNONE;
+ } else if(sscanf(pch, "%u", &v1) == 1) {
+ //Set one
+ if(v1 >= TPM_NUM_PCR) {
+ error("hwinitpcr error: Invalid PCR index %u", v1);
+ return -1;
+ }
+ opt_args.hwinitpcrs |= (1 << v1);
+ } else if(sscanf(pch, "%u-%u", &v1, &v2) == 2) {
+ //Set range
+ if(v1 >= TPM_NUM_PCR) {
+ error("hwinitpcr error: Invalid PCR index %u", v1);
+ return -1;
+ }
+ if(v2 >= TPM_NUM_PCR) {
+ error("hwinitpcr error: Invalid PCR index %u", v1);
+ return -1;
+ }
+ if(v2 < v1) {
+ unsigned tp = v1;
+ v1 = v2;
+ v2 = tp;
+ }
+ for(unsigned int i = v1; i <= v2; ++i) {
+ opt_args.hwinitpcrs |= (1 << i);
+ }
+ } else {
+ error("hwintipcr error: Invalid PCR specification : %s", pch);
+ return -1;
+ }
+ pch = strtok(NULL, ",");
+ }
+ }
+ else {
+ error("Invalid command line option `%s'", argv[i]);
+ }
+
+ }
+
+ /* Check Errors and print results */
+ switch(opt_args.startup) {
+ case ST_CLEAR:
+ info("Startup mode is `clear'");
+ break;
+ case ST_SAVE:
+ info("Startup mode is `save'");
+ break;
+ case ST_DEACTIVATED:
+ info("Startup mode is `deactivated'");
+ break;
+ default:
+ error("Invalid startup mode %d", opt_args.startup);
+ return -1;
+ }
+
+ if(opt_args.hwinitpcrs & (VTPM_PCRALL))
+ {
+ char pcrstr[1024];
+ char* ptr = pcrstr;
+
+ pcrstr[0] = '\0';
+ info("The following PCRs will be initialized with values from the hardware TPM:");
+ for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
+ if(opt_args.hwinitpcrs & (1 << i)) {
+ ptr += sprintf(ptr, "%u, ", i);
+ }
+ }
+ /* get rid of the last comma if any numbers were printed */
+ *(ptr -2) = '\0';
+
+ info("\t%s", pcrstr);
+ } else {
+ info("All PCRs initialized to default values");
+ }
+
+ if(!opt_args.enable_maint_cmds) {
+ info("TPM Maintenance Commands disabled");
+ badords[n_badords++] = TPM_ORD_CreateMaintenanceArchive;
+ badords[n_badords++] = TPM_ORD_LoadMaintenanceArchive;
+ badords[n_badords++] = TPM_ORD_KillMaintenanceFeature;
+ badords[n_badords++] = TPM_ORD_LoadManuMaintPub;
+ badords[n_badords++] = TPM_ORD_ReadManuMaintPub;
+ } else {
+ info("TPM Maintenance Commands enabled");
+ }
+
+ info("Log level set to %s", logstr);
+
+ return 0;
+}
+
+void cleanup_opt_args(void) {
+}
+
+int main(int argc, char **argv)
+{
+ //FIXME: initializing blkfront without this sleep causes the domain to crash on boot
+ sleep(2);
+
+ /* Setup extern function pointers */
+ tpm_extern_init = vtpm_extern_init_fake;
+ tpm_extern_release = vtpm_extern_release_fake;
+ tpm_malloc = malloc;
+ tpm_free = free;
+ tpm_log = vtpm_log;
+ tpm_get_ticks = vtpm_get_ticks;
+ tpm_get_extern_random_bytes = vtpm_get_extern_random_bytes;
+ tpm_write_to_storage = vtpm_write_to_file;
+ tpm_read_from_storage = vtpm_read_from_file;
+
+ info("starting TPM Emulator (1.2.%d.%d-%d)", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
+ if(parse_cmd_line(argc, argv)) {
+ error("Error parsing commandline\n");
+ return -1;
+ }
+
+ /* Initialize devices */
+ init_tpmback();
+ if((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
+ error("Unable to initialize tpmfront device");
+ goto abort_posttpmfront;
+ }
+
+ /* Seed the RNG with entropy from hardware TPM */
+ if(init_random()) {
+ error("Unable to initialize RNG");
+ goto abort_postrng;
+ }
+
+ /* Initialize blkfront device */
+ if(init_vtpmblk(tpmfront_dev)) {
+ error("Unable to initialize Blkfront persistent storage");
+ goto abort_postvtpmblk;
+ }
+
+ /* Run main loop */
+ main_loop();
+
+ /* Shutdown blkfront */
+ shutdown_vtpmblk();
+abort_postvtpmblk:
+abort_postrng:
+
+ /* Close devices */
+ shutdown_tpmfront(tpmfront_dev);
+abort_posttpmfront:
+ shutdown_tpmback();
+
+ cleanup_opt_args();
+
+ return 0;
+}
diff --git a/stubdom/vtpm/vtpm.h b/stubdom/vtpm/vtpm.h
new file mode 100644
index 0000000..5919e44
--- /dev/null
+++ b/stubdom/vtpm/vtpm.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef VTPM_H
+#define VTPM_H
+
+#include <stdbool.h>
+
+/* For testing */
+#define VERS_CMD "\x00\xC1\x00\x00\x00\x16\x00\x00\x00\x65\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x01\x03"
+#define VERS_CMD_LEN 22
+
+/* Global commandline options */
+struct Opt_args {
+ enum StartUp {
+ ST_CLEAR = 1,
+ ST_SAVE = 2,
+ ST_DEACTIVATED = 3
+ } startup;
+ unsigned long hwinitpcrs;
+ int loglevel;
+ uint32_t tpmconf;
+ bool enable_maint_cmds;
+};
+extern struct Opt_args opt_args;
+
+#endif
diff --git a/stubdom/vtpm/vtpm_cmd.c b/stubdom/vtpm/vtpm_cmd.c
new file mode 100644
index 0000000..7eae98b
--- /dev/null
+++ b/stubdom/vtpm/vtpm_cmd.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include <types.h>
+#include <xen/xen.h>
+#include <mm.h>
+#include <gnttab.h>
+#include "tpm/tpm_marshalling.h"
+#include "vtpm_manager.h"
+#include "vtpm_cmd.h"
+#include <tpmback.h>
+
+#define TRYFAILGOTO(C) \
+ if((C)) { \
+ status = TPM_FAIL; \
+ goto abort_egress; \
+ }
+#define TRYFAILGOTOMSG(C, msg) \
+ if((C)) { \
+ status = TPM_FAIL; \
+ error(msg); \
+ goto abort_egress; \
+ }
+#define CHECKSTATUSGOTO(ret, fname) \
+ if((ret) != TPM_SUCCESS) { \
+ error("%s failed with error code (%lu)", fname, (unsigned long) ret); \
+ status = ord; \
+ goto abort_egress; \
+ }
+
+#define ERR_MALFORMED "Malformed response from backend"
+#define ERR_TPMFRONT "Error sending command through frontend device"
+
+struct shpage {
+ void* page;
+ grant_ref_t grantref;
+};
+
+typedef struct shpage shpage_t;
+
+static inline int pack_header(uint8_t** bptr, UINT32* len, TPM_TAG tag, UINT32 size, TPM_COMMAND_CODE ord)
+{
+ return *bptr == NULL ||
+ tpm_marshal_UINT16(bptr, len, tag) ||
+ tpm_marshal_UINT32(bptr, len, size) ||
+ tpm_marshal_UINT32(bptr, len, ord);
+}
+
+static inline int unpack_header(uint8_t** bptr, UINT32* len, TPM_TAG* tag, UINT32* size, TPM_COMMAND_CODE* ord)
+{
+ return *bptr == NULL ||
+ tpm_unmarshal_UINT16(bptr, len, tag) ||
+ tpm_unmarshal_UINT32(bptr, len, size) ||
+ tpm_unmarshal_UINT32(bptr, len, ord);
+}
+
+int create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode)
+{
+ TPM_TAG tag;
+ UINT32 len = tpmcmd->req_len;
+ uint8_t* respptr;
+ uint8_t* cmdptr = tpmcmd->req;
+
+ if(!tpm_unmarshal_UINT16(&cmdptr, &len, &tag)) {
+ switch (tag) {
+ case TPM_TAG_RQU_COMMAND:
+ tag = TPM_TAG_RSP_COMMAND;
+ break;
+ case TPM_TAG_RQU_AUTH1_COMMAND:
+ tag = TPM_TAG_RQU_AUTH2_COMMAND;
+ break;
+ case TPM_TAG_RQU_AUTH2_COMMAND:
+ tag = TPM_TAG_RQU_AUTH2_COMMAND;
+ break;
+ }
+ } else {
+ tag = TPM_TAG_RSP_COMMAND;
+ }
+
+ tpmcmd->resp_len = len = 10;
+ tpmcmd->resp = respptr = tpm_malloc(tpmcmd->resp_len);
+
+ return pack_header(&respptr, &len, tag, len, errorcode);
+}
+
+TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes, UINT32 *numbytes) {
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t* cmdbuf, *resp, *bptr;
+ size_t resplen = 0;
+ UINT32 len;
+
+ /*Ask the real tpm for random bytes for the seed */
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = TPM_ORD_GetRandom;
+ len = size = sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE) + sizeof(UINT32);
+
+ /*Create the raw tpm command */
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+ TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, *numbytes));
+
+ /* Send cmd, wait for response */
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen),
+ ERR_TPMFRONT);
+
+ bptr = resp; len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ //Check return status of command
+ CHECKSTATUSGOTO(ord, "TPM_GetRandom()");
+
+ // Get the number of random bytes in the response
+ TRYFAILGOTOMSG(tpm_unmarshal_UINT32(&bptr, &len, &size), ERR_MALFORMED);
+ *numbytes = size;
+
+ //Get the random bytes out, tpm may give us less bytes than what we wanrt
+ TRYFAILGOTOMSG(tpm_unmarshal_BYTE_ARRAY(&bptr, &len, bytes, *numbytes), ERR_MALFORMED);
+
+ goto egress;
+abort_egress:
+egress:
+ free(cmdbuf);
+ return status;
+
+}
+
+TPM_RESULT VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t* data_length)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t* bptr, *resp;
+ uint8_t* cmdbuf = NULL;
+ size_t resplen = 0;
+ UINT32 len;
+
+ TPM_TAG tag = VTPM_TAG_REQ;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = VTPM_ORD_LOADHASHKEY;
+
+ /*Create the command*/
+ len = size = VTPM_COMMAND_HEADER_SIZE;
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+
+ /* Send the command to vtpm_manager */
+ info("Requesting Encryption key from backend");
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
+
+ /* Unpack response header */
+ bptr = resp;
+ len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ /* Check return code */
+ CHECKSTATUSGOTO(ord, "VTPM_LoadHashKey()");
+
+ /* Get the size of the key */
+ *data_length = size - VTPM_COMMAND_HEADER_SIZE;
+
+ /* Copy the key bits */
+ *data = malloc(*data_length);
+ memcpy(*data, bptr, *data_length);
+
+ goto egress;
+abort_egress:
+ error("VTPM_LoadHashKey failed");
+egress:
+ free(cmdbuf);
+ return status;
+}
+
+TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t* bptr, *resp;
+ uint8_t* cmdbuf = NULL;
+ size_t resplen = 0;
+ UINT32 len;
+
+ TPM_TAG tag = VTPM_TAG_REQ;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = VTPM_ORD_SAVEHASHKEY;
+
+ /*Create the command*/
+ len = size = VTPM_COMMAND_HEADER_SIZE + data_length;
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+ memcpy(bptr, data, data_length);
+ bptr += data_length;
+
+ /* Send the command to vtpm_manager */
+ info("Sending encryption key to backend");
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
+
+ /* Unpack response header */
+ bptr = resp;
+ len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ /* Check return code */
+ CHECKSTATUSGOTO(ord, "VTPM_SaveHashKey()");
+
+ goto egress;
+abort_egress:
+ error("VTPM_SaveHashKey failed");
+egress:
+ free(cmdbuf);
+ return status;
+}
+
+TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex, BYTE* outDigest)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t *cmdbuf, *resp, *bptr;
+ size_t resplen = 0;
+ UINT32 len;
+
+ /*Just send a TPM_PCRRead Command to the HW tpm */
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = TPM_ORD_PCRRead;
+ len = size = sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE) + sizeof(UINT32);
+
+ /*Create the raw tpm cmd */
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+ TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, pcrIndex));
+
+ /*Send Cmd wait for response */
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
+
+ bptr = resp; len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ //Check return status of command
+ CHECKSTATUSGOTO(ord, "TPM_PCRRead");
+
+ //Get the ptr value
+ memcpy(outDigest, bptr, sizeof(TPM_PCRVALUE));
+
+ goto egress;
+abort_egress:
+egress:
+ free(cmdbuf);
+ return status;
+
+}
diff --git a/stubdom/vtpm/vtpm_cmd.h b/stubdom/vtpm/vtpm_cmd.h
new file mode 100644
index 0000000..b0bfa22
--- /dev/null
+++ b/stubdom/vtpm/vtpm_cmd.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef MANAGER_H
+#define MANAGER_H
+
+#include <tpmfront.h>
+#include <tpmback.h>
+#include "tpm/tpm_structures.h"
+
+/* Create a command response error header */
+int create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode);
+/* Request random bytes from hardware tpm, returns 0 on success */
+TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes, UINT32* numbytes);
+/* Retreive 256 bit AES encryption key from manager */
+TPM_RESULT VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t* data_length);
+/* Manager securely saves our 256 bit AES encryption key */
+TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length);
+/* Send a TPM_PCRRead command passthrough the manager to the hw tpm */
+TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex, BYTE* outDigest);
+
+#endif
diff --git a/stubdom/vtpm/vtpm_pcrs.c b/stubdom/vtpm/vtpm_pcrs.c
new file mode 100644
index 0000000..22a6cef
--- /dev/null
+++ b/stubdom/vtpm/vtpm_pcrs.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include "vtpm_pcrs.h"
+#include "vtpm_cmd.h"
+#include "tpm/tpm_data.h"
+
+#define PCR_VALUE tpmData.permanent.data.pcrValue
+
+static int write_pcr_direct(unsigned int pcrIndex, uint8_t* val) {
+ if(pcrIndex > TPM_NUM_PCR) {
+ return TPM_BADINDEX;
+ }
+ memcpy(&PCR_VALUE[pcrIndex], val, sizeof(TPM_PCRVALUE));
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev, unsigned long pcrs)
+{
+ TPM_RESULT rc = TPM_SUCCESS;
+ uint8_t digest[sizeof(TPM_PCRVALUE)];
+
+ for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
+ if(pcrs & 1 << i) {
+ if((rc = VTPM_PCRRead(tpmfront_dev, i, digest)) != TPM_SUCCESS) {
+ error("TPM_PCRRead failed with error : %d", rc);
+ return rc;
+ }
+ write_pcr_direct(i, digest);
+ }
+ }
+
+ return rc;
+}
diff --git a/stubdom/vtpm/vtpm_pcrs.h b/stubdom/vtpm/vtpm_pcrs.h
new file mode 100644
index 0000000..11835f9
--- /dev/null
+++ b/stubdom/vtpm/vtpm_pcrs.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef VTPM_PCRS_H
+#define VTPM_PCRS_H
+
+#include "tpm/tpm_structures.h"
+
+#define VTPM_PCR0 1
+#define VTPM_PCR1 1 << 1
+#define VTPM_PCR2 1 << 2
+#define VTPM_PCR3 1 << 3
+#define VTPM_PCR4 1 << 4
+#define VTPM_PCR5 1 << 5
+#define VTPM_PCR6 1 << 6
+#define VTPM_PCR7 1 << 7
+#define VTPM_PCR8 1 << 8
+#define VTPM_PCR9 1 << 9
+#define VTPM_PCR10 1 << 10
+#define VTPM_PCR11 1 << 11
+#define VTPM_PCR12 1 << 12
+#define VTPM_PCR13 1 << 13
+#define VTPM_PCR14 1 << 14
+#define VTPM_PCR15 1 << 15
+#define VTPM_PCR16 1 << 16
+#define VTPM_PCR17 1 << 17
+#define VTPM_PCR18 1 << 18
+#define VTPM_PCR19 1 << 19
+#define VTPM_PCR20 1 << 20
+#define VTPM_PCR21 1 << 21
+#define VTPM_PCR22 1 << 22
+#define VTPM_PCR23 1 << 23
+
+#define VTPM_PCRALL (1 << TPM_NUM_PCR) - 1
+#define VTPM_PCRNONE 0
+
+#define VTPM_NUMPCRS 24
+
+struct tpmfront_dev;
+
+TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev, unsigned long pcrs);
+
+
+#endif
diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c
new file mode 100644
index 0000000..b343bd8
--- /dev/null
+++ b/stubdom/vtpm/vtpmblk.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include <mini-os/byteorder.h>
+#include "vtpmblk.h"
+#include "tpm/tpm_marshalling.h"
+#include "vtpm_cmd.h"
+#include "polarssl/aes.h"
+#include "polarssl/sha1.h"
+#include <blkfront.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/*Encryption key and block sizes */
+#define BLKSZ 16
+
+static struct blkfront_dev* blkdev = NULL;
+static int blkfront_fd = -1;
+
+int init_vtpmblk(struct tpmfront_dev* tpmfront_dev)
+{
+ struct blkfront_info blkinfo;
+ info("Initializing persistent NVM storage\n");
+
+ if((blkdev = init_blkfront(NULL, &blkinfo)) == NULL) {
+ error("BLKIO: ERROR Unable to initialize blkfront");
+ return -1;
+ }
+ if (blkinfo.info & VDISK_READONLY || blkinfo.mode != O_RDWR) {
+ error("BLKIO: ERROR block device is read only!");
+ goto error;
+ }
+ if((blkfront_fd = blkfront_open(blkdev)) == -1) {
+ error("Unable to open blkfront file descriptor!");
+ goto error;
+ }
+
+ return 0;
+error:
+ shutdown_blkfront(blkdev);
+ blkdev = NULL;
+ return -1;
+}
+
+void shutdown_vtpmblk(void)
+{
+ close(blkfront_fd);
+ blkfront_fd = -1;
+ blkdev = NULL;
+}
+
+int write_vtpmblk_raw(uint8_t *data, size_t data_length)
+{
+ int rc;
+ uint32_t lenbuf;
+ debug("Begin Write data=%p len=%u", data, data_length);
+
+ lenbuf = cpu_to_be32((uint32_t)data_length);
+
+ lseek(blkfront_fd, 0, SEEK_SET);
+ if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
+ error("write(length) failed! error was %s", strerror(errno));
+ return -1;
+ }
+ if((rc = write(blkfront_fd, data, data_length)) != data_length) {
+ error("write(data) failed! error was %s", strerror(errno));
+ return -1;
+ }
+
+ info("Wrote %u bytes to NVM persistent storage", data_length);
+
+ return 0;
+}
+
+int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
+{
+ int rc;
+ uint32_t lenbuf;
+
+ lseek(blkfront_fd, 0, SEEK_SET);
+ if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
+ error("read(length) failed! error was %s", strerror(errno));
+ return -1;
+ }
+ *data_length = (size_t) cpu_to_be32(lenbuf);
+ if(*data_length == 0) {
+ error("read 0 data_length for NVM");
+ return -1;
+ }
+
+ *data = tpm_malloc(*data_length);
+ if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
+ error("read(data) failed! error was %s", strerror(errno));
+ return -1;
+ }
+
+ info("Read %u bytes from NVM persistent storage", *data_length);
+ return 0;
+}
+
+int encrypt_vtpmblk(uint8_t* clear, size_t clear_len, uint8_t** cipher, size_t* cipher_len, uint8_t* symkey)
+{
+ int rc = 0;
+ uint8_t iv[BLKSZ];
+ aes_context aes_ctx;
+ UINT32 temp;
+ int mod;
+
+ uint8_t* clbuf = NULL;
+
+ uint8_t* ivptr;
+ int ivlen;
+
+ uint8_t* cptr; //Cipher block pointer
+ int clen; //Cipher block length
+
+ /*Create a new 256 bit encryption key */
+ if(symkey == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+ tpm_get_extern_random_bytes(symkey, NVMKEYSZ);
+
+ /*Setup initialization vector - random bits and then 4 bytes clear text size at the end*/
+ temp = sizeof(UINT32);
+ ivlen = BLKSZ - temp;
+ tpm_get_extern_random_bytes(iv, ivlen);
+ ivptr = iv + ivlen;
+ tpm_marshal_UINT32(&ivptr, &temp, (UINT32) clear_len);
+
+ /*The clear text needs to be padded out to a multiple of BLKSZ */
+ mod = clear_len % BLKSZ;
+ clen = mod ? clear_len + BLKSZ - mod : clear_len;
+ clbuf = malloc(clen);
+ if (clbuf == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+ memcpy(clbuf, clear, clear_len);
+ /* zero out the padding bits - FIXME: better / more secure way to handle these? */
+ if(clen - clear_len) {
+ memset(clbuf + clear_len, 0, clen - clear_len);
+ }
+
+ /* Setup the ciphertext buffer */
+ *cipher_len = BLKSZ + clen; /*iv + ciphertext */
+ cptr = *cipher = malloc(*cipher_len);
+ if (*cipher == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+
+ /* Copy the IV to cipher text blob*/
+ memcpy(cptr, iv, BLKSZ);
+ cptr += BLKSZ;
+
+ /* Setup encryption */
+ aes_setkey_enc(&aes_ctx, symkey, 256);
+
+ /* Do encryption now */
+ aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, clen, iv, clbuf, cptr);
+
+ goto egress;
+abort_egress:
+egress:
+ free(clbuf);
+ return rc;
+}
+int decrypt_vtpmblk(uint8_t* cipher, size_t cipher_len, uint8_t** clear, size_t* clear_len, uint8_t* symkey)
+{
+ int rc = 0;
+ uint8_t iv[BLKSZ];
+ uint8_t* ivptr;
+ UINT32 u32, temp;
+ aes_context aes_ctx;
+
+ uint8_t* cptr = cipher; //cipher block pointer
+ int clen = cipher_len; //cipher block length
+
+ /* Pull out the initialization vector */
+ memcpy(iv, cipher, BLKSZ);
+ cptr += BLKSZ;
+ clen -= BLKSZ;
+
+ /* Setup the clear text buffer */
+ if((*clear = malloc(clen)) == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+
+ /* Get the length of clear text from last 4 bytes of iv */
+ temp = sizeof(UINT32);
+ ivptr = iv + BLKSZ - temp;
+ tpm_unmarshal_UINT32(&ivptr, &temp, &u32);
+ *clear_len = u32;
+
+ /* Setup decryption */
+ aes_setkey_dec(&aes_ctx, symkey, 256);
+
+ /* Do decryption now */
+ if ((clen % BLKSZ) != 0) {
+ error("Decryption Error: Cipher block size was not a multiple of %u", BLKSZ);
+ rc = -1;
+ goto abort_egress;
+ }
+ aes_crypt_cbc(&aes_ctx, AES_DECRYPT, clen, iv, cptr, *clear);
+
+ goto egress;
+abort_egress:
+egress:
+ return rc;
+}
+
+int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
+ int rc;
+ uint8_t* cipher = NULL;
+ size_t cipher_len = 0;
+ uint8_t hashkey[HASHKEYSZ];
+ uint8_t* symkey = hashkey + HASHSZ;
+
+ /* Encrypt the data */
+ if((rc = encrypt_vtpmblk(data, data_length, &cipher, &cipher_len, symkey))) {
+ goto abort_egress;
+ }
+ /* Write to disk */
+ if((rc = write_vtpmblk_raw(cipher, cipher_len))) {
+ goto abort_egress;
+ }
+ /* Get sha1 hash of data */
+ sha1(cipher, cipher_len, hashkey);
+
+ /* Send hash and key to manager */
+ if((rc = VTPM_SaveHashKey(tpmfront_dev, hashkey, HASHKEYSZ)) != TPM_SUCCESS) {
+ goto abort_egress;
+ }
+ goto egress;
+abort_egress:
+egress:
+ free(cipher);
+ return rc;
+}
+
+int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data_length) {
+ int rc;
+ uint8_t* cipher = NULL;
+ size_t cipher_len = 0;
+ size_t keysize;
+ uint8_t* hashkey = NULL;
+ uint8_t hash[HASHSZ];
+ uint8_t* symkey;
+
+ /* Retreive the hash and the key from the manager */
+ if((rc = VTPM_LoadHashKey(tpmfront_dev, &hashkey, &keysize)) != TPM_SUCCESS) {
+ goto abort_egress;
+ }
+ if(keysize != HASHKEYSZ) {
+ error("Manager returned a hashkey of invalid size! expected %d, actual %d", NVMKEYSZ, keysize);
+ rc = -1;
+ goto abort_egress;
+ }
+ symkey = hashkey + HASHSZ;
+
+ /* Read from disk now */
+ if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
+ goto abort_egress;
+ }
+
+ /* Compute the hash of the cipher text and compare */
+ sha1(cipher, cipher_len, hash);
+ if(memcmp(hash, hashkey, HASHSZ)) {
+ int i;
+ error("NVM Storage Checksum failed!");
+ printf("Expected: ");
+ for(i = 0; i < HASHSZ; ++i) {
+ printf("%02hhX ", hashkey[i]);
+ }
+ printf("\n");
+ printf("Actual: ");
+ for(i = 0; i < HASHSZ; ++i) {
+ printf("%02hhX ", hash[i]);
+ }
+ printf("\n");
+ rc = -1;
+ goto abort_egress;
+ }
+
+ /* Decrypt the blob */
+ if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
+ goto abort_egress;
+ }
+ goto egress;
+abort_egress:
+egress:
+ free(cipher);
+ free(hashkey);
+ return rc;
+}
diff --git a/stubdom/vtpm/vtpmblk.h b/stubdom/vtpm/vtpmblk.h
new file mode 100644
index 0000000..282ce6a
--- /dev/null
+++ b/stubdom/vtpm/vtpmblk.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef NVM_H
+#define NVM_H
+#include <mini-os/types.h>
+#include <xen/xen.h>
+#include <tpmfront.h>
+
+#define NVMKEYSZ 32
+#define HASHSZ 20
+#define HASHKEYSZ (NVMKEYSZ + HASHSZ)
+
+int init_vtpmblk(struct tpmfront_dev* tpmfront_dev);
+void shutdown_vtpmblk(void);
+
+/* Encrypts and writes data to blk device */
+int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t *data, size_t data_length);
+/* Reads, Decrypts, and returns data from blk device */
+int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t **data, size_t *data_length);
+
+#endif
--
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Re: [VTPM v7 1/8] add vtpm-stubdom code [ In reply to ]
For future reference please could you include an indication of what
changed in a new posting of a series, either in the 0/N mail (which is
useful to include as an intro in any case) or in the individual
changelogs.

On Thu, 2012-12-06 at 18:19 +0000, Matthew Fioravante wrote:
> Add the code base for vtpm-stubdom to the stubdom
> heirarchy. Makefile changes in later patch.
>
> Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> ---
> stubdom/vtpm/Makefile | 37 +++++
> stubdom/vtpm/minios.cfg | 14 ++
> stubdom/vtpm/vtpm.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
> stubdom/vtpm/vtpm.h | 36 +++++
> stubdom/vtpm/vtpm_cmd.c | 256 +++++++++++++++++++++++++++++
> stubdom/vtpm/vtpm_cmd.h | 31 ++++
> stubdom/vtpm/vtpm_pcrs.c | 43 +++++
> stubdom/vtpm/vtpm_pcrs.h | 53 ++++++
> stubdom/vtpm/vtpmblk.c | 307 +++++++++++++++++++++++++++++++++++
> stubdom/vtpm/vtpmblk.h | 31 ++++
> 10 files changed, 1212 insertions(+)
> create mode 100644 stubdom/vtpm/Makefile
> create mode 100644 stubdom/vtpm/minios.cfg
> create mode 100644 stubdom/vtpm/vtpm.c
> create mode 100644 stubdom/vtpm/vtpm.h
> create mode 100644 stubdom/vtpm/vtpm_cmd.c
> create mode 100644 stubdom/vtpm/vtpm_cmd.h
> create mode 100644 stubdom/vtpm/vtpm_pcrs.c
> create mode 100644 stubdom/vtpm/vtpm_pcrs.h
> create mode 100644 stubdom/vtpm/vtpmblk.c
> create mode 100644 stubdom/vtpm/vtpmblk.h
>
> diff --git a/stubdom/vtpm/Makefile b/stubdom/vtpm/Makefile
> new file mode 100644
> index 0000000..686c0ea
> --- /dev/null
> +++ b/stubdom/vtpm/Makefile
> @@ -0,0 +1,37 @@
> +# Copyright (c) 2010-2012 United States Government, as represented by
> +# the Secretary of Defense. All rights reserved.
> +#
> +# THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> +# ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> +# INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> +# FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> +# DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> +# SOFTWARE.
> +#
> +
> +XEN_ROOT=../..
> +
> +PSSL_DIR=../polarssl-$(XEN_TARGET_ARCH)/library
> +PSSL_OBJS=aes.o sha1.o entropy.o ctr_drbg.o sha4.o
> +
> +TARGET=vtpm.a
> +OBJS=vtpm.o vtpm_cmd.o vtpmblk.o vtpm_pcrs.o
> +
> +
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/build
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/tpm
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/crypto
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)
> +
> +$(TARGET): $(OBJS)
> + ar -cr $@ $(OBJS) $(TPMEMU_OBJS) $(foreach obj,$(PSSL_OBJS),$(PSSL_DIR)/$(obj))
> +
> +$(OBJS): vtpm_manager.h
> +
> +vtpm_manager.h:
> + ln -s ../vtpmmgr/vtpm_manager.h vtpm_manager.h
> +
> +clean:
> + -rm $(TARGET) $(OBJS) vtpm_manager.h
> +
> +.PHONY: clean
> diff --git a/stubdom/vtpm/minios.cfg b/stubdom/vtpm/minios.cfg
> new file mode 100644
> index 0000000..31652ee
> --- /dev/null
> +++ b/stubdom/vtpm/minios.cfg
> @@ -0,0 +1,14 @@
> +CONFIG_TPMFRONT=y
> +CONFIG_TPM_TIS=n
> +CONFIG_TPMBACK=y
> +CONFIG_START_NETWORK=n
> +CONFIG_TEST=n
> +CONFIG_PCIFRONT=n
> +CONFIG_BLKFRONT=y
> +CONFIG_NETFRONT=n
> +CONFIG_FBFRONT=n
> +CONFIG_KBDFRONT=n
> +CONFIG_CONSFRONT=n
> +CONFIG_XENBUS=y
> +CONFIG_LWIP=n
> +CONFIG_XC=n
> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
> new file mode 100644
> index 0000000..71aef78
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm.c
> @@ -0,0 +1,404 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <syslog.h>
> +#include <stdbool.h>
> +#include <errno.h>
> +#include <sys/time.h>
> +#include <xen/xen.h>
> +#include <tpmback.h>
> +#include <tpmfront.h>
> +
> +#include <polarssl/entropy.h>
> +#include <polarssl/ctr_drbg.h>
> +
> +#include "tpm/tpm_emulator_extern.h"
> +#include "tpm/tpm_marshalling.h"
> +#include "vtpm.h"
> +#include "vtpm_cmd.h"
> +#include "vtpm_pcrs.h"
> +#include "vtpmblk.h"
> +
> +#define TPM_LOG_INFO LOG_INFO
> +#define TPM_LOG_ERROR LOG_ERR
> +#define TPM_LOG_DEBUG LOG_DEBUG
> +
> +/* Global commandline options - default values */
> +struct Opt_args opt_args = {
> + .startup = ST_CLEAR,
> + .loglevel = TPM_LOG_INFO,
> + .hwinitpcrs = VTPM_PCRNONE,
> + .tpmconf = 0,
> + .enable_maint_cmds = false,
> +};
> +
> +static uint32_t badords[32];
> +static unsigned int n_badords = 0;
> +
> +entropy_context entropy;
> +ctr_drbg_context ctr_drbg;
> +
> +struct tpmfront_dev* tpmfront_dev;
> +
> +void vtpm_get_extern_random_bytes(void *buf, size_t nbytes)
> +{
> + ctr_drbg_random(&ctr_drbg, buf, nbytes);
> +}
> +
> +int vtpm_read_from_file(uint8_t **data, size_t *data_length) {
> + return read_vtpmblk(tpmfront_dev, data, data_length);
> +}
> +
> +int vtpm_write_to_file(uint8_t *data, size_t data_length) {
> + return write_vtpmblk(tpmfront_dev, data, data_length);
> +}
> +
> +int vtpm_extern_init_fake(void) {
> + return 0;
> +}
> +
> +void vtpm_extern_release_fake(void) {
> +}
> +
> +
> +void vtpm_log(int priority, const char *fmt, ...)
> +{
> + if(opt_args.loglevel >= priority) {
> + va_list v;
> + va_start(v, fmt);
> + vprintf(fmt, v);
> + va_end(v);
> + }
> +}
> +
> +static uint64_t vtpm_get_ticks(void)
> +{
> + static uint64_t old_t = 0;
> + uint64_t new_t, res_t;
> + struct timeval tv;
> + gettimeofday(&tv, NULL);
> + new_t = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
> + res_t = (old_t > 0) ? new_t - old_t : 0;
> + old_t = new_t;
> + return res_t;
> +}
> +
> +
> +static int tpm_entropy_source(void* dummy, unsigned char* data, size_t len, size_t* olen) {
> + UINT32 sz = len;
> + TPM_RESULT rc = VTPM_GetRandom(tpmfront_dev, data, &sz);
> + *olen = sz;
> + return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
> +}
> +
> +int init_random(void) {
> + /* Initialize the rng */
> + entropy_init(&entropy);
> + entropy_add_source(&entropy, tpm_entropy_source, NULL, 0);
> + entropy_gather(&entropy);
> + ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, NULL, 0);
> + ctr_drbg_set_prediction_resistance( &ctr_drbg, CTR_DRBG_PR_OFF );
> +
> + return 0;
> +}
> +
> +int check_ordinal(tpmcmd_t* tpmcmd) {
> + TPM_COMMAND_CODE ord;
> + UINT32 len = 4;
> + BYTE* ptr;
> + unsigned int i;
> +
> + if(tpmcmd->req_len < 10) {
> + return true;
> + }
> +
> + ptr = tpmcmd->req + 6;
> + tpm_unmarshal_UINT32(&ptr, &len, &ord);
> +
> + for(i = 0; i < n_badords; ++i) {
> + if(ord == badords[i]) {
> + error("Disabled command ordinal (%" PRIu32") requested!\n");
> + return false;
> + }
> + }
> + return true;
> +}
> +
> +static void main_loop(void) {
> + tpmcmd_t* tpmcmd = NULL;
> + domid_t domid; /* Domid of frontend */
> + unsigned int handle; /* handle of frontend */
> + int res = -1;
> +
> + info("VTPM Initializing\n");
> +
> + /* Set required tpm config args */
> + opt_args.tpmconf |= TPM_CONF_STRONG_PERSISTENCE;
> + opt_args.tpmconf &= ~TPM_CONF_USE_INTERNAL_PRNG;
> + opt_args.tpmconf |= TPM_CONF_GENERATE_EK;
> + opt_args.tpmconf |= TPM_CONF_GENERATE_SEED_DAA;
> +
> + /* Initialize the emulator */
> + tpm_emulator_init(opt_args.startup, opt_args.tpmconf);
> +
> + /* Initialize any requested PCRs with hardware TPM values */
> + if(vtpm_initialize_hw_pcrs(tpmfront_dev, opt_args.hwinitpcrs) != TPM_SUCCESS) {
> + error("Failed to initialize PCRs with hardware TPM values");
> + goto abort_postpcrs;
> + }
> +
> + /* Wait for the frontend domain to connect */
> + info("Waiting for frontend domain to connect..");
> + if(tpmback_wait_for_frontend_connect(&domid, &handle) == 0) {
> + info("VTPM attached to Frontend %u/%u", (unsigned int) domid, handle);
> + } else {
> + error("Unable to attach to a frontend");
> + }
> +
> + tpmcmd = tpmback_req(domid, handle);
> + while(tpmcmd) {
> + /* Handle the request */
> + if(tpmcmd->req_len) {
> + tpmcmd->resp = NULL;
> + tpmcmd->resp_len = 0;
> +
> + /* First check for disabled ordinals */
> + if(!check_ordinal(tpmcmd)) {
> + create_error_response(tpmcmd, TPM_BAD_ORDINAL);
> + }
> + /* If not disabled, do the command */
> + else {
> + if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
> + error("tpm_handle_command() failed");
> + create_error_response(tpmcmd, TPM_FAIL);
> + }
> + }
> + }
> +
> + /* Send the response */
> + tpmback_resp(tpmcmd);
> +
> + /* Wait for the next request */
> + tpmcmd = tpmback_req(domid, handle);
> +
> + }
> +
> +abort_postpcrs:
> + info("VTPM Shutting down\n");
> +
> + tpm_emulator_shutdown();
> +}
> +
> +int parse_cmd_line(int argc, char** argv)
> +{
> + char sval[25];
> + char* logstr = NULL;
> + /* Parse the command strings */
> + for(unsigned int i = 1; i < argc; ++i) {
> + if (sscanf(argv[i], "loglevel=%25s", sval) == 1){
> + if (!strcmp(sval, "debug")) {
> + opt_args.loglevel = TPM_LOG_DEBUG;
> + logstr = "debug";
> + }
> + else if (!strcmp(sval, "info")) {
> + logstr = "info";
> + opt_args.loglevel = TPM_LOG_INFO;
> + }
> + else if (!strcmp(sval, "error")) {
> + logstr = "error";
> + opt_args.loglevel = TPM_LOG_ERROR;
> + }
> + }
> + else if (!strcmp(argv[i], "clear")) {
> + opt_args.startup = ST_CLEAR;
> + }
> + else if (!strcmp(argv[i], "save")) {
> + opt_args.startup = ST_SAVE;
> + }
> + else if (!strcmp(argv[i], "deactivated")) {
> + opt_args.startup = ST_DEACTIVATED;
> + }
> + else if (!strncmp(argv[i], "maintcmds=", 10)) {
> + if(!strcmp(argv[i] + 10, "1")) {
> + opt_args.enable_maint_cmds = true;
> + } else if(!strcmp(argv[i] + 10, "0")) {
> + opt_args.enable_maint_cmds = false;
> + }
> + }
> + else if(!strncmp(argv[i], "hwinitpcr=", 10)) {
> + char *pch = argv[i] + 10;
> + unsigned int v1, v2;
> + pch = strtok(pch, ",");
> + while(pch != NULL) {
> + if(!strcmp(pch, "all")) {
> + //Set all
> + opt_args.hwinitpcrs = VTPM_PCRALL;
> + } else if(!strcmp(pch, "none")) {
> + //Set none
> + opt_args.hwinitpcrs = VTPM_PCRNONE;
> + } else if(sscanf(pch, "%u", &v1) == 1) {
> + //Set one
> + if(v1 >= TPM_NUM_PCR) {
> + error("hwinitpcr error: Invalid PCR index %u", v1);
> + return -1;
> + }
> + opt_args.hwinitpcrs |= (1 << v1);
> + } else if(sscanf(pch, "%u-%u", &v1, &v2) == 2) {
> + //Set range
> + if(v1 >= TPM_NUM_PCR) {
> + error("hwinitpcr error: Invalid PCR index %u", v1);
> + return -1;
> + }
> + if(v2 >= TPM_NUM_PCR) {
> + error("hwinitpcr error: Invalid PCR index %u", v1);
> + return -1;
> + }
> + if(v2 < v1) {
> + unsigned tp = v1;
> + v1 = v2;
> + v2 = tp;
> + }
> + for(unsigned int i = v1; i <= v2; ++i) {
> + opt_args.hwinitpcrs |= (1 << i);
> + }
> + } else {
> + error("hwintipcr error: Invalid PCR specification : %s", pch);
> + return -1;
> + }
> + pch = strtok(NULL, ",");
> + }
> + }
> + else {
> + error("Invalid command line option `%s'", argv[i]);
> + }
> +
> + }
> +
> + /* Check Errors and print results */
> + switch(opt_args.startup) {
> + case ST_CLEAR:
> + info("Startup mode is `clear'");
> + break;
> + case ST_SAVE:
> + info("Startup mode is `save'");
> + break;
> + case ST_DEACTIVATED:
> + info("Startup mode is `deactivated'");
> + break;
> + default:
> + error("Invalid startup mode %d", opt_args.startup);
> + return -1;
> + }
> +
> + if(opt_args.hwinitpcrs & (VTPM_PCRALL))
> + {
> + char pcrstr[1024];
> + char* ptr = pcrstr;
> +
> + pcrstr[0] = '\0';
> + info("The following PCRs will be initialized with values from the hardware TPM:");
> + for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
> + if(opt_args.hwinitpcrs & (1 << i)) {
> + ptr += sprintf(ptr, "%u, ", i);
> + }
> + }
> + /* get rid of the last comma if any numbers were printed */
> + *(ptr -2) = '\0';
> +
> + info("\t%s", pcrstr);
> + } else {
> + info("All PCRs initialized to default values");
> + }
> +
> + if(!opt_args.enable_maint_cmds) {
> + info("TPM Maintenance Commands disabled");
> + badords[n_badords++] = TPM_ORD_CreateMaintenanceArchive;
> + badords[n_badords++] = TPM_ORD_LoadMaintenanceArchive;
> + badords[n_badords++] = TPM_ORD_KillMaintenanceFeature;
> + badords[n_badords++] = TPM_ORD_LoadManuMaintPub;
> + badords[n_badords++] = TPM_ORD_ReadManuMaintPub;
> + } else {
> + info("TPM Maintenance Commands enabled");
> + }
> +
> + info("Log level set to %s", logstr);
> +
> + return 0;
> +}
> +
> +void cleanup_opt_args(void) {
> +}
> +
> +int main(int argc, char **argv)
> +{
> + //FIXME: initializing blkfront without this sleep causes the domain to crash on boot
> + sleep(2);
> +
> + /* Setup extern function pointers */
> + tpm_extern_init = vtpm_extern_init_fake;
> + tpm_extern_release = vtpm_extern_release_fake;
> + tpm_malloc = malloc;
> + tpm_free = free;
> + tpm_log = vtpm_log;
> + tpm_get_ticks = vtpm_get_ticks;
> + tpm_get_extern_random_bytes = vtpm_get_extern_random_bytes;
> + tpm_write_to_storage = vtpm_write_to_file;
> + tpm_read_from_storage = vtpm_read_from_file;
> +
> + info("starting TPM Emulator (1.2.%d.%d-%d)", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
> + if(parse_cmd_line(argc, argv)) {
> + error("Error parsing commandline\n");
> + return -1;
> + }
> +
> + /* Initialize devices */
> + init_tpmback();
> + if((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
> + error("Unable to initialize tpmfront device");
> + goto abort_posttpmfront;
> + }
> +
> + /* Seed the RNG with entropy from hardware TPM */
> + if(init_random()) {
> + error("Unable to initialize RNG");
> + goto abort_postrng;
> + }
> +
> + /* Initialize blkfront device */
> + if(init_vtpmblk(tpmfront_dev)) {
> + error("Unable to initialize Blkfront persistent storage");
> + goto abort_postvtpmblk;
> + }
> +
> + /* Run main loop */
> + main_loop();
> +
> + /* Shutdown blkfront */
> + shutdown_vtpmblk();
> +abort_postvtpmblk:
> +abort_postrng:
> +
> + /* Close devices */
> + shutdown_tpmfront(tpmfront_dev);
> +abort_posttpmfront:
> + shutdown_tpmback();
> +
> + cleanup_opt_args();
> +
> + return 0;
> +}
> diff --git a/stubdom/vtpm/vtpm.h b/stubdom/vtpm/vtpm.h
> new file mode 100644
> index 0000000..5919e44
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm.h
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#ifndef VTPM_H
> +#define VTPM_H
> +
> +#include <stdbool.h>
> +
> +/* For testing */
> +#define VERS_CMD "\x00\xC1\x00\x00\x00\x16\x00\x00\x00\x65\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x01\x03"
> +#define VERS_CMD_LEN 22
> +
> +/* Global commandline options */
> +struct Opt_args {
> + enum StartUp {
> + ST_CLEAR = 1,
> + ST_SAVE = 2,
> + ST_DEACTIVATED = 3
> + } startup;
> + unsigned long hwinitpcrs;
> + int loglevel;
> + uint32_t tpmconf;
> + bool enable_maint_cmds;
> +};
> +extern struct Opt_args opt_args;
> +
> +#endif
> diff --git a/stubdom/vtpm/vtpm_cmd.c b/stubdom/vtpm/vtpm_cmd.c
> new file mode 100644
> index 0000000..7eae98b
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_cmd.c
> @@ -0,0 +1,256 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#include <types.h>
> +#include <xen/xen.h>
> +#include <mm.h>
> +#include <gnttab.h>
> +#include "tpm/tpm_marshalling.h"
> +#include "vtpm_manager.h"
> +#include "vtpm_cmd.h"
> +#include <tpmback.h>
> +
> +#define TRYFAILGOTO(C) \
> + if((C)) { \
> + status = TPM_FAIL; \
> + goto abort_egress; \
> + }
> +#define TRYFAILGOTOMSG(C, msg) \
> + if((C)) { \
> + status = TPM_FAIL; \
> + error(msg); \
> + goto abort_egress; \
> + }
> +#define CHECKSTATUSGOTO(ret, fname) \
> + if((ret) != TPM_SUCCESS) { \
> + error("%s failed with error code (%lu)", fname, (unsigned long) ret); \
> + status = ord; \
> + goto abort_egress; \
> + }
> +
> +#define ERR_MALFORMED "Malformed response from backend"
> +#define ERR_TPMFRONT "Error sending command through frontend device"
> +
> +struct shpage {
> + void* page;
> + grant_ref_t grantref;
> +};
> +
> +typedef struct shpage shpage_t;
> +
> +static inline int pack_header(uint8_t** bptr, UINT32* len, TPM_TAG tag, UINT32 size, TPM_COMMAND_CODE ord)
> +{
> + return *bptr == NULL ||
> + tpm_marshal_UINT16(bptr, len, tag) ||
> + tpm_marshal_UINT32(bptr, len, size) ||
> + tpm_marshal_UINT32(bptr, len, ord);
> +}
> +
> +static inline int unpack_header(uint8_t** bptr, UINT32* len, TPM_TAG* tag, UINT32* size, TPM_COMMAND_CODE* ord)
> +{
> + return *bptr == NULL ||
> + tpm_unmarshal_UINT16(bptr, len, tag) ||
> + tpm_unmarshal_UINT32(bptr, len, size) ||
> + tpm_unmarshal_UINT32(bptr, len, ord);
> +}
> +
> +int create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode)
> +{
> + TPM_TAG tag;
> + UINT32 len = tpmcmd->req_len;
> + uint8_t* respptr;
> + uint8_t* cmdptr = tpmcmd->req;
> +
> + if(!tpm_unmarshal_UINT16(&cmdptr, &len, &tag)) {
> + switch (tag) {
> + case TPM_TAG_RQU_COMMAND:
> + tag = TPM_TAG_RSP_COMMAND;
> + break;
> + case TPM_TAG_RQU_AUTH1_COMMAND:
> + tag = TPM_TAG_RQU_AUTH2_COMMAND;
> + break;
> + case TPM_TAG_RQU_AUTH2_COMMAND:
> + tag = TPM_TAG_RQU_AUTH2_COMMAND;
> + break;
> + }
> + } else {
> + tag = TPM_TAG_RSP_COMMAND;
> + }
> +
> + tpmcmd->resp_len = len = 10;
> + tpmcmd->resp = respptr = tpm_malloc(tpmcmd->resp_len);
> +
> + return pack_header(&respptr, &len, tag, len, errorcode);
> +}
> +
> +TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes, UINT32 *numbytes) {
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t* cmdbuf, *resp, *bptr;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + /*Ask the real tpm for random bytes for the seed */
> + TPM_TAG tag = TPM_TAG_RQU_COMMAND;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = TPM_ORD_GetRandom;
> + len = size = sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE) + sizeof(UINT32);
> +
> + /*Create the raw tpm command */
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> + TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, *numbytes));
> +
> + /* Send cmd, wait for response */
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen),
> + ERR_TPMFRONT);
> +
> + bptr = resp; len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
> +
> + //Check return status of command
> + CHECKSTATUSGOTO(ord, "TPM_GetRandom()");
> +
> + // Get the number of random bytes in the response
> + TRYFAILGOTOMSG(tpm_unmarshal_UINT32(&bptr, &len, &size), ERR_MALFORMED);
> + *numbytes = size;
> +
> + //Get the random bytes out, tpm may give us less bytes than what we wanrt
> + TRYFAILGOTOMSG(tpm_unmarshal_BYTE_ARRAY(&bptr, &len, bytes, *numbytes), ERR_MALFORMED);
> +
> + goto egress;
> +abort_egress:
> +egress:
> + free(cmdbuf);
> + return status;
> +
> +}
> +
> +TPM_RESULT VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t* data_length)
> +{
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t* bptr, *resp;
> + uint8_t* cmdbuf = NULL;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + TPM_TAG tag = VTPM_TAG_REQ;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = VTPM_ORD_LOADHASHKEY;
> +
> + /*Create the command*/
> + len = size = VTPM_COMMAND_HEADER_SIZE;
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> +
> + /* Send the command to vtpm_manager */
> + info("Requesting Encryption key from backend");
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
> +
> + /* Unpack response header */
> + bptr = resp;
> + len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
> +
> + /* Check return code */
> + CHECKSTATUSGOTO(ord, "VTPM_LoadHashKey()");
> +
> + /* Get the size of the key */
> + *data_length = size - VTPM_COMMAND_HEADER_SIZE;
> +
> + /* Copy the key bits */
> + *data = malloc(*data_length);
> + memcpy(*data, bptr, *data_length);
> +
> + goto egress;
> +abort_egress:
> + error("VTPM_LoadHashKey failed");
> +egress:
> + free(cmdbuf);
> + return status;
> +}
> +
> +TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length)
> +{
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t* bptr, *resp;
> + uint8_t* cmdbuf = NULL;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + TPM_TAG tag = VTPM_TAG_REQ;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = VTPM_ORD_SAVEHASHKEY;
> +
> + /*Create the command*/
> + len = size = VTPM_COMMAND_HEADER_SIZE + data_length;
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> + memcpy(bptr, data, data_length);
> + bptr += data_length;
> +
> + /* Send the command to vtpm_manager */
> + info("Sending encryption key to backend");
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
> +
> + /* Unpack response header */
> + bptr = resp;
> + len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
> +
> + /* Check return code */
> + CHECKSTATUSGOTO(ord, "VTPM_SaveHashKey()");
> +
> + goto egress;
> +abort_egress:
> + error("VTPM_SaveHashKey failed");
> +egress:
> + free(cmdbuf);
> + return status;
> +}
> +
> +TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex, BYTE* outDigest)
> +{
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t *cmdbuf, *resp, *bptr;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + /*Just send a TPM_PCRRead Command to the HW tpm */
> + TPM_TAG tag = TPM_TAG_RQU_COMMAND;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = TPM_ORD_PCRRead;
> + len = size = sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE) + sizeof(UINT32);
> +
> + /*Create the raw tpm cmd */
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> + TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, pcrIndex));
> +
> + /*Send Cmd wait for response */
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
> +
> + bptr = resp; len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
> +
> + //Check return status of command
> + CHECKSTATUSGOTO(ord, "TPM_PCRRead");
> +
> + //Get the ptr value
> + memcpy(outDigest, bptr, sizeof(TPM_PCRVALUE));
> +
> + goto egress;
> +abort_egress:
> +egress:
> + free(cmdbuf);
> + return status;
> +
> +}
> diff --git a/stubdom/vtpm/vtpm_cmd.h b/stubdom/vtpm/vtpm_cmd.h
> new file mode 100644
> index 0000000..b0bfa22
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_cmd.h
> @@ -0,0 +1,31 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#ifndef MANAGER_H
> +#define MANAGER_H
> +
> +#include <tpmfront.h>
> +#include <tpmback.h>
> +#include "tpm/tpm_structures.h"
> +
> +/* Create a command response error header */
> +int create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode);
> +/* Request random bytes from hardware tpm, returns 0 on success */
> +TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes, UINT32* numbytes);
> +/* Retreive 256 bit AES encryption key from manager */
> +TPM_RESULT VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t* data_length);
> +/* Manager securely saves our 256 bit AES encryption key */
> +TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length);
> +/* Send a TPM_PCRRead command passthrough the manager to the hw tpm */
> +TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex, BYTE* outDigest);
> +
> +#endif
> diff --git a/stubdom/vtpm/vtpm_pcrs.c b/stubdom/vtpm/vtpm_pcrs.c
> new file mode 100644
> index 0000000..22a6cef
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_pcrs.c
> @@ -0,0 +1,43 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#include "vtpm_pcrs.h"
> +#include "vtpm_cmd.h"
> +#include "tpm/tpm_data.h"
> +
> +#define PCR_VALUE tpmData.permanent.data.pcrValue
> +
> +static int write_pcr_direct(unsigned int pcrIndex, uint8_t* val) {
> + if(pcrIndex > TPM_NUM_PCR) {
> + return TPM_BADINDEX;
> + }
> + memcpy(&PCR_VALUE[pcrIndex], val, sizeof(TPM_PCRVALUE));
> + return TPM_SUCCESS;
> +}
> +
> +TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev, unsigned long pcrs)
> +{
> + TPM_RESULT rc = TPM_SUCCESS;
> + uint8_t digest[sizeof(TPM_PCRVALUE)];
> +
> + for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
> + if(pcrs & 1 << i) {
> + if((rc = VTPM_PCRRead(tpmfront_dev, i, digest)) != TPM_SUCCESS) {
> + error("TPM_PCRRead failed with error : %d", rc);
> + return rc;
> + }
> + write_pcr_direct(i, digest);
> + }
> + }
> +
> + return rc;
> +}
> diff --git a/stubdom/vtpm/vtpm_pcrs.h b/stubdom/vtpm/vtpm_pcrs.h
> new file mode 100644
> index 0000000..11835f9
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_pcrs.h
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#ifndef VTPM_PCRS_H
> +#define VTPM_PCRS_H
> +
> +#include "tpm/tpm_structures.h"
> +
> +#define VTPM_PCR0 1
> +#define VTPM_PCR1 1 << 1
> +#define VTPM_PCR2 1 << 2
> +#define VTPM_PCR3 1 << 3
> +#define VTPM_PCR4 1 << 4
> +#define VTPM_PCR5 1 << 5
> +#define VTPM_PCR6 1 << 6
> +#define VTPM_PCR7 1 << 7
> +#define VTPM_PCR8 1 << 8
> +#define VTPM_PCR9 1 << 9
> +#define VTPM_PCR10 1 << 10
> +#define VTPM_PCR11 1 << 11
> +#define VTPM_PCR12 1 << 12
> +#define VTPM_PCR13 1 << 13
> +#define VTPM_PCR14 1 << 14
> +#define VTPM_PCR15 1 << 15
> +#define VTPM_PCR16 1 << 16
> +#define VTPM_PCR17 1 << 17
> +#define VTPM_PCR18 1 << 18
> +#define VTPM_PCR19 1 << 19
> +#define VTPM_PCR20 1 << 20
> +#define VTPM_PCR21 1 << 21
> +#define VTPM_PCR22 1 << 22
> +#define VTPM_PCR23 1 << 23
> +
> +#define VTPM_PCRALL (1 << TPM_NUM_PCR) - 1
> +#define VTPM_PCRNONE 0
> +
> +#define VTPM_NUMPCRS 24
> +
> +struct tpmfront_dev;
> +
> +TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev, unsigned long pcrs);
> +
> +
> +#endif
> diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c
> new file mode 100644
> index 0000000..b343bd8
> --- /dev/null
> +++ b/stubdom/vtpm/vtpmblk.c
> @@ -0,0 +1,307 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#include <mini-os/byteorder.h>
> +#include "vtpmblk.h"
> +#include "tpm/tpm_marshalling.h"
> +#include "vtpm_cmd.h"
> +#include "polarssl/aes.h"
> +#include "polarssl/sha1.h"
> +#include <blkfront.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +
> +/*Encryption key and block sizes */
> +#define BLKSZ 16
> +
> +static struct blkfront_dev* blkdev = NULL;
> +static int blkfront_fd = -1;
> +
> +int init_vtpmblk(struct tpmfront_dev* tpmfront_dev)
> +{
> + struct blkfront_info blkinfo;
> + info("Initializing persistent NVM storage\n");
> +
> + if((blkdev = init_blkfront(NULL, &blkinfo)) == NULL) {
> + error("BLKIO: ERROR Unable to initialize blkfront");
> + return -1;
> + }
> + if (blkinfo.info & VDISK_READONLY || blkinfo.mode != O_RDWR) {
> + error("BLKIO: ERROR block device is read only!");
> + goto error;
> + }
> + if((blkfront_fd = blkfront_open(blkdev)) == -1) {
> + error("Unable to open blkfront file descriptor!");
> + goto error;
> + }
> +
> + return 0;
> +error:
> + shutdown_blkfront(blkdev);
> + blkdev = NULL;
> + return -1;
> +}
> +
> +void shutdown_vtpmblk(void)
> +{
> + close(blkfront_fd);
> + blkfront_fd = -1;
> + blkdev = NULL;
> +}
> +
> +int write_vtpmblk_raw(uint8_t *data, size_t data_length)
> +{
> + int rc;
> + uint32_t lenbuf;
> + debug("Begin Write data=%p len=%u", data, data_length);
> +
> + lenbuf = cpu_to_be32((uint32_t)data_length);
> +
> + lseek(blkfront_fd, 0, SEEK_SET);
> + if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
> + error("write(length) failed! error was %s", strerror(errno));
> + return -1;
> + }
> + if((rc = write(blkfront_fd, data, data_length)) != data_length) {
> + error("write(data) failed! error was %s", strerror(errno));
> + return -1;
> + }
> +
> + info("Wrote %u bytes to NVM persistent storage", data_length);
> +
> + return 0;
> +}
> +
> +int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
> +{
> + int rc;
> + uint32_t lenbuf;
> +
> + lseek(blkfront_fd, 0, SEEK_SET);
> + if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
> + error("read(length) failed! error was %s", strerror(errno));
> + return -1;
> + }
> + *data_length = (size_t) cpu_to_be32(lenbuf);
> + if(*data_length == 0) {
> + error("read 0 data_length for NVM");
> + return -1;
> + }
> +
> + *data = tpm_malloc(*data_length);
> + if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
> + error("read(data) failed! error was %s", strerror(errno));
> + return -1;
> + }
> +
> + info("Read %u bytes from NVM persistent storage", *data_length);
> + return 0;
> +}
> +
> +int encrypt_vtpmblk(uint8_t* clear, size_t clear_len, uint8_t** cipher, size_t* cipher_len, uint8_t* symkey)
> +{
> + int rc = 0;
> + uint8_t iv[BLKSZ];
> + aes_context aes_ctx;
> + UINT32 temp;
> + int mod;
> +
> + uint8_t* clbuf = NULL;
> +
> + uint8_t* ivptr;
> + int ivlen;
> +
> + uint8_t* cptr; //Cipher block pointer
> + int clen; //Cipher block length
> +
> + /*Create a new 256 bit encryption key */
> + if(symkey == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> + tpm_get_extern_random_bytes(symkey, NVMKEYSZ);
> +
> + /*Setup initialization vector - random bits and then 4 bytes clear text size at the end*/
> + temp = sizeof(UINT32);
> + ivlen = BLKSZ - temp;
> + tpm_get_extern_random_bytes(iv, ivlen);
> + ivptr = iv + ivlen;
> + tpm_marshal_UINT32(&ivptr, &temp, (UINT32) clear_len);
> +
> + /*The clear text needs to be padded out to a multiple of BLKSZ */
> + mod = clear_len % BLKSZ;
> + clen = mod ? clear_len + BLKSZ - mod : clear_len;
> + clbuf = malloc(clen);
> + if (clbuf == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> + memcpy(clbuf, clear, clear_len);
> + /* zero out the padding bits - FIXME: better / more secure way to handle these? */
> + if(clen - clear_len) {
> + memset(clbuf + clear_len, 0, clen - clear_len);
> + }
> +
> + /* Setup the ciphertext buffer */
> + *cipher_len = BLKSZ + clen; /*iv + ciphertext */
> + cptr = *cipher = malloc(*cipher_len);
> + if (*cipher == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> +
> + /* Copy the IV to cipher text blob*/
> + memcpy(cptr, iv, BLKSZ);
> + cptr += BLKSZ;
> +
> + /* Setup encryption */
> + aes_setkey_enc(&aes_ctx, symkey, 256);
> +
> + /* Do encryption now */
> + aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, clen, iv, clbuf, cptr);
> +
> + goto egress;
> +abort_egress:
> +egress:
> + free(clbuf);
> + return rc;
> +}
> +int decrypt_vtpmblk(uint8_t* cipher, size_t cipher_len, uint8_t** clear, size_t* clear_len, uint8_t* symkey)
> +{
> + int rc = 0;
> + uint8_t iv[BLKSZ];
> + uint8_t* ivptr;
> + UINT32 u32, temp;
> + aes_context aes_ctx;
> +
> + uint8_t* cptr = cipher; //cipher block pointer
> + int clen = cipher_len; //cipher block length
> +
> + /* Pull out the initialization vector */
> + memcpy(iv, cipher, BLKSZ);
> + cptr += BLKSZ;
> + clen -= BLKSZ;
> +
> + /* Setup the clear text buffer */
> + if((*clear = malloc(clen)) == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> +
> + /* Get the length of clear text from last 4 bytes of iv */
> + temp = sizeof(UINT32);
> + ivptr = iv + BLKSZ - temp;
> + tpm_unmarshal_UINT32(&ivptr, &temp, &u32);
> + *clear_len = u32;
> +
> + /* Setup decryption */
> + aes_setkey_dec(&aes_ctx, symkey, 256);
> +
> + /* Do decryption now */
> + if ((clen % BLKSZ) != 0) {
> + error("Decryption Error: Cipher block size was not a multiple of %u", BLKSZ);
> + rc = -1;
> + goto abort_egress;
> + }
> + aes_crypt_cbc(&aes_ctx, AES_DECRYPT, clen, iv, cptr, *clear);
> +
> + goto egress;
> +abort_egress:
> +egress:
> + return rc;
> +}
> +
> +int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
> + int rc;
> + uint8_t* cipher = NULL;
> + size_t cipher_len = 0;
> + uint8_t hashkey[HASHKEYSZ];
> + uint8_t* symkey = hashkey + HASHSZ;
> +
> + /* Encrypt the data */
> + if((rc = encrypt_vtpmblk(data, data_length, &cipher, &cipher_len, symkey))) {
> + goto abort_egress;
> + }
> + /* Write to disk */
> + if((rc = write_vtpmblk_raw(cipher, cipher_len))) {
> + goto abort_egress;
> + }
> + /* Get sha1 hash of data */
> + sha1(cipher, cipher_len, hashkey);
> +
> + /* Send hash and key to manager */
> + if((rc = VTPM_SaveHashKey(tpmfront_dev, hashkey, HASHKEYSZ)) != TPM_SUCCESS) {
> + goto abort_egress;
> + }
> + goto egress;
> +abort_egress:
> +egress:
> + free(cipher);
> + return rc;
> +}
> +
> +int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data_length) {
> + int rc;
> + uint8_t* cipher = NULL;
> + size_t cipher_len = 0;
> + size_t keysize;
> + uint8_t* hashkey = NULL;
> + uint8_t hash[HASHSZ];
> + uint8_t* symkey;
> +
> + /* Retreive the hash and the key from the manager */
> + if((rc = VTPM_LoadHashKey(tpmfront_dev, &hashkey, &keysize)) != TPM_SUCCESS) {
> + goto abort_egress;
> + }
> + if(keysize != HASHKEYSZ) {
> + error("Manager returned a hashkey of invalid size! expected %d, actual %d", NVMKEYSZ, keysize);
> + rc = -1;
> + goto abort_egress;
> + }
> + symkey = hashkey + HASHSZ;
> +
> + /* Read from disk now */
> + if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
> + goto abort_egress;
> + }
> +
> + /* Compute the hash of the cipher text and compare */
> + sha1(cipher, cipher_len, hash);
> + if(memcmp(hash, hashkey, HASHSZ)) {
> + int i;
> + error("NVM Storage Checksum failed!");
> + printf("Expected: ");
> + for(i = 0; i < HASHSZ; ++i) {
> + printf("%02hhX ", hashkey[i]);
> + }
> + printf("\n");
> + printf("Actual: ");
> + for(i = 0; i < HASHSZ; ++i) {
> + printf("%02hhX ", hash[i]);
> + }
> + printf("\n");
> + rc = -1;
> + goto abort_egress;
> + }
> +
> + /* Decrypt the blob */
> + if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
> + goto abort_egress;
> + }
> + goto egress;
> +abort_egress:
> +egress:
> + free(cipher);
> + free(hashkey);
> + return rc;
> +}
> diff --git a/stubdom/vtpm/vtpmblk.h b/stubdom/vtpm/vtpmblk.h
> new file mode 100644
> index 0000000..282ce6a
> --- /dev/null
> +++ b/stubdom/vtpm/vtpmblk.h
> @@ -0,0 +1,31 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
> + * SOFTWARE.
> + */
> +
> +#ifndef NVM_H
> +#define NVM_H
> +#include <mini-os/types.h>
> +#include <xen/xen.h>
> +#include <tpmfront.h>
> +
> +#define NVMKEYSZ 32
> +#define HASHSZ 20
> +#define HASHKEYSZ (NVMKEYSZ + HASHSZ)
> +
> +int init_vtpmblk(struct tpmfront_dev* tpmfront_dev);
> +void shutdown_vtpmblk(void);
> +
> +/* Encrypts and writes data to blk device */
> +int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t *data, size_t data_length);
> +/* Reads, Decrypts, and returns data from blk device */
> +int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t **data, size_t *data_length);
> +
> +#endif
> --
> 1.7.10.4
>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Re: [VTPM v7 1/8] add vtpm-stubdom code [ In reply to ]
Ok, just for reference for now, Nothing has changed with the vtpm patches, just the autoconf stuff is evolving.

-----Original Message-----
From: Ian Campbell [mailto:Ian.Campbell@citrix.com]
Sent: Thursday, December 13, 2012 6:48 AM
To: Fioravante, Matthew E.
Cc: xen-devel@lists.xen.org; Ian Jackson
Subject: Re: [VTPM v7 1/8] add vtpm-stubdom code

For future reference please could you include an indication of what changed in a new posting of a series, either in the 0/N mail (which is useful to include as an intro in any case) or in the individual changelogs.

On Thu, 2012-12-06 at 18:19 +0000, Matthew Fioravante wrote:
> Add the code base for vtpm-stubdom to the stubdom heirarchy. Makefile
> changes in later patch.
>
> Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> ---
> stubdom/vtpm/Makefile | 37 +++++
> stubdom/vtpm/minios.cfg | 14 ++
> stubdom/vtpm/vtpm.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
> stubdom/vtpm/vtpm.h | 36 +++++
> stubdom/vtpm/vtpm_cmd.c | 256 +++++++++++++++++++++++++++++
> stubdom/vtpm/vtpm_cmd.h | 31 ++++
> stubdom/vtpm/vtpm_pcrs.c | 43 +++++
> stubdom/vtpm/vtpm_pcrs.h | 53 ++++++
> stubdom/vtpm/vtpmblk.c | 307 +++++++++++++++++++++++++++++++++++
> stubdom/vtpm/vtpmblk.h | 31 ++++
> 10 files changed, 1212 insertions(+)
> create mode 100644 stubdom/vtpm/Makefile create mode 100644
> stubdom/vtpm/minios.cfg create mode 100644 stubdom/vtpm/vtpm.c
> create mode 100644 stubdom/vtpm/vtpm.h create mode 100644
> stubdom/vtpm/vtpm_cmd.c create mode 100644 stubdom/vtpm/vtpm_cmd.h
> create mode 100644 stubdom/vtpm/vtpm_pcrs.c create mode 100644
> stubdom/vtpm/vtpm_pcrs.h create mode 100644 stubdom/vtpm/vtpmblk.c
> create mode 100644 stubdom/vtpm/vtpmblk.h
>
> diff --git a/stubdom/vtpm/Makefile b/stubdom/vtpm/Makefile new file
> mode 100644 index 0000000..686c0ea
> --- /dev/null
> +++ b/stubdom/vtpm/Makefile
> @@ -0,0 +1,37 @@
> +# Copyright (c) 2010-2012 United States Government, as represented by
> +# the Secretary of Defense. All rights reserved.
> +#
> +# THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> +# ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES #
> +INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
> +# FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY #
> +DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE #
> +SOFTWARE.
> +#
> +
> +XEN_ROOT=../..
> +
> +PSSL_DIR=../polarssl-$(XEN_TARGET_ARCH)/library
> +PSSL_OBJS=aes.o sha1.o entropy.o ctr_drbg.o sha4.o
> +
> +TARGET=vtpm.a
> +OBJS=vtpm.o vtpm_cmd.o vtpmblk.o vtpm_pcrs.o
> +
> +
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/build
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/tpm
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/crypto
> +CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)
> +
> +$(TARGET): $(OBJS)
> + ar -cr $@ $(OBJS) $(TPMEMU_OBJS) $(foreach
> +obj,$(PSSL_OBJS),$(PSSL_DIR)/$(obj))
> +
> +$(OBJS): vtpm_manager.h
> +
> +vtpm_manager.h:
> + ln -s ../vtpmmgr/vtpm_manager.h vtpm_manager.h
> +
> +clean:
> + -rm $(TARGET) $(OBJS) vtpm_manager.h
> +
> +.PHONY: clean
> diff --git a/stubdom/vtpm/minios.cfg b/stubdom/vtpm/minios.cfg new
> file mode 100644 index 0000000..31652ee
> --- /dev/null
> +++ b/stubdom/vtpm/minios.cfg
> @@ -0,0 +1,14 @@
> +CONFIG_TPMFRONT=y
> +CONFIG_TPM_TIS=n
> +CONFIG_TPMBACK=y
> +CONFIG_START_NETWORK=n
> +CONFIG_TEST=n
> +CONFIG_PCIFRONT=n
> +CONFIG_BLKFRONT=y
> +CONFIG_NETFRONT=n
> +CONFIG_FBFRONT=n
> +CONFIG_KBDFRONT=n
> +CONFIG_CONSFRONT=n
> +CONFIG_XENBUS=y
> +CONFIG_LWIP=n
> +CONFIG_XC=n
> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c new file mode
> 100644 index 0000000..71aef78
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm.c
> @@ -0,0 +1,404 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <syslog.h>
> +#include <stdbool.h>
> +#include <errno.h>
> +#include <sys/time.h>
> +#include <xen/xen.h>
> +#include <tpmback.h>
> +#include <tpmfront.h>
> +
> +#include <polarssl/entropy.h>
> +#include <polarssl/ctr_drbg.h>
> +
> +#include "tpm/tpm_emulator_extern.h"
> +#include "tpm/tpm_marshalling.h"
> +#include "vtpm.h"
> +#include "vtpm_cmd.h"
> +#include "vtpm_pcrs.h"
> +#include "vtpmblk.h"
> +
> +#define TPM_LOG_INFO LOG_INFO
> +#define TPM_LOG_ERROR LOG_ERR
> +#define TPM_LOG_DEBUG LOG_DEBUG
> +
> +/* Global commandline options - default values */ struct Opt_args
> +opt_args = {
> + .startup = ST_CLEAR,
> + .loglevel = TPM_LOG_INFO,
> + .hwinitpcrs = VTPM_PCRNONE,
> + .tpmconf = 0,
> + .enable_maint_cmds = false,
> +};
> +
> +static uint32_t badords[32];
> +static unsigned int n_badords = 0;
> +
> +entropy_context entropy;
> +ctr_drbg_context ctr_drbg;
> +
> +struct tpmfront_dev* tpmfront_dev;
> +
> +void vtpm_get_extern_random_bytes(void *buf, size_t nbytes) {
> + ctr_drbg_random(&ctr_drbg, buf, nbytes); }
> +
> +int vtpm_read_from_file(uint8_t **data, size_t *data_length) {
> + return read_vtpmblk(tpmfront_dev, data, data_length); }
> +
> +int vtpm_write_to_file(uint8_t *data, size_t data_length) {
> + return write_vtpmblk(tpmfront_dev, data, data_length); }
> +
> +int vtpm_extern_init_fake(void) {
> + return 0;
> +}
> +
> +void vtpm_extern_release_fake(void) { }
> +
> +
> +void vtpm_log(int priority, const char *fmt, ...) {
> + if(opt_args.loglevel >= priority) {
> + va_list v;
> + va_start(v, fmt);
> + vprintf(fmt, v);
> + va_end(v);
> + }
> +}
> +
> +static uint64_t vtpm_get_ticks(void)
> +{
> + static uint64_t old_t = 0;
> + uint64_t new_t, res_t;
> + struct timeval tv;
> + gettimeofday(&tv, NULL);
> + new_t = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
> + res_t = (old_t > 0) ? new_t - old_t : 0;
> + old_t = new_t;
> + return res_t;
> +}
> +
> +
> +static int tpm_entropy_source(void* dummy, unsigned char* data, size_t len, size_t* olen) {
> + UINT32 sz = len;
> + TPM_RESULT rc = VTPM_GetRandom(tpmfront_dev, data, &sz);
> + *olen = sz;
> + return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
> +}
> +
> +int init_random(void) {
> + /* Initialize the rng */
> + entropy_init(&entropy);
> + entropy_add_source(&entropy, tpm_entropy_source, NULL, 0);
> + entropy_gather(&entropy);
> + ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, NULL, 0);
> + ctr_drbg_set_prediction_resistance( &ctr_drbg, CTR_DRBG_PR_OFF );
> +
> + return 0;
> +}
> +
> +int check_ordinal(tpmcmd_t* tpmcmd) {
> + TPM_COMMAND_CODE ord;
> + UINT32 len = 4;
> + BYTE* ptr;
> + unsigned int i;
> +
> + if(tpmcmd->req_len < 10) {
> + return true;
> + }
> +
> + ptr = tpmcmd->req + 6;
> + tpm_unmarshal_UINT32(&ptr, &len, &ord);
> +
> + for(i = 0; i < n_badords; ++i) {
> + if(ord == badords[i]) {
> + error("Disabled command ordinal (%" PRIu32") requested!\n");
> + return false;
> + }
> + }
> + return true;
> +}
> +
> +static void main_loop(void) {
> + tpmcmd_t* tpmcmd = NULL;
> + domid_t domid; /* Domid of frontend */
> + unsigned int handle; /* handle of frontend */
> + int res = -1;
> +
> + info("VTPM Initializing\n");
> +
> + /* Set required tpm config args */
> + opt_args.tpmconf |= TPM_CONF_STRONG_PERSISTENCE;
> + opt_args.tpmconf &= ~TPM_CONF_USE_INTERNAL_PRNG;
> + opt_args.tpmconf |= TPM_CONF_GENERATE_EK;
> + opt_args.tpmconf |= TPM_CONF_GENERATE_SEED_DAA;
> +
> + /* Initialize the emulator */
> + tpm_emulator_init(opt_args.startup, opt_args.tpmconf);
> +
> + /* Initialize any requested PCRs with hardware TPM values */
> + if(vtpm_initialize_hw_pcrs(tpmfront_dev, opt_args.hwinitpcrs) != TPM_SUCCESS) {
> + error("Failed to initialize PCRs with hardware TPM values");
> + goto abort_postpcrs;
> + }
> +
> + /* Wait for the frontend domain to connect */
> + info("Waiting for frontend domain to connect..");
> + if(tpmback_wait_for_frontend_connect(&domid, &handle) == 0) {
> + info("VTPM attached to Frontend %u/%u", (unsigned int) domid, handle);
> + } else {
> + error("Unable to attach to a frontend");
> + }
> +
> + tpmcmd = tpmback_req(domid, handle);
> + while(tpmcmd) {
> + /* Handle the request */
> + if(tpmcmd->req_len) {
> + tpmcmd->resp = NULL;
> + tpmcmd->resp_len = 0;
> +
> + /* First check for disabled ordinals */
> + if(!check_ordinal(tpmcmd)) {
> + create_error_response(tpmcmd, TPM_BAD_ORDINAL);
> + }
> + /* If not disabled, do the command */
> + else {
> + if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
> + error("tpm_handle_command() failed");
> + create_error_response(tpmcmd, TPM_FAIL);
> + }
> + }
> + }
> +
> + /* Send the response */
> + tpmback_resp(tpmcmd);
> +
> + /* Wait for the next request */
> + tpmcmd = tpmback_req(domid, handle);
> +
> + }
> +
> +abort_postpcrs:
> + info("VTPM Shutting down\n");
> +
> + tpm_emulator_shutdown();
> +}
> +
> +int parse_cmd_line(int argc, char** argv) {
> + char sval[25];
> + char* logstr = NULL;
> + /* Parse the command strings */
> + for(unsigned int i = 1; i < argc; ++i) {
> + if (sscanf(argv[i], "loglevel=%25s", sval) == 1){
> + if (!strcmp(sval, "debug")) {
> + opt_args.loglevel = TPM_LOG_DEBUG;
> + logstr = "debug";
> + }
> + else if (!strcmp(sval, "info")) {
> + logstr = "info";
> + opt_args.loglevel = TPM_LOG_INFO;
> + }
> + else if (!strcmp(sval, "error")) {
> + logstr = "error";
> + opt_args.loglevel = TPM_LOG_ERROR;
> + }
> + }
> + else if (!strcmp(argv[i], "clear")) {
> + opt_args.startup = ST_CLEAR;
> + }
> + else if (!strcmp(argv[i], "save")) {
> + opt_args.startup = ST_SAVE;
> + }
> + else if (!strcmp(argv[i], "deactivated")) {
> + opt_args.startup = ST_DEACTIVATED;
> + }
> + else if (!strncmp(argv[i], "maintcmds=", 10)) {
> + if(!strcmp(argv[i] + 10, "1")) {
> + opt_args.enable_maint_cmds = true;
> + } else if(!strcmp(argv[i] + 10, "0")) {
> + opt_args.enable_maint_cmds = false;
> + }
> + }
> + else if(!strncmp(argv[i], "hwinitpcr=", 10)) {
> + char *pch = argv[i] + 10;
> + unsigned int v1, v2;
> + pch = strtok(pch, ",");
> + while(pch != NULL) {
> + if(!strcmp(pch, "all")) {
> + //Set all
> + opt_args.hwinitpcrs = VTPM_PCRALL;
> + } else if(!strcmp(pch, "none")) {
> + //Set none
> + opt_args.hwinitpcrs = VTPM_PCRNONE;
> + } else if(sscanf(pch, "%u", &v1) == 1) {
> + //Set one
> + if(v1 >= TPM_NUM_PCR) {
> + error("hwinitpcr error: Invalid PCR index %u", v1);
> + return -1;
> + }
> + opt_args.hwinitpcrs |= (1 << v1);
> + } else if(sscanf(pch, "%u-%u", &v1, &v2) == 2) {
> + //Set range
> + if(v1 >= TPM_NUM_PCR) {
> + error("hwinitpcr error: Invalid PCR index %u", v1);
> + return -1;
> + }
> + if(v2 >= TPM_NUM_PCR) {
> + error("hwinitpcr error: Invalid PCR index %u", v1);
> + return -1;
> + }
> + if(v2 < v1) {
> + unsigned tp = v1;
> + v1 = v2;
> + v2 = tp;
> + }
> + for(unsigned int i = v1; i <= v2; ++i) {
> + opt_args.hwinitpcrs |= (1 << i);
> + }
> + } else {
> + error("hwintipcr error: Invalid PCR specification : %s", pch);
> + return -1;
> + }
> + pch = strtok(NULL, ",");
> + }
> + }
> + else {
> + error("Invalid command line option `%s'", argv[i]);
> + }
> +
> + }
> +
> + /* Check Errors and print results */
> + switch(opt_args.startup) {
> + case ST_CLEAR:
> + info("Startup mode is `clear'");
> + break;
> + case ST_SAVE:
> + info("Startup mode is `save'");
> + break;
> + case ST_DEACTIVATED:
> + info("Startup mode is `deactivated'");
> + break;
> + default:
> + error("Invalid startup mode %d", opt_args.startup);
> + return -1;
> + }
> +
> + if(opt_args.hwinitpcrs & (VTPM_PCRALL))
> + {
> + char pcrstr[1024];
> + char* ptr = pcrstr;
> +
> + pcrstr[0] = '\0';
> + info("The following PCRs will be initialized with values from the hardware TPM:");
> + for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
> + if(opt_args.hwinitpcrs & (1 << i)) {
> + ptr += sprintf(ptr, "%u, ", i);
> + }
> + }
> + /* get rid of the last comma if any numbers were printed */
> + *(ptr -2) = '\0';
> +
> + info("\t%s", pcrstr);
> + } else {
> + info("All PCRs initialized to default values");
> + }
> +
> + if(!opt_args.enable_maint_cmds) {
> + info("TPM Maintenance Commands disabled");
> + badords[n_badords++] = TPM_ORD_CreateMaintenanceArchive;
> + badords[n_badords++] = TPM_ORD_LoadMaintenanceArchive;
> + badords[n_badords++] = TPM_ORD_KillMaintenanceFeature;
> + badords[n_badords++] = TPM_ORD_LoadManuMaintPub;
> + badords[n_badords++] = TPM_ORD_ReadManuMaintPub;
> + } else {
> + info("TPM Maintenance Commands enabled");
> + }
> +
> + info("Log level set to %s", logstr);
> +
> + return 0;
> +}
> +
> +void cleanup_opt_args(void) {
> +}
> +
> +int main(int argc, char **argv)
> +{
> + //FIXME: initializing blkfront without this sleep causes the domain to crash on boot
> + sleep(2);
> +
> + /* Setup extern function pointers */
> + tpm_extern_init = vtpm_extern_init_fake;
> + tpm_extern_release = vtpm_extern_release_fake;
> + tpm_malloc = malloc;
> + tpm_free = free;
> + tpm_log = vtpm_log;
> + tpm_get_ticks = vtpm_get_ticks;
> + tpm_get_extern_random_bytes = vtpm_get_extern_random_bytes;
> + tpm_write_to_storage = vtpm_write_to_file;
> + tpm_read_from_storage = vtpm_read_from_file;
> +
> + info("starting TPM Emulator (1.2.%d.%d-%d)", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
> + if(parse_cmd_line(argc, argv)) {
> + error("Error parsing commandline\n");
> + return -1;
> + }
> +
> + /* Initialize devices */
> + init_tpmback();
> + if((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
> + error("Unable to initialize tpmfront device");
> + goto abort_posttpmfront;
> + }
> +
> + /* Seed the RNG with entropy from hardware TPM */
> + if(init_random()) {
> + error("Unable to initialize RNG");
> + goto abort_postrng;
> + }
> +
> + /* Initialize blkfront device */
> + if(init_vtpmblk(tpmfront_dev)) {
> + error("Unable to initialize Blkfront persistent storage");
> + goto abort_postvtpmblk;
> + }
> +
> + /* Run main loop */
> + main_loop();
> +
> + /* Shutdown blkfront */
> + shutdown_vtpmblk();
> +abort_postvtpmblk:
> +abort_postrng:
> +
> + /* Close devices */
> + shutdown_tpmfront(tpmfront_dev);
> +abort_posttpmfront:
> + shutdown_tpmback();
> +
> + cleanup_opt_args();
> +
> + return 0;
> +}
> diff --git a/stubdom/vtpm/vtpm.h b/stubdom/vtpm/vtpm.h new file mode
> 100644 index 0000000..5919e44
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm.h
> @@ -0,0 +1,36 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#ifndef VTPM_H
> +#define VTPM_H
> +
> +#include <stdbool.h>
> +
> +/* For testing */
> +#define VERS_CMD "\x00\xC1\x00\x00\x00\x16\x00\x00\x00\x65\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x01\x03"
> +#define VERS_CMD_LEN 22
> +
> +/* Global commandline options */
> +struct Opt_args {
> + enum StartUp {
> + ST_CLEAR = 1,
> + ST_SAVE = 2,
> + ST_DEACTIVATED = 3
> + } startup;
> + unsigned long hwinitpcrs;
> + int loglevel;
> + uint32_t tpmconf;
> + bool enable_maint_cmds;
> +};
> +extern struct Opt_args opt_args;
> +
> +#endif
> diff --git a/stubdom/vtpm/vtpm_cmd.c b/stubdom/vtpm/vtpm_cmd.c new
> file mode 100644 index 0000000..7eae98b
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_cmd.c
> @@ -0,0 +1,256 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#include <types.h>
> +#include <xen/xen.h>
> +#include <mm.h>
> +#include <gnttab.h>
> +#include "tpm/tpm_marshalling.h"
> +#include "vtpm_manager.h"
> +#include "vtpm_cmd.h"
> +#include <tpmback.h>
> +
> +#define TRYFAILGOTO(C) \
> + if((C)) { \
> + status = TPM_FAIL; \
> + goto abort_egress; \
> + }
> +#define TRYFAILGOTOMSG(C, msg) \
> + if((C)) { \
> + status = TPM_FAIL; \
> + error(msg); \
> + goto abort_egress; \
> + }
> +#define CHECKSTATUSGOTO(ret, fname) \
> + if((ret) != TPM_SUCCESS) { \
> + error("%s failed with error code (%lu)", fname, (unsigned long) ret); \
> + status = ord; \
> + goto abort_egress; \
> + }
> +
> +#define ERR_MALFORMED "Malformed response from backend"
> +#define ERR_TPMFRONT "Error sending command through frontend device"
> +
> +struct shpage {
> + void* page;
> + grant_ref_t grantref;
> +};
> +
> +typedef struct shpage shpage_t;
> +
> +static inline int pack_header(uint8_t** bptr, UINT32* len, TPM_TAG
> +tag, UINT32 size, TPM_COMMAND_CODE ord) {
> + return *bptr == NULL ||
> + tpm_marshal_UINT16(bptr, len, tag) ||
> + tpm_marshal_UINT32(bptr, len, size) ||
> + tpm_marshal_UINT32(bptr, len, ord); }
> +
> +static inline int unpack_header(uint8_t** bptr, UINT32* len, TPM_TAG*
> +tag, UINT32* size, TPM_COMMAND_CODE* ord) {
> + return *bptr == NULL ||
> + tpm_unmarshal_UINT16(bptr, len, tag) ||
> + tpm_unmarshal_UINT32(bptr, len, size) ||
> + tpm_unmarshal_UINT32(bptr, len, ord); }
> +
> +int create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode) {
> + TPM_TAG tag;
> + UINT32 len = tpmcmd->req_len;
> + uint8_t* respptr;
> + uint8_t* cmdptr = tpmcmd->req;
> +
> + if(!tpm_unmarshal_UINT16(&cmdptr, &len, &tag)) {
> + switch (tag) {
> + case TPM_TAG_RQU_COMMAND:
> + tag = TPM_TAG_RSP_COMMAND;
> + break;
> + case TPM_TAG_RQU_AUTH1_COMMAND:
> + tag = TPM_TAG_RQU_AUTH2_COMMAND;
> + break;
> + case TPM_TAG_RQU_AUTH2_COMMAND:
> + tag = TPM_TAG_RQU_AUTH2_COMMAND;
> + break;
> + }
> + } else {
> + tag = TPM_TAG_RSP_COMMAND;
> + }
> +
> + tpmcmd->resp_len = len = 10;
> + tpmcmd->resp = respptr = tpm_malloc(tpmcmd->resp_len);
> +
> + return pack_header(&respptr, &len, tag, len, errorcode); }
> +
> +TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes, UINT32 *numbytes) {
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t* cmdbuf, *resp, *bptr;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + /*Ask the real tpm for random bytes for the seed */
> + TPM_TAG tag = TPM_TAG_RQU_COMMAND;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = TPM_ORD_GetRandom;
> + len = size = sizeof(TPM_TAG) + sizeof(UINT32) +
> + sizeof(TPM_COMMAND_CODE) + sizeof(UINT32);
> +
> + /*Create the raw tpm command */
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> + TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, *numbytes));
> +
> + /* Send cmd, wait for response */
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen),
> + ERR_TPMFRONT);
> +
> + bptr = resp; len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord),
> + ERR_MALFORMED);
> +
> + //Check return status of command
> + CHECKSTATUSGOTO(ord, "TPM_GetRandom()");
> +
> + // Get the number of random bytes in the response
> + TRYFAILGOTOMSG(tpm_unmarshal_UINT32(&bptr, &len, &size), ERR_MALFORMED);
> + *numbytes = size;
> +
> + //Get the random bytes out, tpm may give us less bytes than what we wanrt
> + TRYFAILGOTOMSG(tpm_unmarshal_BYTE_ARRAY(&bptr, &len, bytes,
> + *numbytes), ERR_MALFORMED);
> +
> + goto egress;
> +abort_egress:
> +egress:
> + free(cmdbuf);
> + return status;
> +
> +}
> +
> +TPM_RESULT VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev,
> +uint8_t** data, size_t* data_length) {
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t* bptr, *resp;
> + uint8_t* cmdbuf = NULL;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + TPM_TAG tag = VTPM_TAG_REQ;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = VTPM_ORD_LOADHASHKEY;
> +
> + /*Create the command*/
> + len = size = VTPM_COMMAND_HEADER_SIZE;
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> +
> + /* Send the command to vtpm_manager */
> + info("Requesting Encryption key from backend");
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp,
> + &resplen), ERR_TPMFRONT);
> +
> + /* Unpack response header */
> + bptr = resp;
> + len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord),
> + ERR_MALFORMED);
> +
> + /* Check return code */
> + CHECKSTATUSGOTO(ord, "VTPM_LoadHashKey()");
> +
> + /* Get the size of the key */
> + *data_length = size - VTPM_COMMAND_HEADER_SIZE;
> +
> + /* Copy the key bits */
> + *data = malloc(*data_length);
> + memcpy(*data, bptr, *data_length);
> +
> + goto egress;
> +abort_egress:
> + error("VTPM_LoadHashKey failed");
> +egress:
> + free(cmdbuf);
> + return status;
> +}
> +
> +TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev,
> +uint8_t* data, size_t data_length) {
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t* bptr, *resp;
> + uint8_t* cmdbuf = NULL;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + TPM_TAG tag = VTPM_TAG_REQ;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = VTPM_ORD_SAVEHASHKEY;
> +
> + /*Create the command*/
> + len = size = VTPM_COMMAND_HEADER_SIZE + data_length;
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> + memcpy(bptr, data, data_length);
> + bptr += data_length;
> +
> + /* Send the command to vtpm_manager */
> + info("Sending encryption key to backend");
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp,
> + &resplen), ERR_TPMFRONT);
> +
> + /* Unpack response header */
> + bptr = resp;
> + len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord),
> + ERR_MALFORMED);
> +
> + /* Check return code */
> + CHECKSTATUSGOTO(ord, "VTPM_SaveHashKey()");
> +
> + goto egress;
> +abort_egress:
> + error("VTPM_SaveHashKey failed");
> +egress:
> + free(cmdbuf);
> + return status;
> +}
> +
> +TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32
> +pcrIndex, BYTE* outDigest) {
> + TPM_RESULT status = TPM_SUCCESS;
> + uint8_t *cmdbuf, *resp, *bptr;
> + size_t resplen = 0;
> + UINT32 len;
> +
> + /*Just send a TPM_PCRRead Command to the HW tpm */
> + TPM_TAG tag = TPM_TAG_RQU_COMMAND;
> + UINT32 size;
> + TPM_COMMAND_CODE ord = TPM_ORD_PCRRead;
> + len = size = sizeof(TPM_TAG) + sizeof(UINT32) +
> + sizeof(TPM_COMMAND_CODE) + sizeof(UINT32);
> +
> + /*Create the raw tpm cmd */
> + bptr = cmdbuf = malloc(size);
> + TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
> + TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, pcrIndex));
> +
> + /*Send Cmd wait for response */
> + TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp,
> + &resplen), ERR_TPMFRONT);
> +
> + bptr = resp; len = resplen;
> + TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord),
> + ERR_MALFORMED);
> +
> + //Check return status of command
> + CHECKSTATUSGOTO(ord, "TPM_PCRRead");
> +
> + //Get the ptr value
> + memcpy(outDigest, bptr, sizeof(TPM_PCRVALUE));
> +
> + goto egress;
> +abort_egress:
> +egress:
> + free(cmdbuf);
> + return status;
> +
> +}
> diff --git a/stubdom/vtpm/vtpm_cmd.h b/stubdom/vtpm/vtpm_cmd.h new
> file mode 100644 index 0000000..b0bfa22
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_cmd.h
> @@ -0,0 +1,31 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#ifndef MANAGER_H
> +#define MANAGER_H
> +
> +#include <tpmfront.h>
> +#include <tpmback.h>
> +#include "tpm/tpm_structures.h"
> +
> +/* Create a command response error header */ int
> +create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode);
> +/* Request random bytes from hardware tpm, returns 0 on success */
> +TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE*
> +bytes, UINT32* numbytes);
> +/* Retreive 256 bit AES encryption key from manager */ TPM_RESULT
> +VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data,
> +size_t* data_length);
> +/* Manager securely saves our 256 bit AES encryption key */
> +TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev,
> +uint8_t* data, size_t data_length);
> +/* Send a TPM_PCRRead command passthrough the manager to the hw tpm
> +*/ TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32
> +pcrIndex, BYTE* outDigest);
> +
> +#endif
> diff --git a/stubdom/vtpm/vtpm_pcrs.c b/stubdom/vtpm/vtpm_pcrs.c new
> file mode 100644 index 0000000..22a6cef
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_pcrs.c
> @@ -0,0 +1,43 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#include "vtpm_pcrs.h"
> +#include "vtpm_cmd.h"
> +#include "tpm/tpm_data.h"
> +
> +#define PCR_VALUE tpmData.permanent.data.pcrValue
> +
> +static int write_pcr_direct(unsigned int pcrIndex, uint8_t* val) {
> + if(pcrIndex > TPM_NUM_PCR) {
> + return TPM_BADINDEX;
> + }
> + memcpy(&PCR_VALUE[pcrIndex], val, sizeof(TPM_PCRVALUE));
> + return TPM_SUCCESS;
> +}
> +
> +TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev,
> +unsigned long pcrs) {
> + TPM_RESULT rc = TPM_SUCCESS;
> + uint8_t digest[sizeof(TPM_PCRVALUE)];
> +
> + for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
> + if(pcrs & 1 << i) {
> + if((rc = VTPM_PCRRead(tpmfront_dev, i, digest)) != TPM_SUCCESS) {
> + error("TPM_PCRRead failed with error : %d", rc);
> + return rc;
> + }
> + write_pcr_direct(i, digest);
> + }
> + }
> +
> + return rc;
> +}
> diff --git a/stubdom/vtpm/vtpm_pcrs.h b/stubdom/vtpm/vtpm_pcrs.h new
> file mode 100644 index 0000000..11835f9
> --- /dev/null
> +++ b/stubdom/vtpm/vtpm_pcrs.h
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#ifndef VTPM_PCRS_H
> +#define VTPM_PCRS_H
> +
> +#include "tpm/tpm_structures.h"
> +
> +#define VTPM_PCR0 1
> +#define VTPM_PCR1 1 << 1
> +#define VTPM_PCR2 1 << 2
> +#define VTPM_PCR3 1 << 3
> +#define VTPM_PCR4 1 << 4
> +#define VTPM_PCR5 1 << 5
> +#define VTPM_PCR6 1 << 6
> +#define VTPM_PCR7 1 << 7
> +#define VTPM_PCR8 1 << 8
> +#define VTPM_PCR9 1 << 9
> +#define VTPM_PCR10 1 << 10
> +#define VTPM_PCR11 1 << 11
> +#define VTPM_PCR12 1 << 12
> +#define VTPM_PCR13 1 << 13
> +#define VTPM_PCR14 1 << 14
> +#define VTPM_PCR15 1 << 15
> +#define VTPM_PCR16 1 << 16
> +#define VTPM_PCR17 1 << 17
> +#define VTPM_PCR18 1 << 18
> +#define VTPM_PCR19 1 << 19
> +#define VTPM_PCR20 1 << 20
> +#define VTPM_PCR21 1 << 21
> +#define VTPM_PCR22 1 << 22
> +#define VTPM_PCR23 1 << 23
> +
> +#define VTPM_PCRALL (1 << TPM_NUM_PCR) - 1 #define VTPM_PCRNONE 0
> +
> +#define VTPM_NUMPCRS 24
> +
> +struct tpmfront_dev;
> +
> +TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev,
> +unsigned long pcrs);
> +
> +
> +#endif
> diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c new file
> mode 100644 index 0000000..b343bd8
> --- /dev/null
> +++ b/stubdom/vtpm/vtpmblk.c
> @@ -0,0 +1,307 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#include <mini-os/byteorder.h>
> +#include "vtpmblk.h"
> +#include "tpm/tpm_marshalling.h"
> +#include "vtpm_cmd.h"
> +#include "polarssl/aes.h"
> +#include "polarssl/sha1.h"
> +#include <blkfront.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +
> +/*Encryption key and block sizes */
> +#define BLKSZ 16
> +
> +static struct blkfront_dev* blkdev = NULL; static int blkfront_fd =
> +-1;
> +
> +int init_vtpmblk(struct tpmfront_dev* tpmfront_dev) {
> + struct blkfront_info blkinfo;
> + info("Initializing persistent NVM storage\n");
> +
> + if((blkdev = init_blkfront(NULL, &blkinfo)) == NULL) {
> + error("BLKIO: ERROR Unable to initialize blkfront");
> + return -1;
> + }
> + if (blkinfo.info & VDISK_READONLY || blkinfo.mode != O_RDWR) {
> + error("BLKIO: ERROR block device is read only!");
> + goto error;
> + }
> + if((blkfront_fd = blkfront_open(blkdev)) == -1) {
> + error("Unable to open blkfront file descriptor!");
> + goto error;
> + }
> +
> + return 0;
> +error:
> + shutdown_blkfront(blkdev);
> + blkdev = NULL;
> + return -1;
> +}
> +
> +void shutdown_vtpmblk(void)
> +{
> + close(blkfront_fd);
> + blkfront_fd = -1;
> + blkdev = NULL;
> +}
> +
> +int write_vtpmblk_raw(uint8_t *data, size_t data_length) {
> + int rc;
> + uint32_t lenbuf;
> + debug("Begin Write data=%p len=%u", data, data_length);
> +
> + lenbuf = cpu_to_be32((uint32_t)data_length);
> +
> + lseek(blkfront_fd, 0, SEEK_SET);
> + if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
> + error("write(length) failed! error was %s", strerror(errno));
> + return -1;
> + }
> + if((rc = write(blkfront_fd, data, data_length)) != data_length) {
> + error("write(data) failed! error was %s", strerror(errno));
> + return -1;
> + }
> +
> + info("Wrote %u bytes to NVM persistent storage", data_length);
> +
> + return 0;
> +}
> +
> +int read_vtpmblk_raw(uint8_t **data, size_t *data_length) {
> + int rc;
> + uint32_t lenbuf;
> +
> + lseek(blkfront_fd, 0, SEEK_SET);
> + if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
> + error("read(length) failed! error was %s", strerror(errno));
> + return -1;
> + }
> + *data_length = (size_t) cpu_to_be32(lenbuf);
> + if(*data_length == 0) {
> + error("read 0 data_length for NVM");
> + return -1;
> + }
> +
> + *data = tpm_malloc(*data_length);
> + if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
> + error("read(data) failed! error was %s", strerror(errno));
> + return -1;
> + }
> +
> + info("Read %u bytes from NVM persistent storage", *data_length);
> + return 0;
> +}
> +
> +int encrypt_vtpmblk(uint8_t* clear, size_t clear_len, uint8_t**
> +cipher, size_t* cipher_len, uint8_t* symkey) {
> + int rc = 0;
> + uint8_t iv[BLKSZ];
> + aes_context aes_ctx;
> + UINT32 temp;
> + int mod;
> +
> + uint8_t* clbuf = NULL;
> +
> + uint8_t* ivptr;
> + int ivlen;
> +
> + uint8_t* cptr; //Cipher block pointer
> + int clen; //Cipher block length
> +
> + /*Create a new 256 bit encryption key */
> + if(symkey == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> + tpm_get_extern_random_bytes(symkey, NVMKEYSZ);
> +
> + /*Setup initialization vector - random bits and then 4 bytes clear text size at the end*/
> + temp = sizeof(UINT32);
> + ivlen = BLKSZ - temp;
> + tpm_get_extern_random_bytes(iv, ivlen);
> + ivptr = iv + ivlen;
> + tpm_marshal_UINT32(&ivptr, &temp, (UINT32) clear_len);
> +
> + /*The clear text needs to be padded out to a multiple of BLKSZ */
> + mod = clear_len % BLKSZ;
> + clen = mod ? clear_len + BLKSZ - mod : clear_len;
> + clbuf = malloc(clen);
> + if (clbuf == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> + memcpy(clbuf, clear, clear_len);
> + /* zero out the padding bits - FIXME: better / more secure way to handle these? */
> + if(clen - clear_len) {
> + memset(clbuf + clear_len, 0, clen - clear_len);
> + }
> +
> + /* Setup the ciphertext buffer */
> + *cipher_len = BLKSZ + clen; /*iv + ciphertext */
> + cptr = *cipher = malloc(*cipher_len);
> + if (*cipher == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> +
> + /* Copy the IV to cipher text blob*/
> + memcpy(cptr, iv, BLKSZ);
> + cptr += BLKSZ;
> +
> + /* Setup encryption */
> + aes_setkey_enc(&aes_ctx, symkey, 256);
> +
> + /* Do encryption now */
> + aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, clen, iv, clbuf, cptr);
> +
> + goto egress;
> +abort_egress:
> +egress:
> + free(clbuf);
> + return rc;
> +}
> +int decrypt_vtpmblk(uint8_t* cipher, size_t cipher_len, uint8_t**
> +clear, size_t* clear_len, uint8_t* symkey) {
> + int rc = 0;
> + uint8_t iv[BLKSZ];
> + uint8_t* ivptr;
> + UINT32 u32, temp;
> + aes_context aes_ctx;
> +
> + uint8_t* cptr = cipher; //cipher block pointer
> + int clen = cipher_len; //cipher block length
> +
> + /* Pull out the initialization vector */
> + memcpy(iv, cipher, BLKSZ);
> + cptr += BLKSZ;
> + clen -= BLKSZ;
> +
> + /* Setup the clear text buffer */
> + if((*clear = malloc(clen)) == NULL) {
> + rc = -1;
> + goto abort_egress;
> + }
> +
> + /* Get the length of clear text from last 4 bytes of iv */
> + temp = sizeof(UINT32);
> + ivptr = iv + BLKSZ - temp;
> + tpm_unmarshal_UINT32(&ivptr, &temp, &u32);
> + *clear_len = u32;
> +
> + /* Setup decryption */
> + aes_setkey_dec(&aes_ctx, symkey, 256);
> +
> + /* Do decryption now */
> + if ((clen % BLKSZ) != 0) {
> + error("Decryption Error: Cipher block size was not a multiple of %u", BLKSZ);
> + rc = -1;
> + goto abort_egress;
> + }
> + aes_crypt_cbc(&aes_ctx, AES_DECRYPT, clen, iv, cptr, *clear);
> +
> + goto egress;
> +abort_egress:
> +egress:
> + return rc;
> +}
> +
> +int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
> + int rc;
> + uint8_t* cipher = NULL;
> + size_t cipher_len = 0;
> + uint8_t hashkey[HASHKEYSZ];
> + uint8_t* symkey = hashkey + HASHSZ;
> +
> + /* Encrypt the data */
> + if((rc = encrypt_vtpmblk(data, data_length, &cipher, &cipher_len, symkey))) {
> + goto abort_egress;
> + }
> + /* Write to disk */
> + if((rc = write_vtpmblk_raw(cipher, cipher_len))) {
> + goto abort_egress;
> + }
> + /* Get sha1 hash of data */
> + sha1(cipher, cipher_len, hashkey);
> +
> + /* Send hash and key to manager */
> + if((rc = VTPM_SaveHashKey(tpmfront_dev, hashkey, HASHKEYSZ)) != TPM_SUCCESS) {
> + goto abort_egress;
> + }
> + goto egress;
> +abort_egress:
> +egress:
> + free(cipher);
> + return rc;
> +}
> +
> +int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data_length) {
> + int rc;
> + uint8_t* cipher = NULL;
> + size_t cipher_len = 0;
> + size_t keysize;
> + uint8_t* hashkey = NULL;
> + uint8_t hash[HASHSZ];
> + uint8_t* symkey;
> +
> + /* Retreive the hash and the key from the manager */
> + if((rc = VTPM_LoadHashKey(tpmfront_dev, &hashkey, &keysize)) != TPM_SUCCESS) {
> + goto abort_egress;
> + }
> + if(keysize != HASHKEYSZ) {
> + error("Manager returned a hashkey of invalid size! expected %d, actual %d", NVMKEYSZ, keysize);
> + rc = -1;
> + goto abort_egress;
> + }
> + symkey = hashkey + HASHSZ;
> +
> + /* Read from disk now */
> + if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
> + goto abort_egress;
> + }
> +
> + /* Compute the hash of the cipher text and compare */
> + sha1(cipher, cipher_len, hash);
> + if(memcmp(hash, hashkey, HASHSZ)) {
> + int i;
> + error("NVM Storage Checksum failed!");
> + printf("Expected: ");
> + for(i = 0; i < HASHSZ; ++i) {
> + printf("%02hhX ", hashkey[i]);
> + }
> + printf("\n");
> + printf("Actual: ");
> + for(i = 0; i < HASHSZ; ++i) {
> + printf("%02hhX ", hash[i]);
> + }
> + printf("\n");
> + rc = -1;
> + goto abort_egress;
> + }
> +
> + /* Decrypt the blob */
> + if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
> + goto abort_egress;
> + }
> + goto egress;
> +abort_egress:
> +egress:
> + free(cipher);
> + free(hashkey);
> + return rc;
> +}
> diff --git a/stubdom/vtpm/vtpmblk.h b/stubdom/vtpm/vtpmblk.h new file
> mode 100644 index 0000000..282ce6a
> --- /dev/null
> +++ b/stubdom/vtpm/vtpmblk.h
> @@ -0,0 +1,31 @@
> +/*
> + * Copyright (c) 2010-2012 United States Government, as represented
> +by
> + * the Secretary of Defense. All rights reserved.
> + *
> + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
> + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
> + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY,
> +FITNESS
> + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY
> + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING
> +THE
> + * SOFTWARE.
> + */
> +
> +#ifndef NVM_H
> +#define NVM_H
> +#include <mini-os/types.h>
> +#include <xen/xen.h>
> +#include <tpmfront.h>
> +
> +#define NVMKEYSZ 32
> +#define HASHSZ 20
> +#define HASHKEYSZ (NVMKEYSZ + HASHSZ)
> +
> +int init_vtpmblk(struct tpmfront_dev* tpmfront_dev); void
> +shutdown_vtpmblk(void);
> +
> +/* Encrypts and writes data to blk device */ int write_vtpmblk(struct
> +tpmfront_dev* tpmfront_dev, uint8_t *data, size_t data_length);
> +/* Reads, Decrypts, and returns data from blk device */ int
> +read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t **data,
> +size_t *data_length);
> +
> +#endif
> --
> 1.7.10.4
>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel