mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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> Committed-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
5e5e2d2a34
commit
d463e3c5a3
12 files changed
+1214
No files matched your search
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||