From: kaf24@firebug.cl.cam.ac.uk Date: Tue, 27 Jun 2006 10:15:48 +0000 (+0100) Subject: [VTPM_TOOLS] Hotplug script enabled the vtpm manager and removed the X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15913^2~25 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=110b2784a3a99a63621149df91cba1d6ac8ad2b5;p=xen.git [VTPM_TOOLS] Hotplug script enabled the vtpm manager and removed the control messages from the BE. Signed-off-by: Vincent Scarlata --- diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h index c0e80fffcc..fba08d1c91 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h @@ -63,8 +63,6 @@ void tpmif_xenbus_init(void); void tpmif_xenbus_exit(void); int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn); irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs); -int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domain, u32 instance); -int tpmif_vtpm_close(u32 instance); int vtpm_release_packets(tpmif_t * tpmif, int send_msgs); diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c index a899bcba9b..066bcf33aa 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c @@ -684,95 +684,6 @@ static struct miscdevice vtpms_miscdevice = { .fops = &vtpm_ops, }; -/*************************************************************** - Virtual TPM functions and data stuctures -***************************************************************/ - -static u8 create_cmd[] = { - 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0, 0, 0, 19, /* 2: length */ - 0, 0, 0, 0x1, /* 6: VTPM_ORD_OPEN */ - 0, /* 10: VTPM type */ - 0, 0, 0, 0, /* 11: domain id */ - 0, 0, 0, 0 /* 15: instance id */ -}; - -int tpmif_vtpm_open(tpmif_t * tpmif, domid_t domid, u32 instance) -{ - int rc = 0; - struct packet *pak; - - pak = packet_alloc(tpmif, - sizeof (create_cmd), - create_cmd[1], - PACKET_FLAG_DISCARD_RESPONSE | - PACKET_FLAG_CHECK_RESPONSESTATUS); - if (pak) { - u8 buf[sizeof (create_cmd)]; - u32 domid_no = htonl((u32) domid); - u32 instance_no = htonl(instance); - - memcpy(buf, create_cmd, sizeof (create_cmd)); - - memcpy(&buf[11], &domid_no, sizeof (u32)); - memcpy(&buf[15], &instance_no, sizeof (u32)); - - /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof (buf)); - - if (rc == 0) { - pak->tpm_instance = 0; - rc = vtpm_queue_packet(pak); - } - if (rc < 0) { - /* could not be queued or built */ - packet_free(pak); - } - } else { - rc = -ENOMEM; - } - return rc; -} - -static u8 destroy_cmd[] = { - 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0, 0, 0, 14, /* 2: length */ - 0, 0, 0, 0x2, /* 6: VTPM_ORD_CLOSE */ - 0, 0, 0, 0 /* 10: instance id */ -}; - -int tpmif_vtpm_close(u32 instid) -{ - int rc = 0; - struct packet *pak; - - pak = packet_alloc(NULL, - sizeof (destroy_cmd), - destroy_cmd[1], PACKET_FLAG_DISCARD_RESPONSE); - if (pak) { - u8 buf[sizeof (destroy_cmd)]; - u32 instid_no = htonl(instid); - - memcpy(buf, destroy_cmd, sizeof (destroy_cmd)); - memcpy(&buf[10], &instid_no, sizeof (u32)); - - /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof (buf)); - - if (rc == 0) { - pak->tpm_instance = 0; - rc = vtpm_queue_packet(pak); - } - if (rc < 0) { - /* could not be queued or built */ - packet_free(pak); - } - } else { - rc = -ENOMEM; - } - return rc; -} - /*************************************************************** Utility functions ***************************************************************/ diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index ee72c83a0d..e98072e29b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -154,11 +154,6 @@ static void frontend_changed(struct xenbus_device *dev, break; case XenbusStateClosed: - /* - * Notify the vTPM manager about the front-end - * having left. - */ - tpmif_vtpm_close(be->instance); device_unregister(&be->dev->dev); tpmback_remove(dev); break; @@ -177,28 +172,10 @@ static void frontend_changed(struct xenbus_device *dev, static void maybe_connect(struct backend_info *be) { - int err; - if (be->tpmif == NULL || be->tpmif->status == CONNECTED) return; connect(be); - - /* - * Notify the vTPM manager about a new front-end. - */ - err = tpmif_vtpm_open(be->tpmif, - be->frontend_id, - be->instance); - if (err) { - xenbus_dev_error(be->dev, err, - "queueing vtpm open packet"); - /* - * Should close down this device and notify FE - * about closure. - */ - return; - } } diff --git a/tools/examples/Makefile b/tools/examples/Makefile index 4cbb15658b..c5ccb6c8af 100644 --- a/tools/examples/Makefile +++ b/tools/examples/Makefile @@ -32,7 +32,7 @@ XEN_SCRIPTS += external-device-migrate XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh vtpm-hotplug-common.sh -XEN_SCRIPT_DATA += vtpm-migration.sh +XEN_SCRIPT_DATA += vtpm-migration.sh vtpm-impl XEN_HOTPLUG_DIR = /etc/hotplug XEN_HOTPLUG_SCRIPTS = xen-backend.agent diff --git a/tools/examples/vtpm-impl b/tools/examples/vtpm-impl new file mode 100644 index 0000000000..f51f3383ca --- /dev/null +++ b/tools/examples/vtpm-impl @@ -0,0 +1,136 @@ +#!/bin/bash +# =================================================================== +# +# Copyright (c) 2005, Intel Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. +# =================================================================== + +VTPM_IMPL_DEFINED=1 + +# | SRC | TAG | CMD SIZE | ORD | type| mode +TPM_CMD_OPEN=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x01 +TPM_CMD_RESM=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x02 +TPM_CMD_CLOS=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x0e\\x01\\x00\\x00\\x02 +TPM_CMD_DELE=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x0e\\x01\\x00\\x00\\x03 + +TPM_SUCCESS=00000000 + +TX_VTPM_MANAGER=/var/vtpm/fifos/from_console.fifo +RX_VTPM_MANAGER=/var/vtpm/fifos/to_console.fifo + +# -------------------- Helpers for binary streams ----------- + +function str_to_hex32() { + printf "%0.8x" $1 +} + +function hex32_to_bin() { + local inst=$(str_to_hex32 $1); + + local n1=`echo $inst | sed 's/\(..\)....../\\\\x\1/'` + local n2=`echo $inst | sed 's/..\(..\)..../\\\\x\1/'` + local n3=`echo $inst | sed 's/....\(..\)../\\\\x\1/'` + local n4=`echo $inst | sed 's/......\(..\)/\\\\x\1/'` + + echo "$n1$n2$n3$n4" +} + +function vtpm_manager_cmd() { + local cmd=$1; + local inst=$2; + local inst_bin=$(hex32_to_bin $inst); + + #send cmd to vtpm_manager + printf "$cmd$inst_bin" > $TX_VTPM_MANAGER + + #recv response + local resp_hex=`dd skip=10 bs=1 count=4 if=$RX_VTPM_MANAGER 2> /dev/null | xxd -ps` + + #return whether the command was successful + if [ $resp_hex != $TPM_SUCCESS ]; then + vtpm_fatal_error=1 + false + else + true + fi +} + +# ------------------ Command handlers ----------------- + +# Create new vtpm instance & set it up for use +function vtpm_create () { + # Creation is handled implicitly by the manager on first setup + # so just set it up for use + $(vtpm_start $1) +} + +# Setup vtpm instance for use. +function vtpm_start() { + $(vtpm_manager_cmd $TPM_CMD_OPEN $1) +} + +function vtpm_resume() { + $(vtpm_manager_cmd $TPM_CMD_RESM $1) +} + +# Reset the vtpm AKA clear PCRs +function vtpm_reset() { + #not used by current implemenation + true +} + +# Shutdown the vtpm while the vm is down +# This could be a suspend of shutdown +# we cannot distinquish, so save the state +# and decide on startup if we should keep is +function vtpm_suspend() { + $(vtpm_manager_cmd $TPM_CMD_CLOS $1) +} + + +function vtpm_delete() { + local inst=$1 + if $(vtpm_manager_cmd $TPM_CMD_DELE $inst); then + rm -f /var/vtpm/vtpm_dm_$1.data + true + else + vtpm_fatal_error=1 + false + fi +} + +function vtpm_migrate() { + echo "Error: vTPM migration accross machines not implemented." +} + +function vtpm_migrate_recover() { + true +} + diff --git a/tools/vtpm_manager/manager/dmictl.c b/tools/vtpm_manager/manager/dmictl.c index 4edd14408b..7961f98433 100644 --- a/tools/vtpm_manager/manager/dmictl.c +++ b/tools/vtpm_manager/manager/dmictl.c @@ -76,14 +76,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf) { VTPM_DMI_RESOURCE *new_dmi=NULL; TPM_RESULT status=TPM_FAIL; - BYTE type; - UINT32 dmi_id, domain_id, *dmi_id_key; + BYTE type, startup_mode; + UINT32 dmi_id, *dmi_id_key=NULL; if (param_buf == NULL) { // Assume creation of Dom 0 control - type = 0; - domain_id = VTPM_CTL_DM; + type = VTPM_TYPE_NON_MIGRATABLE; dmi_id = VTPM_CTL_DM; - } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) { + } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(BYTE) + sizeof(UINT32)) { vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n", buffer_len(param_buf)); status = TPM_BAD_PARAMETER; goto abort_egress; @@ -91,13 +90,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf) { vtpm_globals->connected_dmis++; // Put this here so we don't count Dom0 BSG_UnpackList( param_buf->bytes, 3, BSG_TYPE_BYTE, &type, - BSG_TYPE_UINT32, &domain_id, + BSG_TYPE_BYTE, &startup_mode, BSG_TYPE_UINT32, &dmi_id); } - + new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id); if (new_dmi == NULL) { - vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on domain %d.\n", dmi_id, domain_id); + vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached.\n", dmi_id ); // Brand New DMI. Initialize the persistent pieces if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE))) == NULL) { status = TPM_RESOURCES; @@ -106,32 +105,44 @@ TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf) { memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE)); new_dmi->dmi_id = dmi_id; new_dmi->connected = FALSE; + + if (type != VTPM_TYPE_MIGRATED) { + new_dmi->dmi_type = type; + } else { + vtpmlogerror(VTPM_LOG_VTPM, "Creation of VTPM with illegal type.\n"); + status = TPM_BAD_PARAMETER; + goto free_egress; + } if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) { status = TPM_RESOURCES; - goto abort_egress; + goto free_egress; } *dmi_id_key = new_dmi->dmi_id; // install into map if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){ - free(new_dmi); - free(dmi_id_key); + vtpmlogerror(VTPM_LOG_VTPM, "Failed to insert instance into table. Aborting.\n", dmi_id); status = TPM_FAIL; - goto egress; + goto free_egress; } } else - vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d .\n", dmi_id, domain_id); + vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d.\n", dmi_id); if (new_dmi->connected) { vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached instance %d. Ignoring\n", dmi_id); status = TPM_BAD_PARAMETER; - goto egress; + goto abort_egress; } + if (type == VTPM_TYPE_MIGRATED) { + vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach previously migrated instance %d without recovering first. Ignoring\n", dmi_id); + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + // Initialize the Non-persistent pieces - new_dmi->dmi_domain_id = domain_id; new_dmi->NVMLocation = NULL; new_dmi->TCSContext = 0; @@ -144,9 +155,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf) { // Design specific new DMI code. // Includes: create IPCs, Measuring DMI, and maybe launching DMI - status = VTPM_New_DMI_Extra(new_dmi); + status = VTPM_New_DMI_Extra(new_dmi, startup_mode); goto egress; + free_egress: // Error that requires freeing of newly allocated dmi + free(new_dmi); + free(dmi_id_key); + abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to create DMI id=%d due to status=%s. Cleaning.\n", dmi_id, tpm_get_error_name(status)); close_dmi(new_dmi ); @@ -221,7 +236,7 @@ TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t *param_buf) { goto abort_egress; } - //TODO: Automatically delete file dmi_res->NVMLocation + //vtpm scripts delete file dmi_res->NVMLocation for us // Close DMI first TPMTRYRETURN(close_dmi( dmi_res )); diff --git a/tools/vtpm_manager/manager/securestorage.c b/tools/vtpm_manager/manager/securestorage.c index b49d1298f5..37c0a160c4 100644 --- a/tools/vtpm_manager/manager/securestorage.c +++ b/tools/vtpm_manager/manager/securestorage.c @@ -190,8 +190,7 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, long bytes_written; buffer_t sealed_NVM; - - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x\n", buffer_len(inbuf)); + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_len(inbuf)); TPMTRYRETURN( envelope_encrypt(inbuf, &vtpm_globals->storageKey, @@ -310,6 +309,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap); struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes}; struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes}; + BYTE vtpm_manager_gen = VTPM_MANAGER_GEN; struct hashtable_itr *dmi_itr; VTPM_DMI_RESOURCE *dmi_res; @@ -321,7 +321,8 @@ TPM_RESULT VTPM_SaveManagerData(void) { boot_key_size = sizeof(UINT32) + // bootkeysize bootKeySize; // boot key - TPMTRYRETURN(buffer_init(&clear_flat_global, 3*sizeof(TPM_DIGEST) + // Auths + TPMTRYRETURN(buffer_init(&clear_flat_global,sizeof(BYTE) + // manager version + 3*sizeof(TPM_DIGEST) + // Auths sizeof(UINT32) +// storagekeysize storageKeySize, NULL) ); // storage key @@ -332,7 +333,8 @@ TPM_RESULT VTPM_SaveManagerData(void) { boot_key_size = BSG_PackList(flat_boot_key, 1, BSG_TPM_SIZE32_DATA, &boot_key_pack); - BSG_PackList(clear_flat_global.bytes, 3, + BSG_PackList(clear_flat_global.bytes, 4, + BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); @@ -348,7 +350,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { flat_dmis = (BYTE *) malloc( (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) - (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info + (sizeof(UINT32) +sizeof(BYTE) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); do { @@ -360,8 +362,9 @@ TPM_RESULT VTPM_SaveManagerData(void) { continue; - flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 3, + flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 4, BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TYPE_BYTE, &dmi_res->dmi_type, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); @@ -408,6 +411,7 @@ TPM_RESULT VTPM_LoadManagerData(void) { buffer_t unsealed_data; struct pack_buf_t storage_key_pack, boot_key_pack; UINT32 *dmi_id_key, enc_size; + BYTE vtpm_manager_gen; VTPM_DMI_RESOURCE *dmi_res; struct stat file_stat; @@ -458,8 +462,14 @@ TPM_RESULT VTPM_LoadManagerData(void) { &unsealed_data) ); step_size += enc_size; + if (*unsealed_data.bytes != VTPM_MANAGER_GEN) { + // Once there is more than one gen, this will include some compatability stuff + vtpmlogerror(VTPM_LOG_VTPM, "Warning: Manager Data file is gen %d, which this manager is gen %d.\n", vtpm_manager_gen, VTPM_MANAGER_GEN); + } + // Global Values needing to be saved - BSG_UnpackList( unsealed_data.bytes, 3, + BSG_UnpackList( unsealed_data.bytes, 4, + BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); @@ -469,7 +479,7 @@ TPM_RESULT VTPM_LoadManagerData(void) { // Per DMI values to be saved while ( step_size < fh_size ){ - if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) { + if (fh_size - step_size < (long) (sizeof(UINT32) + sizeof(BYTE) + 2*sizeof(TPM_DIGEST))) { vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of manager state.\n", fh_size-step_size); step_size = fh_size; } else { @@ -478,8 +488,9 @@ TPM_RESULT VTPM_LoadManagerData(void) { dmi_res->connected = FALSE; - step_size += BSG_UnpackList(flat_table + step_size, 3, + step_size += BSG_UnpackList(flat_table + step_size, 4, BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TYPE_BYTE, &dmi_res->dmi_type, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); diff --git a/tools/vtpm_manager/manager/vtpm_manager.c b/tools/vtpm_manager/manager/vtpm_manager.c index 6d02952e3b..e7663f4741 100644 --- a/tools/vtpm_manager/manager/vtpm_manager.c +++ b/tools/vtpm_manager/manager/vtpm_manager.c @@ -168,6 +168,7 @@ TPM_RESULT VTPM_Create_Manager(){ &vtpm_globals->bootKey, TRUE ) ); + TPMTRYRETURN( VTSP_SaveState(vtpm_globals->manager_tcs_handle) ); goto egress; abort_egress: @@ -218,7 +219,7 @@ TPM_RESULT VTPM_Init_Manager() { &vtpm_globals->keyAuth) ); vtpm_globals->keyAuth.fContinueAuthSession = TRUE; - // If failed, create new Manager. + // If failed, create new Manager. serviceStatus = VTPM_LoadManagerData(); if (serviceStatus == TPM_IOERROR) { vtpmloginfo(VTPM_LOG_VTPM, "Failed to read manager file. Assuming first time initialization.\n"); diff --git a/tools/vtpm_manager/manager/vtpm_manager.h b/tools/vtpm_manager/manager/vtpm_manager.h index b38c1e13af..3df76720f8 100644 --- a/tools/vtpm_manager/manager/vtpm_manager.h +++ b/tools/vtpm_manager/manager/vtpm_manager.h @@ -73,6 +73,12 @@ #define VTPM_RESTORE_CONTEXT_FAILED 4 #define VTPM_INVALID_REQUEST 5 +//*********************** Parameter Values ************************* +#define VTPM_TYPE_NON_MIGRATABLE 0x00 +#define VTPM_TYPE_MIGRATABLE 0x01 +#define VTPM_TYPE_MIGRATED 0xFF // VTPM has been migrated. + // VTPM can be recovered or deleted only + /******************* Command Parameter API ************************* VTPM Command Format @@ -94,8 +100,8 @@ VTPM Response Format VTPM_Open: Input Parameters: - Domain_type: 1 byte - domain_id: 4 bytes + Domain_type: 1 byte + startup_mode: 1 byte // Cold Boot = 1, resume = 2, deactive = 3 instance_id: 4 bytes Output Parameters: None diff --git a/tools/vtpm_manager/manager/vtpm_manager_handler.c b/tools/vtpm_manager/manager/vtpm_manager_handler.c index 2512a859d4..c3c54362bb 100644 --- a/tools/vtpm_manager/manager/vtpm_manager_handler.c +++ b/tools/vtpm_manager/manager/vtpm_manager_handler.c @@ -78,13 +78,14 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, BOOL is_priv, char *thread_name) { TPM_RESULT status = TPM_FAIL; // Should never return - UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, out_message_size_full; - BYTE *cmd_header, *in_param, *out_message; + UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, reply_size; + BYTE *cmd_header=NULL, *in_param=NULL, *out_message=NULL, *reply; buffer_t *command_buf=NULL, *result_buf=NULL; TPM_TAG tag; TPM_COMMAND_CODE ord; VTPM_DMI_RESOURCE *dmi_res; int size_read, size_write, i; + BOOL add_header=TRUE; // This indicates to prepend a header on result_buf before sending cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV); command_buf = (buffer_t *) malloc(sizeof(buffer_t)); @@ -100,7 +101,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, // Read command header size_read = vtpm_ipc_read(rx_ipc_h, NULL, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV); if (size_read > 0) { - vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d}: 0x", size_read); + vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d]: 0x", size_read); for (i=0; iconnected) ) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to non-existent or disconnected DMI %d. Aborting...\n", dmi); status = TPM_BAD_PARAMETER; + goto abort_with_error; } if (tag == VTPM_TAG_REQ) { @@ -176,9 +178,14 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, status = vtpm_manager_handle_tpm_cmd(fw_tx_ipc_h, fw_rx_ipc_h, dmi_res, cmd_header, command_buf, result_buf, thread_name); // This means calling the DMI failed, not that the cmd failed in the DMI + // Since the return will be interpretted by a TPM app, all errors are IO_ERRORs to the app if (status != TPM_SUCCESS) { + status = TPM_IOERROR; goto abort_with_error; } + // Unlike all other commands, forwarded commands yield a result_buf that includes the DMI's status. This + // should be forwarded to the caller VM + add_header = FALSE; } else { // We are not supposed to forward TPM commands at all. int i; @@ -205,38 +212,43 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, #ifndef VTPM_MULTI_VM abort_with_error: #endif + + if (add_header) { + // Prepend VTPM header with destination DM stamped + out_param_size = buffer_len(result_buf); + out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size; + reply_size = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; + out_message = (BYTE *) malloc (reply_size); + reply = out_message; - // Prepend VTPM header with destination DM stamped - out_param_size = buffer_len(result_buf); - out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size; - out_message_size_full = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; - out_message = (BYTE *) malloc (out_message_size_full); - - BSG_PackList(out_message, 4, - BSG_TYPE_UINT32, (BYTE *) &dmi, - BSG_TPM_TAG, (BYTE *) &tag, - BSG_TYPE_UINT32, (BYTE *) &out_message_size, - BSG_TPM_RESULT, (BYTE *) &status); + BSG_PackList(out_message, 4, + BSG_TYPE_UINT32, (BYTE *) &dmi, + BSG_TPM_TAG, (BYTE *) &tag, + BSG_TYPE_UINT32, (BYTE *) &out_message_size, + BSG_TPM_RESULT, (BYTE *) &status); - if (buffer_len(result_buf) > 0) - memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size); - - //Note: Send message + dmi_id - size_write = vtpm_ipc_write(tx_ipc_h, dmi_res->tx_vtpm_ipc_h, out_message, out_message_size_full ); + if (buffer_len(result_buf) > 0) + memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size); + //Note: Send message + dmi_id + } else { + reply = result_buf->bytes; + reply_size = buffer_len(result_buf); + } + size_write = vtpm_ipc_write(tx_ipc_h, (dmi_res ? dmi_res->tx_vtpm_ipc_h : NULL), reply, reply_size ); if (size_write > 0) { vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x"); - for (i=0; i < out_message_size_full; i++) - vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", out_message[i]); + for (i=0; i < reply_size; i++) + vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", reply[i]); vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); } else { vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s had error writing to ipc. Aborting... \n", thread_name); goto abort_command; } - free(out_message); + free(out_message); out_message=NULL; - if (size_write < (int)out_message_size_full) { - vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full command to ipc (%d/%d)\n", thread_name, size_write, out_message_size_full); + if (size_write < (int)reply_size) { + vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full command to ipc (%d/%d)\n", thread_name, size_write, reply_size); goto abort_command; } @@ -246,9 +258,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, //free buffers bzero(cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV); //free(in_param); // This was converted to command_buf. No need to free - if (command_buf != result_buf) - buffer_free(result_buf); - + buffer_free(result_buf); buffer_free(command_buf); // If we have a write lock, save the manager table @@ -258,6 +268,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, } vtpm_lock_unlock(); + add_header = TRUE; // Reset to the default } // End while(1) } @@ -369,6 +380,7 @@ TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h, dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV; size_write = vtpm_ipc_write(tx_ipc_h, dmi_res->tx_tpm_ipc_h, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV ); if (size_write > 0) { + vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT (DMI): 0x"); for (i=0; iNVMLocation, &file_info) == -1) + switch (startup_mode) { + case TPM_ST_CLEAR: execl (TPM_EMULATOR_PATH, "vtmpd", "clear", dmi_id_str, NULL); - else + break; + case TPM_ST_STATE: execl (TPM_EMULATOR_PATH, "vtpmd", "save", dmi_id_str, NULL); + break; + case TPM_ST_DEACTIVATED: + execl (TPM_EMULATOR_PATH, "vtpmd", "deactivated", dmi_id_str, NULL); + break; + default: + status = TPM_BAD_PARAMETER; + goto abort_egress; + } // Returning from these at all is an error. vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n"); @@ -309,7 +311,7 @@ int main(int argc, char **argv) { be_thread_params.fw_tpm = TRUE; be_thread_params.fw_tx_ipc_h = NULL; be_thread_params.fw_rx_ipc_h = &rx_tpm_ipc_h; - be_thread_params.is_priv = TRUE; //FIXME: Change when HP is up + be_thread_params.is_priv = FALSE; be_thread_params.thread_name = "Backend Listener"; dmi_thread_params.tx_ipc_h = NULL; @@ -318,7 +320,7 @@ int main(int argc, char **argv) { dmi_thread_params.fw_tx_ipc_h = NULL; dmi_thread_params.fw_rx_ipc_h = NULL; dmi_thread_params.is_priv = FALSE; - dmi_thread_params.thread_name = "VTPM Listeners"; + dmi_thread_params.thread_name = "VTPM Listener"; hp_thread_params.tx_ipc_h = &tx_hp_ipc_h; hp_thread_params.rx_ipc_h = &rx_hp_ipc_h; @@ -345,10 +347,10 @@ int main(int argc, char **argv) { } -// if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_params) != 0) { -// vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); -// exit(-1); -// } + if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_params) != 0) { + vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); + exit(-1); + } //Join the other threads until exit time. pthread_join(be_thread, NULL); diff --git a/tools/vtpm_manager/manager/vtpmpriv.h b/tools/vtpm_manager/manager/vtpmpriv.h index 84ace076dd..1296b1b8e5 100644 --- a/tools/vtpm_manager/manager/vtpmpriv.h +++ b/tools/vtpm_manager/manager/vtpmpriv.h @@ -40,15 +40,19 @@ #ifndef __VTPMPRIV_H__ #define __VTPMPRIV_H__ +#include "vtpm_manager.h" #include "tcg.h" #include "tcs.h" #include "buffer.h" #include "crypto.h" #include "vtpm_ipc.h" -#define STATE_FILE "/var/vtpm/VTPM" -#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" -#define VTPM_CTL_DM 0 +#define VTPM_MANAGER_GEN 2 // This is incremented when the manager's table + // is changed. It's used for backwards compatability + +#define STATE_FILE "/var/vtpm/VTPM" +#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" +#define VTPM_CTL_DM 0 // ------------------------ Private Structures ----------------------- typedef struct VTPM_DMI_RESOURCE_T { @@ -70,6 +74,7 @@ typedef struct VTPM_DMI_RESOURCE_T { // of NVM. // Persistent Information about DMI UINT32 dmi_id; + BYTE dmi_type; TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the blob TPM_DIGEST DMI_measurement; // Correct measurement of the owning DMI } VTPM_DMI_RESOURCE; @@ -138,7 +143,7 @@ TPM_RESULT VTPM_Handle_Delete_DMI(const buffer_t *param_buf); TPM_RESULT VTPM_SaveManagerData(void); TPM_RESULT VTPM_LoadManagerData(void); -TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res); +TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE startup_mode); TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res); diff --git a/tools/vtpm_manager/manager/vtsp.c b/tools/vtpm_manager/manager/vtsp.c index 70a20cf616..f7408c6457 100644 --- a/tools/vtpm_manager/manager/vtsp.c +++ b/tools/vtpm_manager/manager/vtsp.c @@ -971,6 +971,17 @@ TPM_RESULT VTSP_Unseal(const TCS_CONTEXT_HANDLE hContext, return status; } +TPM_RESULT VTSP_SaveState( const TCS_CONTEXT_HANDLE hContext) { + + vtpmloginfo(VTPM_LOG_VTSP, "Calling TPM_SaveState.\n"); + + TPM_RESULT status = TPM_SUCCESS; + + // Call TCS + return ( TCSP_SaveState ( hContext ) ); + +} + // Function Reaches into unsupported TCS command, beware. TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext, diff --git a/tools/vtpm_manager/manager/vtsp.h b/tools/vtpm_manager/manager/vtsp.h index 5baa2a377c..90077c2ec1 100644 --- a/tools/vtpm_manager/manager/vtsp.h +++ b/tools/vtpm_manager/manager/vtsp.h @@ -118,4 +118,6 @@ TPM_RESULT VTSP_Unseal(const TCS_CONTEXT_HANDLE hContext, TCS_AUTH *auth, TCS_AUTH *dataAuth); +TPM_RESULT VTSP_SaveState( const TCS_CONTEXT_HANDLE hContext); + #endif //_VTSP_H_ diff --git a/tools/vtpm_manager/tcs/tcs.c b/tools/vtpm_manager/tcs/tcs.c index 376a11eb20..6ed019dd41 100644 --- a/tools/vtpm_manager/tcs/tcs.c +++ b/tools/vtpm_manager/tcs/tcs.c @@ -1126,6 +1126,49 @@ TPM_RESULT TCSP_ReadPubek(TCS_CONTEXT_HANDLE hContext, // in return(returnCode); } + +TPM_RESULT TCSP_SaveState(TCS_CONTEXT_HANDLE hContext) // in +{ + // setup input/output parameters block + TPM_TAG tag = TPM_TAG_RQU_COMMAND; + UINT32 paramSize = 0; + TPM_COMMAND_CODE ordinal = TPM_ORD_SaveState; + TPM_RESULT returnCode = TPM_SUCCESS; + + // setup the TPM driver input and output buffers + TDDL_RESULT hRes = TDDL_E_FAIL; + TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH; + TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH; + + // Convert Byte Input parameter in the input byte stream InBuf + InLength = BSG_PackList(InBuf, 3, + BSG_TPM_TAG, &tag, + BSG_TYPE_UINT32, ¶mSize, + BSG_TPM_COMMAND_CODE, &ordinal); + // fill paramSize again as we now have the correct size + BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2); + + vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength); + + // call the TPM driver + if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) { + // unpack OutBuf to get the tag, paramSize, & returnCode + BSG_UnpackList(OutBuf, 3, + BSG_TPM_TAG, &tag, + BSG_TYPE_UINT32, ¶mSize, + BSG_TPM_COMMAND_CODE, &returnCode); + + if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) { + vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize); + } else { + vtpmlogerror(VTPM_LOG_TCS, "TCSP_SaveState Failed with return code %s\n", tpm_get_error_name(returnCode)); + } + } + + return(returnCode); +} + + TPM_RESULT TCSP_RawTransmitData( UINT32 inDataSize, // in BYTE *inData, // in UINT32 *outDataSize,// in/out diff --git a/tools/vtpm_manager/tcs/tcs.h b/tools/vtpm_manager/tcs/tcs.h index 49e4b34543..83b9cd0709 100644 --- a/tools/vtpm_manager/tcs/tcs.h +++ b/tools/vtpm_manager/tcs/tcs.h @@ -229,7 +229,10 @@ TPM_RESULT TCSP_ReadPubek ( TCS_CONTEXT_HANDLE hContext, // in ); -// Non-Standard TCSP call to give direct access to TransmitData. +// Non-Standard TCSP calls +TPM_RESULT TCSP_SaveState(TCS_CONTEXT_HANDLE hContext); // in + +//Give direct access to TransmitData. // Key and Auth Management is done before transfering command to TDDL. TPM_RESULT TCSP_RawTransmitData(UINT32 inDataSize, // in BYTE *inData, // in diff --git a/tools/vtpm_manager/util/tcg.h b/tools/vtpm_manager/util/tcg.h index 79f31ba688..f529e82a76 100644 --- a/tools/vtpm_manager/util/tcg.h +++ b/tools/vtpm_manager/util/tcg.h @@ -389,6 +389,11 @@ typedef struct pack_constbuf_t { #define TPM_DELEGATE_ADMIN TPM_BASE + 77 // Delegation table management not enabled #define TPM_TRANSPORT_EXCLUSIVE TPM_BASE + 78 // There was a command executed outside of an exclusive transport session +// TPM_STARTUP_TYPE values +#define TPM_ST_CLEAR 0x0001 +#define TPM_ST_STATE 0x0002 +#define TPM_ST_DEACTIVATED 0x003 + // TPM_TAG values #define TPM_TAG_RQU_COMMAND 0x00c1 #define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2