* [PATCH RFC] stubdom: Change vTPM shared page ABI
@ 2012-11-20 16:11 Daniel De Graaf
  2012-11-20 16:16 ` Fioravante, Matthew E.
  2012-11-27 14:38 ` Matthew Fioravante
  0 siblings, 2 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-20 16:11 UTC (permalink / raw)
  To: matthew.fioravante; +Cc: Daniel De Graaf, Ian.Campbell, xen-devel
Since the vTPM implementations are being incorproated into Xen and
possibly upstream Linux, I would like to see if this protocol change
could be added before we have significant legacy implementations. If
not, I still think it would be useful as either a v2 or negotiated
protocol change.
The current vTPM protocol is a copy of the network protocol. This was
likely done for ease of implementation, since support for the network
backend/frontend existed in Linux and minios. However, this
implementation is overly complex when dealing with vTPM packets: for
example, a vTPM never needs to deal with having more than one packet in
flight at any given time.
I will send the corresponding patch for the Linux kernel module once I
have adapted it for the file names used in the upstream version.
------------------------------------>8----------------------------------
This changes the vTPM shared page ABI from a copy of the Xen network
interface to a single-page interface that better reflects the expected
behavior of a TPM: only a single request packet can be sent at any given
time, and every packet sent generates a single response packet. This
protocol change should also increase efficiency as it avoids mapping and
unmapping grants when possible.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
   |   1 +
  |   7 +-
           | 132 ++++++++++++++-------------------
          | 150 +++++++++++++++++++-------------------
 xen/include/public/io/tpmif.h     |  45 +++---------
 5 files changed, 148 insertions(+), 187 deletions(-)
 --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
index ff86732..ec9eda4 100644
--- a/extras/mini-os/include/tpmback.h
+++ b/extras/mini-os/include/tpmback.h
@@ -43,6 +43,7 @@
 
 struct tpmcmd {
    domid_t domid;		/* Domid of the frontend */
+   uint8_t locality;    /* Locality requested by the frontend */
    unsigned int handle;	/* Handle of the frontend */
    unsigned char uuid[16];			/* uuid of the tpm interface */
 
 --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
index fd2cb17..a0c7c4d 100644
--- a/extras/mini-os/include/tpmfront.h
+++ b/extras/mini-os/include/tpmfront.h
@@ -37,9 +37,7 @@ struct tpmfront_dev {
    grant_ref_t ring_ref;
    evtchn_port_t evtchn;
 
-   tpmif_tx_interface_t* tx;
-
-   void** pages;
+   vtpm_shared_page_t *page;
 
    domid_t bedomid;
    char* nodename;
@@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
  * */
 int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
 
+/* Set the locality used for communicating with a vTPM */
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
+
 #ifdef HAVE_LIBC
 #include <sys/stat.h>
 /* POSIX IO functions:
 --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
index 658fed1..29aced9 100644
--- a/extras/mini-os/tpmback.c
+++ b/extras/mini-os/tpmback.c
@@ -86,10 +86,7 @@ struct tpmif {
    evtchn_port_t evtchn;
 
    /* Shared page */
-   tpmif_tx_interface_t* tx;
-
-   /* pointer to TPMIF_RX_RING_SIZE pages */
-   void** pages;
+   vtpm_shared_page_t *page;
 
    enum xenbus_state state;
    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
@@ -386,8 +383,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
    tpmif->fe_state_path = NULL;
    tpmif->state = XenbusStateInitialising;
    tpmif->status = DISCONNECTED;
-   tpmif->tx = NULL;
-   tpmif->pages = NULL;
+   tpmif->page = NULL;
    tpmif->flags = 0;
    memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
    return tpmif;
@@ -395,9 +391,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
 
 void __free_tpmif(tpmif_t* tpmif)
 {
-   if(tpmif->pages) {
-      free(tpmif->pages);
-   }
    if(tpmif->fe_path) {
       free(tpmif->fe_path);
    }
@@ -430,12 +423,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
       goto error;
    }
 
-   /* allocate pages to be used for shared mapping */
-   if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
-      goto error;
-   }
-   memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
-
    if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
       goto error;
    }
@@ -486,7 +473,7 @@ void free_tpmif(tpmif_t* tpmif)
       tpmif->status = DISCONNECTING;
       mask_evtchn(tpmif->evtchn);
 
-      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1)) {
+      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
 	 TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
       }
 
@@ -529,9 +516,10 @@ void free_tpmif(tpmif_t* tpmif)
 void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
 {
    tpmif_t* tpmif = (tpmif_t*) data;
-   tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
-   /* Throw away 0 size events, these can trigger from event channel unmasking */
-   if(tx->size == 0)
+   vtpm_shared_page_t* pg = tpmif->page;
+
+   /* Only pay attention if the request is ready */
+   if (pg->state == 0)
       return;
 
    TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
@@ -585,11 +573,10 @@ int connect_fe(tpmif_t* tpmif)
    free(value);
 
    domid = tpmif->domid;
-   if((tpmif->tx = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
+   if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
       TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
       return -1;
    }
-   memset(tpmif->tx, 0, PAGE_SIZE);
 
    /*Bind the event channel */
    if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
@@ -618,10 +605,28 @@ error_post_evtchn:
    mask_evtchn(tpmif->evtchn);
    unbind_evtchn(tpmif->evtchn);
 error_post_map:
-   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1);
+   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
    return -1;
 }
 
+static void disconnect_fe(tpmif_t* tpmif)
+{
+   if (tpmif->status == CONNECTED) {
+      tpmif->status = DISCONNECTING;
+      mask_evtchn(tpmif->evtchn);
+
+      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
+	 TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
+      }
+
+      unbind_evtchn(tpmif->evtchn);
+   }
+   tpmif->status = DISCONNECTED;
+   tpmif_change_state(tpmif, XenbusStateReconfigured);
+
+   TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
+}
+
 static int frontend_changed(tpmif_t* tpmif)
 {
    int state = xenbus_read_integer(tpmif->fe_state_path);
@@ -874,6 +879,7 @@ void shutdown_tpmback(void)
 inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, unsigned char uuid[16])
 {
    tpmcmd->domid = domid;
+   tpmcmd->locality = -1;
    tpmcmd->handle = handle;
    memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
    tpmcmd->req = NULL;
@@ -884,12 +890,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, un
 
 tpmcmd_t* get_request(tpmif_t* tpmif) {
    tpmcmd_t* cmd;
-   tpmif_tx_request_t* tx;
-   int offset;
-   int tocopy;
-   int i;
-   uint32_t domid;
+   vtpm_shared_page_t* shr;
+   unsigned int offset;
    int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+int i;
+#endif
 
    local_irq_save(flags);
 
@@ -899,35 +905,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
    }
    init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
 
-   tx = &tpmif->tx->ring[0].req;
-   cmd->req_len = tx->size;
+   shr = tpmif->page;
+   cmd->req_len = shr->length;
+   cmd->locality = shr->locality;
+   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+   if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
+      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+      goto error;
+   }
    /* Allocate the buffer */
    if(cmd->req_len) {
       if((cmd->req = malloc(cmd->req_len)) == NULL) {
 	 goto error;
       }
    }
-   /* Copy the bits from the shared pages */
-   offset = 0;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
-      tx = &tpmif->tx->ring[i].req;
-
-      /* Map the page with the data */
-      domid = (uint32_t)tpmif->domid;
-      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_READ)) == NULL) {
-	 TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", (unsigned int) tpmif->domid, tpmif->handle);
-	 goto error;
-      }
-
-      /* do the copy now */
-      tocopy = min(cmd->req_len - offset, PAGE_SIZE);
-      memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
-      offset += tocopy;
-
-      /* release the page */
-      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
-
-   }
+   /* Copy the bits from the shared page(s) */
+   memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
 
 #ifdef TPMBACK_PRINT_DEBUG
    TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
@@ -958,38 +951,24 @@ error:
 
 void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
 {
-   tpmif_tx_request_t* tx;
-   int offset;
-   int i;
-   uint32_t domid;
-   int tocopy;
+   vtpm_shared_page_t* shr;
+   unsigned int offset;
    int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+int i;
+#endif
 
    local_irq_save(flags);
 
-   tx = &tpmif->tx->ring[0].req;
-   tx->size = cmd->resp_len;
-
-   offset = 0;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
-      tx = &tpmif->tx->ring[i].req;
-
-      /* Map the page with the data */
-      domid = (uint32_t)tpmif->domid;
-      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_WRITE)) == NULL) {
-	 TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", (unsigned int) tpmif->domid, tpmif->handle);
-	 goto error;
-      }
-
-      /* do the copy now */
-      tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
-      memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
-      offset += tocopy;
-
-      /* release the page */
-      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
+   shr = tpmif->page;
+   shr->length = cmd->resp_len;
 
+   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+   if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
+      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+      goto error;
    }
+   memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
 
 #ifdef TPMBACK_PRINT_DEBUG
    TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
@@ -1003,6 +982,7 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
 #endif
    /* clear the ready flag and send the event channel notice to the frontend */
    tpmif_req_finished(tpmif);
+   shr->state = 0;
    notify_remote_via_evtchn(tpmif->evtchn);
 error:
    local_irq_restore(flags);
 --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index 0218d7f..bcee93d 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -153,6 +153,32 @@ static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
 
 }
 
+static int wait_for_backend_reconfig(xenbus_event_queue* events, char* path)
+{
+   int state;
+
+   TPMFRONT_LOG("Waiting for backend to reconfigure...\n");
+   while(1) {
+      state = xenbus_read_integer(path);
+      if ( state < 0)
+	 state = XenbusStateUnknown;
+      switch(state) {
+	 case XenbusStateUnknown:
+	    TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
+	    return -1;
+	 case XenbusStateClosed:
+	    TPMFRONT_LOG("Backend Closed\n");
+	    return 0;
+	 case XenbusStateReconfigured:
+	    TPMFRONT_LOG("Backend Reconfigured\n");
+	    return 0;
+	 default:
+	    xenbus_wait_for_watch(events);
+      }
+   }
+
+}
+
 static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
    char* err;
    int ret = 0;
@@ -175,8 +201,11 @@ static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState
       case XenbusStateClosed:
 	 ret = wait_for_backend_closed(&events, path);
 	 break;
-      default:
+      case XenbusStateReconfigured:
+	 ret = wait_for_backend_reconfig(&events, path);
 	 break;
+      default:
+         TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
    }
 
    if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
@@ -190,13 +219,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)
 {
    char* err;
    /* Create shared page */
-   dev->tx = (tpmif_tx_interface_t*) alloc_page();
-   if(dev->tx == NULL) {
+   dev->page = (vtpm_shared_page_t*) alloc_page();
+   if(dev->page == NULL) {
       TPMFRONT_ERR("Unable to allocate page for shared memory\n");
       goto error;
    }
-   memset(dev->tx, 0, PAGE_SIZE);
-   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 0);
+   memset(dev->page, 0, PAGE_SIZE);
+   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
    TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
 
    /*Create event channel */
@@ -228,7 +257,7 @@ error_postevtchn:
       unbind_evtchn(dev->evtchn);
 error_postmap:
       gnttab_end_access(dev->ring_ref);
-      free_page(dev->tx);
+      free_page(dev->page);
 error:
    return -1;
 }
@@ -240,7 +269,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
    char path[512];
    char* value, *err;
    unsigned long long ival;
-   int i;
 
    printk("============= Init TPM Front ================\n");
 
@@ -289,19 +317,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
       goto error;
    }
 
-   /* Allocate pages that will contain the messages */
-   dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
-   if(dev->pages == NULL) {
-      goto error;
-   }
-   memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
-   for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
-      dev->pages[i] = (void*)alloc_page();
-      if(dev->pages[i] == NULL) {
-	 goto error;
-      }
-   }
-
    TPMFRONT_LOG("Initialization Completed successfully\n");
 
    return dev;
@@ -314,12 +329,10 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
 {
    char* err;
    char path[512];
-   int i;
-   tpmif_tx_request_t* tx;
    if(dev == NULL) {
       return;
    }
-   TPMFRONT_LOG("Shutting down tpmfront\n");
+   TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
    /* disconnect */
    if(dev->state == XenbusStateConnected) {
       dev->state = XenbusStateClosing;
@@ -349,27 +362,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
       /* Wait for the backend to close and unmap shared pages, ignore any errors */
       wait_for_backend_state_changed(dev, XenbusStateClosed);
 
-      /* Cleanup any shared pages */
-      if(dev->pages) {
-	 for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
-	    if(dev->pages[i]) {
-	       tx = &dev->tx->ring[i].req;
-	       if(tx->ref != 0) {
-		  gnttab_end_access(tx->ref);
-	       }
-	       free_page(dev->pages[i]);
-	    }
-	 }
-	 free(dev->pages);
-      }
-
       /* Close event channel and unmap shared page */
       mask_evtchn(dev->evtchn);
       unbind_evtchn(dev->evtchn);
       gnttab_end_access(dev->ring_ref);
 
-      free_page(dev->tx);
-
+      free_page(dev->page);
    }
 
    /* Cleanup memory usage */
@@ -387,13 +385,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
 
 int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
 {
-   int i;
-   tpmif_tx_request_t* tx = NULL;
+   unsigned int offset;
+   vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+int i;
+#endif
    /* Error Checking */
    if(dev == NULL || dev->state != XenbusStateConnected) {
       TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
       return -1;
    }
+   shr = dev->page;
 
 #ifdef TPMFRONT_PRINT_DEBUG
    TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
@@ -407,19 +409,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
 #endif
 
    /* Copy to shared pages now */
-   for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
-      /* Share the page */
-      tx = &dev->tx->ring[i].req;
-      tx->unused = 0;
-      tx->addr = virt_to_mach(dev->pages[i]);
-      tx->ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->pages[i]), 0);
-      /* Copy the bits to the page */
-      tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
-      memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
-
-      /* Update counters */
-      length -= tx->size;
+   offset = sizeof(*shr);
+   if (length + offset > PAGE_SIZE) {
+      TPMFRONT_ERR("Message too long for shared page\n");
+      return -1;
    }
+   memcpy(offset + (uint8_t*)shr, msg, length);
+   shr->length = length;
+   barrier();
+   shr->state = 1;
+
    dev->waiting = 1;
    dev->resplen = 0;
 #ifdef HAVE_LIBC
@@ -434,44 +433,41 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
 }
 int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
 {
-   tpmif_tx_request_t* tx;
-   int i;
+   unsigned int offset;
+   vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+int i;
+#endif
    if(dev == NULL || dev->state != XenbusStateConnected) {
       TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
       return -1;
    }
    /*Wait for the response */
    wait_event(dev->waitq, (!dev->waiting));
+   shr = dev->page;
+   if (shr->state != 0)
+      goto quit;
 
    /* Initialize */
    *msg = NULL;
-   *length = 0;
+   *length = shr->length;
+   offset = sizeof(*shr);
 
-   /* special case, just quit */
-   tx = &dev->tx->ring[0].req;
-   if(tx->size == 0 ) {
-       goto quit;
-   }
-   /* Get the total size */
-   tx = &dev->tx->ring[0].req;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
-      tx = &dev->tx->ring[i].req;
-      *length += tx->size;
+   if (*length + offset > PAGE_SIZE) {
+      TPMFRONT_ERR("Reply too long for shared page\n");
+      return -1;
    }
+
    /* Alloc the buffer */
    if(dev->respbuf) {
       free(dev->respbuf);
    }
    *msg = dev->respbuf = malloc(*length);
    dev->resplen = *length;
+
    /* Copy the bits */
-   tx = &dev->tx->ring[0].req;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
-      tx = &dev->tx->ring[i].req;
-      memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
-      gnttab_end_access(tx->ref);
-      tx->ref = 0;
-   }
+   memcpy(*msg, offset + (uint8_t*)shr, *length);
+
 #ifdef TPMFRONT_PRINT_DEBUG
    TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
    for(i = 0; i < *length; ++i) {
@@ -504,6 +500,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t*
    return 0;
 }
 
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
+{
+   if (!dev || !dev->page)
+      return -1;
+   dev->page->locality = locality;
+   return 0;
+}
+
 #ifdef HAVE_LIBC
 #include <errno.h>
 int tpmfront_open(struct tpmfront_dev* dev)
diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h
index 02ccdab..afc9181 100644
--- a/xen/include/public/io/tpmif.h
+++ b/xen/include/public/io/tpmif.h
@@ -1,7 +1,7 @@
 /******************************************************************************
  * tpmif.h
  *
- * TPM I/O interface for Xen guest OSes.
+ * TPM I/O interface for Xen guest OSes, v2
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -21,48 +21,23 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Copyright (c) 2005, IBM Corporation
- *
- * Author: Stefan Berger, stefanb@us.ibm.com
- * Grant table support: Mahadevan Gomathisankaran
- *
- * This code has been derived from tools/libxc/xen/io/netif.h
- *
- * Copyright (c) 2003-2004, Keir Fraser
  */
 
 #ifndef __XEN_PUBLIC_IO_TPMIF_H__
 #define __XEN_PUBLIC_IO_TPMIF_H__
 
-#include "../grant_table.h"
+struct vtpm_shared_page {
+    uint16_t length;         /* request/response length in bytes */
 
-struct tpmif_tx_request {
-    unsigned long addr;   /* Machine address of packet.   */
-    grant_ref_t ref;      /* grant table access reference */
-    uint16_t unused;
-    uint16_t size;        /* Packet size in bytes.        */
-};
-typedef struct tpmif_tx_request tpmif_tx_request_t;
-
-/*
- * The TPMIF_TX_RING_SIZE defines the number of pages the
- * front-end and backend can exchange (= size of array).
- */
-typedef uint32_t TPMIF_RING_IDX;
-
-#define TPMIF_TX_RING_SIZE 1
-
-/* This structure must fit in a memory page. */
-
-struct tpmif_ring {
-    struct tpmif_tx_request req;
-};
-typedef struct tpmif_ring tpmif_ring_t;
+    uint8_t state;           /* 0 - response ready / idle
+                              * 1 - request ready / working */
+    uint8_t locality;        /* for the current request */
+    uint8_t padding[3];
 
-struct tpmif_tx_interface {
-    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
+    uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
+    uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
 };
-typedef struct tpmif_tx_interface tpmif_tx_interface_t;
+typedef struct vtpm_shared_page vtpm_shared_page_t;
 
 #endif
 
-- 
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-20 16:11 [PATCH RFC] stubdom: Change vTPM shared page ABI Daniel De Graaf
@ 2012-11-20 16:16 ` Fioravante, Matthew E.
  2012-11-20 18:24   ` [PATCH] drivers/tpm-xen: " Daniel De Graaf
  2012-11-23 11:04   ` [PATCH RFC] stubdom: " Ian Campbell
  2012-11-27 14:38 ` Matthew Fioravante
  1 sibling, 2 replies; 53+ messages in thread
From: Fioravante, Matthew E. @ 2012-11-20 16:16 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
This was something I've been wanting to do for a while so I'm very happy you went ahead and fixed it yourself. Once you submit the linux version I'll test it on my system.
Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
-----Original Message-----
From: Daniel De Graaf [mailto:dgdegra@tycho.nsa.gov]
Sent: Tuesday, November 20, 2012 11:11 AM
To: Fioravante, Matthew E.
Cc: xen-devel@lists.xen.org; Ian.Campbell@citrix.com; Daniel De Graaf
Subject: [PATCH RFC] stubdom: Change vTPM shared page ABI
Since the vTPM implementations are being incorproated into Xen and possibly upstream Linux, I would like to see if this protocol change could be added before we have significant legacy implementations. If not, I still think it would be useful as either a v2 or negotiated protocol change.
The current vTPM protocol is a copy of the network protocol. This was likely done for ease of implementation, since support for the network backend/frontend existed in Linux and minios. However, this implementation is overly complex when dealing with vTPM packets: for example, a vTPM never needs to deal with having more than one packet in flight at any given time.
I will send the corresponding patch for the Linux kernel module once I have adapted it for the file names used in the upstream version.
------------------------------------>8----------------------------------
This changes the vTPM shared page ABI from a copy of the Xen network interface to a single-page interface that better reflects the expected behavior of a TPM: only a single request packet can be sent at any given time, and every packet sent generates a single response packet. This protocol change should also increase efficiency as it avoids mapping and unmapping grants when possible.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
   |   1 +
  |   7 +-
           | 132 ++++++++++++++-------------------
          | 150 +++++++++++++++++++-------------------
 xen/include/public/io/tpmif.h     |  45 +++---------
 5 files changed, 148 insertions(+), 187 deletions(-)
 --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
index ff86732..ec9eda4 100644
--- a/extras/mini-os/include/tpmback.h
+++ b/extras/mini-os/include/tpmback.h
@@ -43,6 +43,7 @@
 struct tpmcmd {
    domid_t domid;              /* Domid of the frontend */
+   uint8_t locality;    /* Locality requested by the frontend */
    unsigned int handle;        /* Handle of the frontend */
    unsigned char uuid[16];                     /* uuid of the tpm interface */
 --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
index fd2cb17..a0c7c4d 100644
--- a/extras/mini-os/include/tpmfront.h
+++ b/extras/mini-os/include/tpmfront.h
@@ -37,9 +37,7 @@ struct tpmfront_dev {
    grant_ref_t ring_ref;
    evtchn_port_t evtchn;
-   tpmif_tx_interface_t* tx;
-
-   void** pages;
+   vtpm_shared_page_t *page;
    domid_t bedomid;
    char* nodename;
@@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
  * */
 int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
+/* Set the locality used for communicating with a vTPM */ int
+tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
+
 #ifdef HAVE_LIBC
 #include <sys/stat.h>
 /* POSIX IO functions:
diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c index 658fed1..29aced9 100644
--- a/extras/mini-os/tpmback.c
+++ b/extras/mini-os/tpmback.c
@@ -86,10 +86,7 @@ struct tpmif {
    evtchn_port_t evtchn;
    /* Shared page */
-   tpmif_tx_interface_t* tx;
-
-   /* pointer to TPMIF_RX_RING_SIZE pages */
-   void** pages;
+   vtpm_shared_page_t *page;
    enum xenbus_state state;
    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; @@ -386,8 +383,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
    tpmif->fe_state_path = NULL;
    tpmif->state = XenbusStateInitialising;
    tpmif->status = DISCONNECTED;
-   tpmif->tx = NULL;
-   tpmif->pages = NULL;
+   tpmif->page = NULL;
    tpmif->flags = 0;
    memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
    return tpmif;
@@ -395,9 +391,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
 void __free_tpmif(tpmif_t* tpmif)
 {
-   if(tpmif->pages) {
-      free(tpmif->pages);
-   }
    if(tpmif->fe_path) {
       free(tpmif->fe_path);
    }
@@ -430,12 +423,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
       goto error;
    }
-   /* allocate pages to be used for shared mapping */
-   if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
-      goto error;
-   }
-   memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
-
    if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
       goto error;
    }
@@ -486,7 +473,7 @@ void free_tpmif(tpmif_t* tpmif)
       tpmif->status = DISCONNECTING;
       mask_evtchn(tpmif->evtchn);
-      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1)) {
+      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
         TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
       }
@@ -529,9 +516,10 @@ void free_tpmif(tpmif_t* tpmif)  void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)  {
    tpmif_t* tpmif = (tpmif_t*) data;
-   tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
-   /* Throw away 0 size events, these can trigger from event channel unmasking */
-   if(tx->size == 0)
+   vtpm_shared_page_t* pg = tpmif->page;
+
+   /* Only pay attention if the request is ready */
+   if (pg->state == 0)
       return;
    TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle); @@ -585,11 +573,10 @@ int connect_fe(tpmif_t* tpmif)
    free(value);
    domid = tpmif->domid;
-   if((tpmif->tx = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
+   if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0,
+ &ringref, PROT_READ | PROT_WRITE)) == NULL) {
       TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
       return -1;
    }
-   memset(tpmif->tx, 0, PAGE_SIZE);
    /*Bind the event channel */
    if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn))) @@ -618,10 +605,28 @@ error_post_evtchn:
    mask_evtchn(tpmif->evtchn);
    unbind_evtchn(tpmif->evtchn);
 error_post_map:
-   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1);
+   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
    return -1;
 }
+static void disconnect_fe(tpmif_t* tpmif) {
+   if (tpmif->status == CONNECTED) {
+      tpmif->status = DISCONNECTING;
+      mask_evtchn(tpmif->evtchn);
+
+      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
+        TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
+      }
+
+      unbind_evtchn(tpmif->evtchn);
+   }
+   tpmif->status = DISCONNECTED;
+   tpmif_change_state(tpmif, XenbusStateReconfigured);
+
+   TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int)
+tpmif->domid, tpmif->handle); }
+
 static int frontend_changed(tpmif_t* tpmif)  {
    int state = xenbus_read_integer(tpmif->fe_state_path);
@@ -874,6 +879,7 @@ void shutdown_tpmback(void)  inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, unsigned char uuid[16])  {
    tpmcmd->domid = domid;
+   tpmcmd->locality = -1;
    tpmcmd->handle = handle;
    memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
    tpmcmd->req = NULL;
@@ -884,12 +890,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, un
 tpmcmd_t* get_request(tpmif_t* tpmif) {
    tpmcmd_t* cmd;
-   tpmif_tx_request_t* tx;
-   int offset;
-   int tocopy;
-   int i;
-   uint32_t domid;
+   vtpm_shared_page_t* shr;
+   unsigned int offset;
    int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+int i;
+#endif
    local_irq_save(flags);
@@ -899,35 +905,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
    }
    init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
-   tx = &tpmif->tx->ring[0].req;
-   cmd->req_len = tx->size;
+   shr = tpmif->page;
+   cmd->req_len = shr->length;
+   cmd->locality = shr->locality;
+   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+   if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
+      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+      goto error;
+   }
    /* Allocate the buffer */
    if(cmd->req_len) {
       if((cmd->req = malloc(cmd->req_len)) == NULL) {
         goto error;
       }
    }
-   /* Copy the bits from the shared pages */
-   offset = 0;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
-      tx = &tpmif->tx->ring[i].req;
-
-      /* Map the page with the data */
-      domid = (uint32_t)tpmif->domid;
-      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_READ)) == NULL) {
-        TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", (unsigned int) tpmif->domid, tpmif->handle);
-        goto error;
-      }
-
-      /* do the copy now */
-      tocopy = min(cmd->req_len - offset, PAGE_SIZE);
-      memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
-      offset += tocopy;
-
-      /* release the page */
-      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
-
-   }
+   /* Copy the bits from the shared page(s) */
+   memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
 #ifdef TPMBACK_PRINT_DEBUG
    TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len); @@ -958,38 +951,24 @@ error:
 void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
-   tpmif_tx_request_t* tx;
-   int offset;
-   int i;
-   uint32_t domid;
-   int tocopy;
+   vtpm_shared_page_t* shr;
+   unsigned int offset;
    int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+int i;
+#endif
    local_irq_save(flags);
-   tx = &tpmif->tx->ring[0].req;
-   tx->size = cmd->resp_len;
-
-   offset = 0;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
-      tx = &tpmif->tx->ring[i].req;
-
-      /* Map the page with the data */
-      domid = (uint32_t)tpmif->domid;
-      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_WRITE)) == NULL) {
-        TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", (unsigned int) tpmif->domid, tpmif->handle);
-        goto error;
-      }
-
-      /* do the copy now */
-      tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
-      memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
-      offset += tocopy;
-
-      /* release the page */
-      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
+   shr = tpmif->page;
+   shr->length = cmd->resp_len;
+   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+   if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
+      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+      goto error;
    }
+   memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
 #ifdef TPMBACK_PRINT_DEBUG
    TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len); @@ -1003,6 +982,7 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  #endif
    /* clear the ready flag and send the event channel notice to the frontend */
    tpmif_req_finished(tpmif);
+   shr->state = 0;
    notify_remote_via_evtchn(tpmif->evtchn);
 error:
    local_irq_restore(flags);
diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c index 0218d7f..bcee93d 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -153,6 +153,32 @@ static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
 }
+static int wait_for_backend_reconfig(xenbus_event_queue* events, char*
+path) {
+   int state;
+
+   TPMFRONT_LOG("Waiting for backend to reconfigure...\n");
+   while(1) {
+      state = xenbus_read_integer(path);
+      if ( state < 0)
+        state = XenbusStateUnknown;
+      switch(state) {
+        case XenbusStateUnknown:
+           TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
+           return -1;
+        case XenbusStateClosed:
+           TPMFRONT_LOG("Backend Closed\n");
+           return 0;
+        case XenbusStateReconfigured:
+           TPMFRONT_LOG("Backend Reconfigured\n");
+           return 0;
+        default:
+           xenbus_wait_for_watch(events);
+      }
+   }
+
+}
+
 static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
    char* err;
    int ret = 0;
@@ -175,8 +201,11 @@ static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState
       case XenbusStateClosed:
         ret = wait_for_backend_closed(&events, path);
         break;
-      default:
+      case XenbusStateReconfigured:
+        ret = wait_for_backend_reconfig(&events, path);
         break;
+      default:
+         TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
    }
    if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) { @@ -190,13 +219,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)  {
    char* err;
    /* Create shared page */
-   dev->tx = (tpmif_tx_interface_t*) alloc_page();
-   if(dev->tx == NULL) {
+   dev->page = (vtpm_shared_page_t*) alloc_page();
+   if(dev->page == NULL) {
       TPMFRONT_ERR("Unable to allocate page for shared memory\n");
       goto error;
    }
-   memset(dev->tx, 0, PAGE_SIZE);
-   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 0);
+   memset(dev->page, 0, PAGE_SIZE);
+   dev->ring_ref = gnttab_grant_access(dev->bedomid,
+ virt_to_mfn(dev->page), 0);
    TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
    /*Create event channel */
@@ -228,7 +257,7 @@ error_postevtchn:
       unbind_evtchn(dev->evtchn);
 error_postmap:
       gnttab_end_access(dev->ring_ref);
-      free_page(dev->tx);
+      free_page(dev->page);
 error:
    return -1;
 }
@@ -240,7 +269,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
    char path[512];
    char* value, *err;
    unsigned long long ival;
-   int i;
    printk("============= Init TPM Front ================\n");
@@ -289,19 +317,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
       goto error;
    }
-   /* Allocate pages that will contain the messages */
-   dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
-   if(dev->pages == NULL) {
-      goto error;
-   }
-   memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
-   for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
-      dev->pages[i] = (void*)alloc_page();
-      if(dev->pages[i] == NULL) {
-        goto error;
-      }
-   }
-
    TPMFRONT_LOG("Initialization Completed successfully\n");
    return dev;
@@ -314,12 +329,10 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)  {
    char* err;
    char path[512];
-   int i;
-   tpmif_tx_request_t* tx;
    if(dev == NULL) {
       return;
    }
-   TPMFRONT_LOG("Shutting down tpmfront\n");
+   TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for
+ reconfigure" : "");
    /* disconnect */
    if(dev->state == XenbusStateConnected) {
       dev->state = XenbusStateClosing;
@@ -349,27 +362,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
       /* Wait for the backend to close and unmap shared pages, ignore any errors */
       wait_for_backend_state_changed(dev, XenbusStateClosed);
-      /* Cleanup any shared pages */
-      if(dev->pages) {
-        for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
-           if(dev->pages[i]) {
-              tx = &dev->tx->ring[i].req;
-              if(tx->ref != 0) {
-                 gnttab_end_access(tx->ref);
-              }
-              free_page(dev->pages[i]);
-           }
-        }
-        free(dev->pages);
-      }
-
       /* Close event channel and unmap shared page */
       mask_evtchn(dev->evtchn);
       unbind_evtchn(dev->evtchn);
       gnttab_end_access(dev->ring_ref);
-      free_page(dev->tx);
-
+      free_page(dev->page);
    }
    /* Cleanup memory usage */
@@ -387,13 +385,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
 int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)  {
-   int i;
-   tpmif_tx_request_t* tx = NULL;
+   unsigned int offset;
+   vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+int i;
+#endif
    /* Error Checking */
    if(dev == NULL || dev->state != XenbusStateConnected) {
       TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
       return -1;
    }
+   shr = dev->page;
 #ifdef TPMFRONT_PRINT_DEBUG
    TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length); @@ -407,19 +409,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)  #endif
    /* Copy to shared pages now */
-   for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
-      /* Share the page */
-      tx = &dev->tx->ring[i].req;
-      tx->unused = 0;
-      tx->addr = virt_to_mach(dev->pages[i]);
-      tx->ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->pages[i]), 0);
-      /* Copy the bits to the page */
-      tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
-      memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
-
-      /* Update counters */
-      length -= tx->size;
+   offset = sizeof(*shr);
+   if (length + offset > PAGE_SIZE) {
+      TPMFRONT_ERR("Message too long for shared page\n");
+      return -1;
    }
+   memcpy(offset + (uint8_t*)shr, msg, length);
+   shr->length = length;
+   barrier();
+   shr->state = 1;
+
    dev->waiting = 1;
    dev->resplen = 0;
 #ifdef HAVE_LIBC
@@ -434,44 +433,41 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)  }  int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)  {
-   tpmif_tx_request_t* tx;
-   int i;
+   unsigned int offset;
+   vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+int i;
+#endif
    if(dev == NULL || dev->state != XenbusStateConnected) {
       TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
       return -1;
    }
    /*Wait for the response */
    wait_event(dev->waitq, (!dev->waiting));
+   shr = dev->page;
+   if (shr->state != 0)
+      goto quit;
    /* Initialize */
    *msg = NULL;
-   *length = 0;
+   *length = shr->length;
+   offset = sizeof(*shr);
-   /* special case, just quit */
-   tx = &dev->tx->ring[0].req;
-   if(tx->size == 0 ) {
-       goto quit;
-   }
-   /* Get the total size */
-   tx = &dev->tx->ring[0].req;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
-      tx = &dev->tx->ring[i].req;
-      *length += tx->size;
+   if (*length + offset > PAGE_SIZE) {
+      TPMFRONT_ERR("Reply too long for shared page\n");
+      return -1;
    }
+
    /* Alloc the buffer */
    if(dev->respbuf) {
       free(dev->respbuf);
    }
    *msg = dev->respbuf = malloc(*length);
    dev->resplen = *length;
+
    /* Copy the bits */
-   tx = &dev->tx->ring[0].req;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
-      tx = &dev->tx->ring[i].req;
-      memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
-      gnttab_end_access(tx->ref);
-      tx->ref = 0;
-   }
+   memcpy(*msg, offset + (uint8_t*)shr, *length);
+
 #ifdef TPMFRONT_PRINT_DEBUG
    TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
    for(i = 0; i < *length; ++i) {
@@ -504,6 +500,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t*
    return 0;
 }
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality) {
+   if (!dev || !dev->page)
+      return -1;
+   dev->page->locality = locality;
+   return 0;
+}
+
 #ifdef HAVE_LIBC
 #include <errno.h>
 int tpmfront_open(struct tpmfront_dev* dev) diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h index 02ccdab..afc9181 100644
--- a/xen/include/public/io/tpmif.h
+++ b/xen/include/public/io/tpmif.h
@@ -1,7 +1,7 @@
 /******************************************************************************
  * tpmif.h
  *
- * TPM I/O interface for Xen guest OSes.
+ * TPM I/O interface for Xen guest OSes, v2
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to @@ -21,48 +21,23 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Copyright (c) 2005, IBM Corporation
- *
- * Author: Stefan Berger, stefanb@us.ibm.com
- * Grant table support: Mahadevan Gomathisankaran
- *
- * This code has been derived from tools/libxc/xen/io/netif.h
- *
- * Copyright (c) 2003-2004, Keir Fraser
  */
 #ifndef __XEN_PUBLIC_IO_TPMIF_H__
 #define __XEN_PUBLIC_IO_TPMIF_H__
-#include "../grant_table.h"
+struct vtpm_shared_page {
+    uint16_t length;         /* request/response length in bytes */
-struct tpmif_tx_request {
-    unsigned long addr;   /* Machine address of packet.   */
-    grant_ref_t ref;      /* grant table access reference */
-    uint16_t unused;
-    uint16_t size;        /* Packet size in bytes.        */
-};
-typedef struct tpmif_tx_request tpmif_tx_request_t;
-
-/*
- * The TPMIF_TX_RING_SIZE defines the number of pages the
- * front-end and backend can exchange (= size of array).
- */
-typedef uint32_t TPMIF_RING_IDX;
-
-#define TPMIF_TX_RING_SIZE 1
-
-/* This structure must fit in a memory page. */
-
-struct tpmif_ring {
-    struct tpmif_tx_request req;
-};
-typedef struct tpmif_ring tpmif_ring_t;
+    uint8_t state;           /* 0 - response ready / idle
+                              * 1 - request ready / working */
+    uint8_t locality;        /* for the current request */
+    uint8_t padding[3];
-struct tpmif_tx_interface {
-    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
+    uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
+    uint32_t extra_pages[0]; /* grant IDs; length is actually
+ nr_extra_pages */
 };
-typedef struct tpmif_tx_interface tpmif_tx_interface_t;
+typedef struct vtpm_shared_page vtpm_shared_page_t;
 #endif
--
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* [PATCH] drivers/tpm-xen: Change vTPM shared page ABI
  2012-11-20 16:16 ` Fioravante, Matthew E.
@ 2012-11-20 18:24   ` Daniel De Graaf
  2012-11-23 11:04   ` [PATCH RFC] stubdom: " Ian Campbell
  1 sibling, 0 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-20 18:24 UTC (permalink / raw)
  To: Matthew.Fioravante
  Cc: jeremy, Ian.Campbell, konrad.wilk, xen-devel, tpmdd-devel,
	Daniel De Graaf
This changes the vTPM shared page ABI from a copy of the Xen network
interface to a single-page interface that better reflects the expected
behavior of a TPM: only a single request packet can be sent at any given
time, and every packet sent generates a single response packet. This
protocol change should also increase efficiency as it avoids mapping and
unmapping grants when possible.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
 drivers/char/tpm/xen-tpmfront_if.c | 191 ++++++-------------------------------
 include/xen/interface/io/tpmif.h   |  42 ++------
 2 files changed, 40 insertions(+), 193 deletions(-)
diff --git a/drivers/char/tpm/xen-tpmfront_if.c b/drivers/char/tpm/xen-tpmfront_if.c
index ba7fad8..02405af 100644
--- a/drivers/char/tpm/xen-tpmfront_if.c
+++ b/drivers/char/tpm/xen-tpmfront_if.c
@@ -53,7 +53,7 @@
 struct tpm_private {
 	struct tpm_chip *chip;
 
-	struct tpmif_tx_interface *tx;
+	struct vtpm_shared_page *page;
 	atomic_t refcnt;
 	unsigned int evtchn;
 	u8 is_connected;
@@ -61,8 +61,6 @@ struct tpm_private {
 
 	spinlock_t tx_lock;
 
-	struct tx_buffer *tx_buffers[TPMIF_TX_RING_SIZE];
-
 	atomic_t tx_busy;
 	void *tx_remember;
 
@@ -73,15 +71,7 @@ struct tpm_private {
 	int ring_ref;
 };
 
-struct tx_buffer {
-	unsigned int size;	/* available space in data */
-	unsigned int len;	/* used space in data */
-	unsigned char *data;	/* pointer to a page */
-};
-
-
 /* locally visible variables */
-static grant_ref_t gref_head;
 static struct tpm_private *my_priv;
 
 /* local function prototypes */
@@ -92,8 +82,6 @@ static int tpmif_connect(struct xenbus_device *dev,
 		struct tpm_private *tp,
 		domid_t domid);
 static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
-static int tpmif_allocate_tx_buffers(struct tpm_private *tp);
-static void tpmif_free_tx_buffers(struct tpm_private *tp);
 static void tpmif_set_connected_state(struct tpm_private *tp,
 		u8 newstate);
 static int tpm_xmit(struct tpm_private *tp,
@@ -101,52 +89,6 @@ static int tpm_xmit(struct tpm_private *tp,
 		void *remember);
 static void destroy_tpmring(struct tpm_private *tp);
 
-static inline int
-tx_buffer_copy(struct tx_buffer *txb, const u8 *src, int len,
-		int isuserbuffer)
-{
-	int copied = len;
-
-	if (len > txb->size)
-		copied = txb->size;
-	if (isuserbuffer) {
-		if (copy_from_user(txb->data, src, copied))
-			return -EFAULT;
-	} else {
-		memcpy(txb->data, src, copied);
-	}
-	txb->len = len;
-	return copied;
-}
-
-static inline struct tx_buffer *tx_buffer_alloc(void)
-{
-	struct tx_buffer *txb;
-
-	txb = kzalloc(sizeof(struct tx_buffer), GFP_KERNEL);
-	if (!txb)
-		return NULL;
-
-	txb->len = 0;
-	txb->size = PAGE_SIZE;
-	txb->data = (unsigned char *)__get_free_page(GFP_KERNEL);
-	if (txb->data == NULL) {
-		kfree(txb);
-		txb = NULL;
-	}
-
-	return txb;
-}
-
-
-static inline void tx_buffer_free(struct tx_buffer *txb)
-{
-	if (txb) {
-		free_page((long)txb->data);
-		kfree(txb);
-	}
-}
-
 /**************************************************************
   Utility function for the tpm_private structure
  **************************************************************/
@@ -162,15 +104,12 @@ static void tpm_private_put(void)
 	if (!atomic_dec_and_test(&my_priv->refcnt))
 		return;
 
-	tpmif_free_tx_buffers(my_priv);
 	kfree(my_priv);
 	my_priv = NULL;
 }
 
 static struct tpm_private *tpm_private_get(void)
 {
-	int err;
-
 	if (my_priv) {
 		atomic_inc(&my_priv->refcnt);
 		return my_priv;
@@ -181,9 +120,6 @@ static struct tpm_private *tpm_private_get(void)
 		return NULL;
 
 	tpm_private_init(my_priv);
-	err = tpmif_allocate_tx_buffers(my_priv);
-	if (err < 0)
-		tpm_private_put();
 
 	return my_priv;
 }
@@ -218,22 +154,22 @@ int vtpm_vd_send(struct tpm_private *tp,
 static int setup_tpmring(struct xenbus_device *dev,
 		struct tpm_private *tp)
 {
-	struct tpmif_tx_interface *sring;
+	struct vtpm_shared_page *sring;
 	int err;
 
 	tp->ring_ref = GRANT_INVALID_REF;
 
-	sring = (void *)__get_free_page(GFP_KERNEL);
+	sring = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 	if (!sring) {
 		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
 		return -ENOMEM;
 	}
-	tp->tx = sring;
+	tp->page = sring;
 
-	err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx));
+	err = xenbus_grant_ring(dev, virt_to_mfn(tp->page));
 	if (err < 0) {
 		free_page((unsigned long)sring);
-		tp->tx = NULL;
+		tp->page = NULL;
 		xenbus_dev_fatal(dev, err, "allocating grant reference");
 		goto fail;
 	}
@@ -256,9 +192,9 @@ static void destroy_tpmring(struct tpm_private *tp)
 
 	if (tp->ring_ref != GRANT_INVALID_REF) {
 		gnttab_end_foreign_access(tp->ring_ref,
-				0, (unsigned long)tp->tx);
+				0, (unsigned long)tp->page);
 		tp->ring_ref = GRANT_INVALID_REF;
-		tp->tx = NULL;
+		tp->page = NULL;
 	}
 
 	if (tp->evtchn)
@@ -470,62 +406,30 @@ static DEFINE_XENBUS_DRIVER(tpmfront, ,
 		.suspend = tpmfront_suspend,
 		);
 
-static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
-{
-	unsigned int i;
-
-	for (i = 0; i < TPMIF_TX_RING_SIZE; i++) {
-		tp->tx_buffers[i] = tx_buffer_alloc();
-		if (!tp->tx_buffers[i]) {
-			tpmif_free_tx_buffers(tp);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static void tpmif_free_tx_buffers(struct tpm_private *tp)
-{
-	unsigned int i;
-
-	for (i = 0; i < TPMIF_TX_RING_SIZE; i++)
-		tx_buffer_free(tp->tx_buffers[i]);
-}
-
 static void tpmif_rx_action(unsigned long priv)
 {
 	struct tpm_private *tp = (struct tpm_private *)priv;
-	int i = 0;
 	unsigned int received;
 	unsigned int offset = 0;
 	u8 *buffer;
-	struct tpmif_tx_request *tx = &tp->tx->ring[i].req;
+	struct vtpm_shared_page *shr = tp->page;
 
 	atomic_set(&tp->tx_busy, 0);
 	wake_up_interruptible(&tp->wait_q);
 
-	received = tx->size;
+	offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+	received = shr->length;
+
+	if (offset > PAGE_SIZE || offset + received > PAGE_SIZE) {
+		printk(KERN_WARNING "tpmif_rx_action packet too large\n");
+		return;
+	}
 
 	buffer = kmalloc(received, GFP_ATOMIC);
 	if (!buffer)
 		return;
 
-	for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) {
-		struct tx_buffer *txb = tp->tx_buffers[i];
-		struct tpmif_tx_request *tx;
-		unsigned int tocopy;
-
-		tx = &tp->tx->ring[i].req;
-		tocopy = tx->size;
-		if (tocopy > PAGE_SIZE)
-			tocopy = PAGE_SIZE;
-
-		memcpy(&buffer[offset], txb->data, tocopy);
-
-		gnttab_release_grant_reference(&gref_head, tx->ref);
-
-		offset += tocopy;
-	}
+	memcpy(buffer, offset + (u8*)shr, received);
 
 	vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
 	kfree(buffer);
@@ -550,8 +454,7 @@ static int tpm_xmit(struct tpm_private *tp,
 		const u8 *buf, size_t count, int isuserbuffer,
 		void *remember)
 {
-	struct tpmif_tx_request *tx;
-	int i;
+	struct vtpm_shared_page *shr;
 	unsigned int offset = 0;
 
 	spin_lock_irq(&tp->tx_lock);
@@ -566,48 +469,23 @@ static int tpm_xmit(struct tpm_private *tp,
 		return -EIO;
 	}
 
-	for (i = 0; count > 0 && i < TPMIF_TX_RING_SIZE; i++) {
-		struct tx_buffer *txb = tp->tx_buffers[i];
-		int copied;
-
-		if (!txb) {
-			spin_unlock_irq(&tp->tx_lock);
-			return -EFAULT;
-		}
-
-		copied = tx_buffer_copy(txb, &buf[offset], count,
-				isuserbuffer);
-		if (copied < 0) {
-			/* An error occurred */
-			spin_unlock_irq(&tp->tx_lock);
-			return copied;
-		}
-		count -= copied;
-		offset += copied;
-
-		tx = &tp->tx->ring[i].req;
-		tx->addr = virt_to_machine(txb->data).maddr;
-		tx->size = txb->len;
-		tx->unused = 0;
-
-		/* Get the granttable reference for this page. */
-		tx->ref = gnttab_claim_grant_reference(&gref_head);
-		if (tx->ref == -ENOSPC) {
-			spin_unlock_irq(&tp->tx_lock);
-			return -ENOSPC;
-		}
-		gnttab_grant_foreign_access_ref(tx->ref,
-				tp->backend_id,
-				virt_to_mfn(txb->data),
-				0 /*RW*/);
-		wmb();
-	}
+	shr = tp->page;
+	offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+
+	if (offset > PAGE_SIZE)
+		return -EIO;
+
+	if (offset + count > PAGE_SIZE)
+		count = PAGE_SIZE - offset;
+
+	memcpy(offset + (u8*)shr, buf, count);
+	shr->length = count;
+	barrier();
+	shr->state = 1;
 
 	atomic_set(&tp->tx_busy, 1);
 	tp->tx_remember = remember;
 
-	mb();
-
 	notify_remote_via_evtchn(tp->evtchn);
 
 	spin_unlock_irq(&tp->tx_lock);
@@ -667,12 +545,6 @@ static int __init tpmif_init(void)
 	if (!tp)
 		return -ENOMEM;
 
-	if (gnttab_alloc_grant_references(TPMIF_TX_RING_SIZE,
-				&gref_head) < 0) {
-		tpm_private_put();
-		return -EFAULT;
-	}
-
 	return xenbus_register_frontend(&tpmfront_driver);
 }
 module_init(tpmif_init);
@@ -680,7 +552,6 @@ module_init(tpmif_init);
 static void __exit tpmif_exit(void)
 {
 	xenbus_unregister_driver(&tpmfront_driver);
-	gnttab_free_grant_references(gref_head);
 	tpm_private_put();
 }
 module_exit(tpmif_exit);
diff --git a/include/xen/interface/io/tpmif.h b/include/xen/interface/io/tpmif.h
index c9e7294..3d5c743 100644
--- a/include/xen/interface/io/tpmif.h
+++ b/include/xen/interface/io/tpmif.h
@@ -1,7 +1,7 @@
 /******************************************************************************
  * tpmif.h
  *
- * TPM I/O interface for Xen guest OSes.
+ * TPM I/O interface for Xen guest OSes, v2
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -21,45 +21,21 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Copyright (c) 2005, IBM Corporation
- *
- * Author: Stefan Berger, stefanb@us.ibm.com
- * Grant table support: Mahadevan Gomathisankaran
- *
- * This code has been derived from tools/libxc/xen/io/netif.h
- *
- * Copyright (c) 2003-2004, Keir Fraser
  */
 
 #ifndef __XEN_PUBLIC_IO_TPMIF_H__
 #define __XEN_PUBLIC_IO_TPMIF_H__
 
-#include "../grant_table.h"
-
-struct tpmif_tx_request {
-	unsigned long addr;   /* Machine address of packet.   */
-	grant_ref_t ref;      /* grant table access reference */
-	uint16_t unused;
-	uint16_t size;        /* Packet size in bytes.        */
-};
-struct tpmif_tx_request;
+struct vtpm_shared_page {
+	uint16_t length;         /* request/response length in bytes */
 
-/*
- * The TPMIF_TX_RING_SIZE defines the number of pages the
- * front-end and backend can exchange (= size of array).
- */
-#define TPMIF_TX_RING_SIZE 1
-
-/* This structure must fit in a memory page. */
-
-struct tpmif_ring {
-	struct tpmif_tx_request req;
-};
-struct tpmif_ring;
+	uint8_t state;           /* 0 - response ready / idle
+                              * 1 - request ready / working */
+	uint8_t locality;        /* for the current request */
+	uint8_t padding[3];
 
-struct tpmif_tx_interface {
-	struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
+	uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
+	uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
 };
-struct tpmif_tx_interface;
 
 #endif
-- 
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-20 16:16 ` Fioravante, Matthew E.
  2012-11-20 18:24   ` [PATCH] drivers/tpm-xen: " Daniel De Graaf
@ 2012-11-23 11:04   ` Ian Campbell
  2012-11-23 16:15     ` Daniel De Graaf
  2012-11-28 20:46     ` Konrad Rzeszutek Wilk
  1 sibling, 2 replies; 53+ messages in thread
From: Ian Campbell @ 2012-11-23 11:04 UTC (permalink / raw)
  To: Fioravante, Matthew E.; +Cc: Daniel De Graaf, xen-devel@lists.xen.org
On Tue, 2012-11-20 at 16:16 +0000, Fioravante, Matthew E. wrote:
> This was something I've been wanting to do for a while so I'm very
> happy you went ahead and fixed it yourself. Once you submit the linux
> version I'll test it on my system.
> 
> Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
Do we need to synchronise with anything else (Linux drivers?) or I can I
just throw this into the tree once it is done?
Are we hanging any existing users of the tpm stuff out to dry? Could we
get a feature-protocol-v2 flag in xenstore so users at least get an
error message from either the front or backend to give a hint why it
isn't working?
>  void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int i;
> -   uint32_t domid;
> -   int tocopy;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>     int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +int i;
> +#endif
Dodgy indentation? (I saw a bunch of these)
> - * Copyright (c) 2005, IBM Corporation
> - *
> - * Author: Stefan Berger, stefanb@us.ibm.com
> - * Grant table support: Mahadevan Gomathisankaran
Did you really remove everything these guys wrote?
> - * This code has been derived from tools/libxc/xen/io/netif.h
> - *
> - * Copyright (c) 2003-2004, Keir Fraser
I guess I can buy this bit no longer being true given that you reworked
the whole protocol.
Ian
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-23 11:04   ` [PATCH RFC] stubdom: " Ian Campbell
@ 2012-11-23 16:15     ` Daniel De Graaf
  2012-11-23 16:30       ` Ian Campbell
  2012-11-26 13:03       ` Fioravante, Matthew E.
  2012-11-28 20:46     ` Konrad Rzeszutek Wilk
  1 sibling, 2 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-23 16:15 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Fioravante, Matthew E., xen-devel@lists.xen.org
On 11/23/2012 06:04 AM, Ian Campbell wrote:
> On Tue, 2012-11-20 at 16:16 +0000, Fioravante, Matthew E. wrote:
>> This was something I've been wanting to do for a while so I'm very
>> happy you went ahead and fixed it yourself. Once you submit the linux
>> version I'll test it on my system.
>>
>> Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
> 
> Do we need to synchronise with anything else (Linux drivers?) or I can I
> just throw this into the tree once it is done?
I think the only Linux drivers are the ones that were just posted, and the
ones for XenLinux 2.6.18. Assuming the modified Linux module that I posted
works as it should, the v2 version will be the only one upstream.
> Are we hanging any existing users of the tpm stuff out to dry? Could we
> get a feature-protocol-v2 flag in xenstore so users at least get an
> error message from either the front or backend to give a hint why it
> isn't working?
I suppose we could do that, although I'm not sure the "feature-" prefix is
appropriate, since the code doesn't have the ability to fall back to v1.
>>  void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
>> -   tpmif_tx_request_t* tx;
>> -   int offset;
>> -   int i;
>> -   uint32_t domid;
>> -   int tocopy;
>> +   vtpm_shared_page_t* shr;
>> +   unsigned int offset;
>>     int flags;
>> +#ifdef TPMBACK_PRINT_DEBUG
>> +int i;
>> +#endif
> 
> Dodgy indentation? (I saw a bunch of these)
Whoops, I'll have to go fix that. The entire mini-os build is sprinkled with
tabs and spaces mostly at random, so perhaps a generic fix-indent patch is
needed after all the real changes are applied.
 
>> - * Copyright (c) 2005, IBM Corporation
>> - *
>> - * Author: Stefan Berger, stefanb@us.ibm.com
>> - * Grant table support: Mahadevan Gomathisankaran
> 
> Did you really remove everything these guys wrote?
>From this file, yes - unless the #ifndef and header/footer comments count, but
I was under the impression that that is too small to count for copyright, and
is duplicated across the other files in that directory anyway.
 
>> - * This code has been derived from tools/libxc/xen/io/netif.h
>> - *
>> - * Copyright (c) 2003-2004, Keir Fraser
> 
> I guess I can buy this bit no longer being true given that you reworked
> the whole protocol.
> 
> Ian
Basically, the file is a rewrite, although not detected by git/hg as such. I can
add an authorship line if that would be helpful (I see that's normal in other
header files).
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-23 16:15     ` Daniel De Graaf
@ 2012-11-23 16:30       ` Ian Campbell
  2012-11-23 17:37         ` Samuel Thibault
  2012-11-26 13:03       ` Fioravante, Matthew E.
  1 sibling, 1 reply; 53+ messages in thread
From: Ian Campbell @ 2012-11-23 16:30 UTC (permalink / raw)
  To: Daniel De Graaf
  Cc: Fioravante, Matthew E., Samuel Thibault, xen-devel@lists.xen.org
On Fri, 2012-11-23 at 16:15 +0000, Daniel De Graaf wrote:
> On 11/23/2012 06:04 AM, Ian Campbell wrote:
> > On Tue, 2012-11-20 at 16:16 +0000, Fioravante, Matthew E. wrote:
> >> This was something I've been wanting to do for a while so I'm very
> >> happy you went ahead and fixed it yourself. Once you submit the linux
> >> version I'll test it on my system.
> >>
> >> Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
> > 
> > Do we need to synchronise with anything else (Linux drivers?) or I can I
> > just throw this into the tree once it is done?
> 
> I think the only Linux drivers are the ones that were just posted, and the
> ones for XenLinux 2.6.18.
Which people might be using?
>  Assuming the modified Linux module that I posted
> works as it should, the v2 version will be the only one upstream.
> 
> > Are we hanging any existing users of the tpm stuff out to dry? Could we
> > get a feature-protocol-v2 flag in xenstore so users at least get an
> > error message from either the front or backend to give a hint why it
> > isn't working?
> 
> I suppose we could do that, although I'm not sure the "feature-" prefix is
> appropriate, since the code doesn't have the ability to fall back to v1.
I think if the "fallback" is printk("Protocol version mismatch") then
that would suffice.
> 
> >>  void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
> >> -   tpmif_tx_request_t* tx;
> >> -   int offset;
> >> -   int i;
> >> -   uint32_t domid;
> >> -   int tocopy;
> >> +   vtpm_shared_page_t* shr;
> >> +   unsigned int offset;
> >>     int flags;
> >> +#ifdef TPMBACK_PRINT_DEBUG
> >> +int i;
> >> +#endif
> > 
> > Dodgy indentation? (I saw a bunch of these)
> 
> Whoops, I'll have to go fix that. The entire mini-os build is sprinkled with
> tabs and spaces mostly at random,
Yeah it's a mess AFAICT.
>  so perhaps a generic fix-indent patch is
> needed after all the real changes are applied.
It's either that or just try and make things a bit better with each new
patch.
Is it supposed to be Xen coding style or something else I wonder. (I
think it predates Samuel's involvement, but lets ask him...)
It would probably be useful to add the emacs magic to the various files.
>  
> >> - * Copyright (c) 2005, IBM Corporation
> >> - *
> >> - * Author: Stefan Berger, stefanb@us.ibm.com
> >> - * Grant table support: Mahadevan Gomathisankaran
> > 
> > Did you really remove everything these guys wrote?
> 
> From this file, yes - unless the #ifndef and header/footer comments count, but
> I was under the impression that that is too small to count for copyright, and
> is duplicated across the other files in that directory anyway.
OK, I just get wary when I see copyright stuff changing ;-)
>  
> >> - * This code has been derived from tools/libxc/xen/io/netif.h
> >> - *
> >> - * Copyright (c) 2003-2004, Keir Fraser
> > 
> > I guess I can buy this bit no longer being true given that you reworked
> > the whole protocol.
> > 
> > Ian
> 
> Basically, the file is a rewrite, although not detected by git/hg as such. I can
> add an authorship line if that would be helpful (I see that's normal in other
> header files).
> 
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-23 16:30       ` Ian Campbell
@ 2012-11-23 17:37         ` Samuel Thibault
  0 siblings, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-23 17:37 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Fioravante, Matthew E., Daniel De Graaf, xen-devel@lists.xen.org
Ian Campbell, le Fri 23 Nov 2012 16:30:17 +0000, a écrit :
> > Whoops, I'll have to go fix that. The entire mini-os build is sprinkled with
> > tabs and spaces mostly at random,
> 
> Yeah it's a mess AFAICT.
> 
> >  so perhaps a generic fix-indent patch is
> > needed after all the real changes are applied.
> 
> It's either that or just try and make things a bit better with each new
> patch.
> 
> Is it supposed to be Xen coding style or something else I wonder. (I
> think it predates Samuel's involvement, but lets ask him...)
It does predate, yes.
> It would probably be useful to add the emacs magic to the various files.
That could help to keep the files themselves coherent, yes.
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-23 16:15     ` Daniel De Graaf
  2012-11-23 16:30       ` Ian Campbell
@ 2012-11-26 13:03       ` Fioravante, Matthew E.
  2012-11-26 13:11         ` Fioravante, Matthew E.
  1 sibling, 1 reply; 53+ messages in thread
From: Fioravante, Matthew E. @ 2012-11-26 13:03 UTC (permalink / raw)
  To: Daniel De Graaf, Ian Campbell; +Cc: xen-devel@lists.xen.org
________________________________________
From: Daniel De Graaf [dgdegra@tycho.nsa.gov]
Sent: Friday, November 23, 2012 11:15 AM
To: Ian Campbell
Cc: Fioravante, Matthew E.; xen-devel@lists.xen.org
Subject: Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
On 11/23/2012 06:04 AM, Ian Campbell wrote:
> On Tue, 2012-11-20 at 16:16 +0000, Fioravante, Matthew E. wrote:
>> This was something I've been wanting to do for a while so I'm very
>> happy you went ahead and fixed it yourself. Once you submit the linux
>> version I'll test it on my system.
>>
>> Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
>
> Do we need to synchronise with anything else (Linux drivers?) or I can I
> just throw this into the tree once it is done?
I think the only Linux drivers are the ones that were just posted, and the
ones for XenLinux 2.6.18. Assuming the modified Linux module that I posted
works as it should, the v2 version will be the only one upstream.
> Are we hanging any existing users of the tpm stuff out to dry? Could we
> get a feature-protocol-v2 flag in xenstore so users at least get an
> error message from either the front or backend to give a hint why it
> isn't working?
I suppose we could do that, although I'm not sure the "feature-" prefix is
appropriate, since the code doesn't have the ability to fall back to v1.
I'd rather just let existing users hang out to dry. First off there aren't really 
any existing users. Anyone who is or might be a user is probably following 
these threads closely. Second the xen tpm driver hasn't even been 
accepted into linux yet so there really is not any "official" version 1.
I can update the documentation to state the requirements on the new
tpm driver version so that nobody tries to use the old version in the
xen 2.6.18 tree.
>>  void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
>> -   tpmif_tx_request_t* tx;
>> -   int offset;
>> -   int i;
>> -   uint32_t domid;
>> -   int tocopy;
>> +   vtpm_shared_page_t* shr;
>> +   unsigned int offset;
>>     int flags;
>> +#ifdef TPMBACK_PRINT_DEBUG
>> +int i;
>> +#endif
>
> Dodgy indentation? (I saw a bunch of these)
Whoops, I'll have to go fix that. The entire mini-os build is sprinkled with
tabs and spaces mostly at random, so perhaps a generic fix-indent patch is
needed after all the real changes are applied.
>> - * Copyright (c) 2005, IBM Corporation
>> - *
>> - * Author: Stefan Berger, stefanb@us.ibm.com
>> - * Grant table support: Mahadevan Gomathisankaran
>
> Did you really remove everything these guys wrote?
>From this file, yes - unless the #ifndef and header/footer comments count, but
I was under the impression that that is too small to count for copyright, and
is duplicated across the other files in that directory anyway.
>> - * This code has been derived from tools/libxc/xen/io/netif.h
>> - *
>> - * Copyright (c) 2003-2004, Keir Fraser
>
> I guess I can buy this bit no longer being true given that you reworked
> the whole protocol.
>
> Ian
Basically, the file is a rewrite, although not detected by git/hg as such. I can
add an authorship line if that would be helpful (I see that's normal in other
header files).
--
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-26 13:03       ` Fioravante, Matthew E.
@ 2012-11-26 13:11         ` Fioravante, Matthew E.
  0 siblings, 0 replies; 53+ messages in thread
From: Fioravante, Matthew E. @ 2012-11-26 13:11 UTC (permalink / raw)
  To: Fioravante, Matthew E., Daniel De Graaf, Ian Campbell
  Cc: xen-devel@lists.xen.org
Ok outlook web email client is horrible. My reply was:
>> Are we hanging any existing users of the tpm stuff out to dry? Could we
>> get a feature-protocol-v2 flag in xenstore so users at least get an
>> error message from either the front or backend to give a hint why it
>> isn't working?
>I suppose we could do that, although I'm not sure the "feature-" prefix is
>appropriate, since the code doesn't have the ability to fall back to v1.
I'd rather just let existing users hang out to dry. First off there aren't really 
any existing users. Anyone who is or might be a user of the new code is 
probably following these threads closely. Second the xen tpm driver 
hasn't even been accepted into linux yet so there really is not any 
"official" version 1.
I can update the documentation to state the requirements on the new
tpm driver version in the current linux tree so that nobody tries to use the old version in the
xen 2.6.18 tree.
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-20 16:11 [PATCH RFC] stubdom: Change vTPM shared page ABI Daniel De Graaf
  2012-11-20 16:16 ` Fioravante, Matthew E.
@ 2012-11-27 14:38 ` Matthew Fioravante
  2012-11-27 15:14   ` [PATCH 0/4] stubdom/vtpm improvements Daniel De Graaf
  1 sibling, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-27 14:38 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 24752 bytes --]
Daniel I just tried your patch and it didn't apply cleanly. The tpm 
drivers have changed slightly from the original versions you are 
probably working with. The vtpm domains have also changed.
Please pull the latest xen unstable and rebase your patches ontop of the 
tpm drivers there. You can apply my VTPM v4 patches in the mailing list 
ontop of xen-unstable to test. It looks like everything except the 
stubdoms and documentation is currently in xen-unstable.
On 11/20/2012 11:11 AM, Daniel De Graaf wrote:
> Since the vTPM implementations are being incorproated into Xen and
> possibly upstream Linux, I would like to see if this protocol change
> could be added before we have significant legacy implementations. If
> not, I still think it would be useful as either a v2 or negotiated
> protocol change.
>
> The current vTPM protocol is a copy of the network protocol. This was
> likely done for ease of implementation, since support for the network
> backend/frontend existed in Linux and minios. However, this
> implementation is overly complex when dealing with vTPM packets: for
> example, a vTPM never needs to deal with having more than one packet in
> flight at any given time.
>
> I will send the corresponding patch for the Linux kernel module once I
> have adapted it for the file names used in the upstream version.
>
> ------------------------------------>8----------------------------------
>
> This changes the vTPM shared page ABI from a copy of the Xen network
> interface to a single-page interface that better reflects the expected
> behavior of a TPM: only a single request packet can be sent at any given
> time, and every packet sent generates a single response packet. This
> protocol change should also increase efficiency as it avoids mapping and
> unmapping grants when possible.
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   extras/mini-os/include/tpmback.h  |   1 +
>   extras/mini-os/include/tpmfront.h |   7 +-
>   extras/mini-os/tpmback.c          | 132 ++++++++++++++-------------------
>   extras/mini-os/tpmfront.c         | 150 +++++++++++++++++++-------------------
>   xen/include/public/io/tpmif.h     |  45 +++---------
>   5 files changed, 148 insertions(+), 187 deletions(-)
>
> diff --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
> index ff86732..ec9eda4 100644
> --- a/extras/mini-os/include/tpmback.h
> +++ b/extras/mini-os/include/tpmback.h
> @@ -43,6 +43,7 @@
>
>   struct tpmcmd {
>      domid_t domid;              /* Domid of the frontend */
> +   uint8_t locality;    /* Locality requested by the frontend */
>      unsigned int handle;        /* Handle of the frontend */
>      unsigned char uuid[16];                     /* uuid of the tpm interface */
>
> diff --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
> index fd2cb17..a0c7c4d 100644
> --- a/extras/mini-os/include/tpmfront.h
> +++ b/extras/mini-os/include/tpmfront.h
> @@ -37,9 +37,7 @@ struct tpmfront_dev {
>      grant_ref_t ring_ref;
>      evtchn_port_t evtchn;
>
> -   tpmif_tx_interface_t* tx;
> -
> -   void** pages;
> +   vtpm_shared_page_t *page;
>
>      domid_t bedomid;
>      char* nodename;
> @@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
>    * */
>   int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
>
> +/* Set the locality used for communicating with a vTPM */
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
> +
>   #ifdef HAVE_LIBC
>   #include <sys/stat.h>
>   /* POSIX IO functions:
> diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
> index 658fed1..29aced9 100644
> --- a/extras/mini-os/tpmback.c
> +++ b/extras/mini-os/tpmback.c
> @@ -86,10 +86,7 @@ struct tpmif {
>      evtchn_port_t evtchn;
>
>      /* Shared page */
> -   tpmif_tx_interface_t* tx;
> -
> -   /* pointer to TPMIF_RX_RING_SIZE pages */
> -   void** pages;
> +   vtpm_shared_page_t *page;
>
>      enum xenbus_state state;
>      enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
> @@ -386,8 +383,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
>      tpmif->fe_state_path = NULL;
>      tpmif->state = XenbusStateInitialising;
>      tpmif->status = DISCONNECTED;
> -   tpmif->tx = NULL;
> -   tpmif->pages = NULL;
> +   tpmif->page = NULL;
>      tpmif->flags = 0;
>      memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
>      return tpmif;
> @@ -395,9 +391,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
>
>   void __free_tpmif(tpmif_t* tpmif)
>   {
> -   if(tpmif->pages) {
> -      free(tpmif->pages);
> -   }
>      if(tpmif->fe_path) {
>         free(tpmif->fe_path);
>      }
> @@ -430,12 +423,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
>         goto error;
>      }
>
> -   /* allocate pages to be used for shared mapping */
> -   if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
> -      goto error;
> -   }
> -   memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -
>      if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
>         goto error;
>      }
> @@ -486,7 +473,7 @@ void free_tpmif(tpmif_t* tpmif)
>         tpmif->status = DISCONNECTING;
>         mask_evtchn(tpmif->evtchn);
>
> -      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1)) {
> +      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
>           TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
>         }
>
> @@ -529,9 +516,10 @@ void free_tpmif(tpmif_t* tpmif)
>   void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
>   {
>      tpmif_t* tpmif = (tpmif_t*) data;
> -   tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
> -   /* Throw away 0 size events, these can trigger from event channel unmasking */
> -   if(tx->size == 0)
> +   vtpm_shared_page_t* pg = tpmif->page;
> +
> +   /* Only pay attention if the request is ready */
> +   if (pg->state == 0)
>         return;
>
>      TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
> @@ -585,11 +573,10 @@ int connect_fe(tpmif_t* tpmif)
>      free(value);
>
>      domid = tpmif->domid;
> -   if((tpmif->tx = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
> +   if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
>         TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
>         return -1;
>      }
> -   memset(tpmif->tx, 0, PAGE_SIZE);
>
>      /*Bind the event channel */
>      if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
> @@ -618,10 +605,28 @@ error_post_evtchn:
>      mask_evtchn(tpmif->evtchn);
>      unbind_evtchn(tpmif->evtchn);
>   error_post_map:
> -   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1);
> +   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
>      return -1;
>   }
>
> +static void disconnect_fe(tpmif_t* tpmif)
> +{
> +   if (tpmif->status == CONNECTED) {
> +      tpmif->status = DISCONNECTING;
> +      mask_evtchn(tpmif->evtchn);
> +
> +      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
> +        TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      }
> +
> +      unbind_evtchn(tpmif->evtchn);
> +   }
> +   tpmif->status = DISCONNECTED;
> +   tpmif_change_state(tpmif, XenbusStateReconfigured);
> +
> +   TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
> +}
> +
>   static int frontend_changed(tpmif_t* tpmif)
>   {
>      int state = xenbus_read_integer(tpmif->fe_state_path);
> @@ -874,6 +879,7 @@ void shutdown_tpmback(void)
>   inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, unsigned char uuid[16])
>   {
>      tpmcmd->domid = domid;
> +   tpmcmd->locality = -1;
>      tpmcmd->handle = handle;
>      memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
>      tpmcmd->req = NULL;
> @@ -884,12 +890,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, un
>
>   tpmcmd_t* get_request(tpmif_t* tpmif) {
>      tpmcmd_t* cmd;
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int tocopy;
> -   int i;
> -   uint32_t domid;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>      int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +int i;
> +#endif
>
>      local_irq_save(flags);
>
> @@ -899,35 +905,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
>      }
>      init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
>
> -   tx = &tpmif->tx->ring[0].req;
> -   cmd->req_len = tx->size;
> +   shr = tpmif->page;
> +   cmd->req_len = shr->length;
> +   cmd->locality = shr->locality;
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
> +   }
>      /* Allocate the buffer */
>      if(cmd->req_len) {
>         if((cmd->req = malloc(cmd->req_len)) == NULL) {
>           goto error;
>         }
>      }
> -   /* Copy the bits from the shared pages */
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_READ)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->req_len - offset, PAGE_SIZE);
> -      memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
> -
> -   }
> +   /* Copy the bits from the shared page(s) */
> +   memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
>
>   #ifdef TPMBACK_PRINT_DEBUG
>      TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
> @@ -958,38 +951,24 @@ error:
>
>   void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>   {
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int i;
> -   uint32_t domid;
> -   int tocopy;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>      int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +int i;
> +#endif
>
>      local_irq_save(flags);
>
> -   tx = &tpmif->tx->ring[0].req;
> -   tx->size = cmd->resp_len;
> -
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_WRITE)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
> -      memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
> +   shr = tpmif->page;
> +   shr->length = cmd->resp_len;
>
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
>      }
> +   memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
>
>   #ifdef TPMBACK_PRINT_DEBUG
>      TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
> @@ -1003,6 +982,7 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>   #endif
>      /* clear the ready flag and send the event channel notice to the frontend */
>      tpmif_req_finished(tpmif);
> +   shr->state = 0;
>      notify_remote_via_evtchn(tpmif->evtchn);
>   error:
>      local_irq_restore(flags);
> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
> index 0218d7f..bcee93d 100644
> --- a/extras/mini-os/tpmfront.c
> +++ b/extras/mini-os/tpmfront.c
> @@ -153,6 +153,32 @@ static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
>
>   }
>
> +static int wait_for_backend_reconfig(xenbus_event_queue* events, char* path)
> +{
> +   int state;
> +
> +   TPMFRONT_LOG("Waiting for backend to reconfigure...\n");
> +   while(1) {
> +      state = xenbus_read_integer(path);
> +      if ( state < 0)
> +        state = XenbusStateUnknown;
> +      switch(state) {
> +        case XenbusStateUnknown:
> +           TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
> +           return -1;
> +        case XenbusStateClosed:
> +           TPMFRONT_LOG("Backend Closed\n");
> +           return 0;
> +        case XenbusStateReconfigured:
> +           TPMFRONT_LOG("Backend Reconfigured\n");
> +           return 0;
> +        default:
> +           xenbus_wait_for_watch(events);
> +      }
> +   }
> +
> +}
> +
>   static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
>      char* err;
>      int ret = 0;
> @@ -175,8 +201,11 @@ static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState
>         case XenbusStateClosed:
>           ret = wait_for_backend_closed(&events, path);
>           break;
> -      default:
> +      case XenbusStateReconfigured:
> +        ret = wait_for_backend_reconfig(&events, path);
>           break;
> +      default:
> +         TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
>      }
>
>      if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
> @@ -190,13 +219,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)
>   {
>      char* err;
>      /* Create shared page */
> -   dev->tx = (tpmif_tx_interface_t*) alloc_page();
> -   if(dev->tx == NULL) {
> +   dev->page = (vtpm_shared_page_t*) alloc_page();
> +   if(dev->page == NULL) {
>         TPMFRONT_ERR("Unable to allocate page for shared memory\n");
>         goto error;
>      }
> -   memset(dev->tx, 0, PAGE_SIZE);
> -   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 0);
> +   memset(dev->page, 0, PAGE_SIZE);
> +   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
>      TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
>
>      /*Create event channel */
> @@ -228,7 +257,7 @@ error_postevtchn:
>         unbind_evtchn(dev->evtchn);
>   error_postmap:
>         gnttab_end_access(dev->ring_ref);
> -      free_page(dev->tx);
> +      free_page(dev->page);
>   error:
>      return -1;
>   }
> @@ -240,7 +269,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>      char path[512];
>      char* value, *err;
>      unsigned long long ival;
> -   int i;
>
>      printk("============= Init TPM Front ================\n");
>
> @@ -289,19 +317,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>         goto error;
>      }
>
> -   /* Allocate pages that will contain the messages */
> -   dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   if(dev->pages == NULL) {
> -      goto error;
> -   }
> -   memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -      dev->pages[i] = (void*)alloc_page();
> -      if(dev->pages[i] == NULL) {
> -        goto error;
> -      }
> -   }
> -
>      TPMFRONT_LOG("Initialization Completed successfully\n");
>
>      return dev;
> @@ -314,12 +329,10 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>   {
>      char* err;
>      char path[512];
> -   int i;
> -   tpmif_tx_request_t* tx;
>      if(dev == NULL) {
>         return;
>      }
> -   TPMFRONT_LOG("Shutting down tpmfront\n");
> +   TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
>      /* disconnect */
>      if(dev->state == XenbusStateConnected) {
>         dev->state = XenbusStateClosing;
> @@ -349,27 +362,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>         /* Wait for the backend to close and unmap shared pages, ignore any errors */
>         wait_for_backend_state_changed(dev, XenbusStateClosed);
>
> -      /* Cleanup any shared pages */
> -      if(dev->pages) {
> -        for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -           if(dev->pages[i]) {
> -              tx = &dev->tx->ring[i].req;
> -              if(tx->ref != 0) {
> -                 gnttab_end_access(tx->ref);
> -              }
> -              free_page(dev->pages[i]);
> -           }
> -        }
> -        free(dev->pages);
> -      }
> -
>         /* Close event channel and unmap shared page */
>         mask_evtchn(dev->evtchn);
>         unbind_evtchn(dev->evtchn);
>         gnttab_end_access(dev->ring_ref);
>
> -      free_page(dev->tx);
> -
> +      free_page(dev->page);
>      }
>
>      /* Cleanup memory usage */
> @@ -387,13 +385,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>
>   int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   {
> -   int i;
> -   tpmif_tx_request_t* tx = NULL;
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
> +int i;
> +#endif
>      /* Error Checking */
>      if(dev == NULL || dev->state != XenbusStateConnected) {
>         TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
>         return -1;
>      }
> +   shr = dev->page;
>
>   #ifdef TPMFRONT_PRINT_DEBUG
>      TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
> @@ -407,19 +409,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   #endif
>
>      /* Copy to shared pages now */
> -   for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
> -      /* Share the page */
> -      tx = &dev->tx->ring[i].req;
> -      tx->unused = 0;
> -      tx->addr = virt_to_mach(dev->pages[i]);
> -      tx->ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->pages[i]), 0);
> -      /* Copy the bits to the page */
> -      tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
> -      memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
> -
> -      /* Update counters */
> -      length -= tx->size;
> +   offset = sizeof(*shr);
> +   if (length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Message too long for shared page\n");
> +      return -1;
>      }
> +   memcpy(offset + (uint8_t*)shr, msg, length);
> +   shr->length = length;
> +   barrier();
> +   shr->state = 1;
> +
>      dev->waiting = 1;
>      dev->resplen = 0;
>   #ifdef HAVE_LIBC
> @@ -434,44 +433,41 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   }
>   int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
>   {
> -   tpmif_tx_request_t* tx;
> -   int i;
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
> +int i;
> +#endif
>      if(dev == NULL || dev->state != XenbusStateConnected) {
>         TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
>         return -1;
>      }
>      /*Wait for the response */
>      wait_event(dev->waitq, (!dev->waiting));
> +   shr = dev->page;
> +   if (shr->state != 0)
> +      goto quit;
>
>      /* Initialize */
>      *msg = NULL;
> -   *length = 0;
> +   *length = shr->length;
> +   offset = sizeof(*shr);
>
> -   /* special case, just quit */
> -   tx = &dev->tx->ring[0].req;
> -   if(tx->size == 0 ) {
> -       goto quit;
> -   }
> -   /* Get the total size */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      *length += tx->size;
> +   if (*length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Reply too long for shared page\n");
> +      return -1;
>      }
> +
>      /* Alloc the buffer */
>      if(dev->respbuf) {
>         free(dev->respbuf);
>      }
>      *msg = dev->respbuf = malloc(*length);
>      dev->resplen = *length;
> +
>      /* Copy the bits */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
> -      gnttab_end_access(tx->ref);
> -      tx->ref = 0;
> -   }
> +   memcpy(*msg, offset + (uint8_t*)shr, *length);
> +
>   #ifdef TPMFRONT_PRINT_DEBUG
>      TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
>      for(i = 0; i < *length; ++i) {
> @@ -504,6 +500,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t*
>      return 0;
>   }
>
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
> +{
> +   if (!dev || !dev->page)
> +      return -1;
> +   dev->page->locality = locality;
> +   return 0;
> +}
> +
>   #ifdef HAVE_LIBC
>   #include <errno.h>
>   int tpmfront_open(struct tpmfront_dev* dev)
> diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h
> index 02ccdab..afc9181 100644
> --- a/xen/include/public/io/tpmif.h
> +++ b/xen/include/public/io/tpmif.h
> @@ -1,7 +1,7 @@
>   /******************************************************************************
>    * tpmif.h
>    *
> - * TPM I/O interface for Xen guest OSes.
> + * TPM I/O interface for Xen guest OSes, v2
>    *
>    * Permission is hereby granted, free of charge, to any person obtaining a copy
>    * of this software and associated documentation files (the "Software"), to
> @@ -21,48 +21,23 @@
>    * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>    * DEALINGS IN THE SOFTWARE.
>    *
> - * Copyright (c) 2005, IBM Corporation
> - *
> - * Author: Stefan Berger, stefanb@us.ibm.com
> - * Grant table support: Mahadevan Gomathisankaran
> - *
> - * This code has been derived from tools/libxc/xen/io/netif.h
> - *
> - * Copyright (c) 2003-2004, Keir Fraser
>    */
>
>   #ifndef __XEN_PUBLIC_IO_TPMIF_H__
>   #define __XEN_PUBLIC_IO_TPMIF_H__
>
> -#include "../grant_table.h"
> +struct vtpm_shared_page {
> +    uint16_t length;         /* request/response length in bytes */
>
> -struct tpmif_tx_request {
> -    unsigned long addr;   /* Machine address of packet.   */
> -    grant_ref_t ref;      /* grant table access reference */
> -    uint16_t unused;
> -    uint16_t size;        /* Packet size in bytes.        */
> -};
> -typedef struct tpmif_tx_request tpmif_tx_request_t;
> -
> -/*
> - * The TPMIF_TX_RING_SIZE defines the number of pages the
> - * front-end and backend can exchange (= size of array).
> - */
> -typedef uint32_t TPMIF_RING_IDX;
> -
> -#define TPMIF_TX_RING_SIZE 1
> -
> -/* This structure must fit in a memory page. */
> -
> -struct tpmif_ring {
> -    struct tpmif_tx_request req;
> -};
> -typedef struct tpmif_ring tpmif_ring_t;
> +    uint8_t state;           /* 0 - response ready / idle
> +                              * 1 - request ready / working */
> +    uint8_t locality;        /* for the current request */
> +    uint8_t padding[3];
>
> -struct tpmif_tx_interface {
> -    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
> +    uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
> +    uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
>   };
> -typedef struct tpmif_tx_interface tpmif_tx_interface_t;
> +typedef struct vtpm_shared_page vtpm_shared_page_t;
>
>   #endif
>
> --
> 1.7.11.7
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* [PATCH 0/4] stubdom/vtpm improvements
  2012-11-27 14:38 ` Matthew Fioravante
@ 2012-11-27 15:14   ` Daniel De Graaf
  2012-11-27 15:14     ` [PATCH 1/4] stubdom: Change vTPM shared page ABI Daniel De Graaf
                       ` (4 more replies)
  0 siblings, 5 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 15:14 UTC (permalink / raw)
  To: matthew.fioravante; +Cc: dgdegra, Ian.Campbell, xen-devel
Patch 1/4 is the (updated) version of the patch starting this thread.
The series is based off the v4 vTPM series posted to xen-devel. The
other 3 patches add support for using the locality field and extending a
static root of trust to a user-specified kernel loaded with pv-grub.
Since pv-grub is already GPL, there should be no licensing issues
created by adding the vTPM code and the Linux SHA1 implementation.
Contents:
  [PATCH 1/4] stubdom: Change vTPM shared page ABI
  [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM
  [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
^ permalink raw reply	[flat|nested] 53+ messages in thread
* [PATCH 1/4] stubdom: Change vTPM shared page ABI
  2012-11-27 15:14   ` [PATCH 0/4] stubdom/vtpm improvements Daniel De Graaf
@ 2012-11-27 15:14     ` Daniel De Graaf
  2012-11-27 21:29       ` Matthew Fioravante
  2012-11-29 14:14       ` Matthew Fioravante
  2012-11-27 15:14     ` [PATCH 2/4] stubdom/vtpm: Add reconfiguration support Daniel De Graaf
                       ` (3 subsequent siblings)
  4 siblings, 2 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 15:14 UTC (permalink / raw)
  To: matthew.fioravante; +Cc: dgdegra, Ian.Campbell, xen-devel
This changes the vTPM shared page ABI from a copy of the Xen network
interface to a single-page interface that better reflects the expected
behavior of a TPM: only a single request packet can be sent at any given
time, and every packet sent generates a single response packet. This
protocol change should also increase efficiency as it avoids mapping and
unmapping grants when possible.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
   |   1 +
  |   7 +-
           | 159 +++++++++++++++++++------------------
          | 162 ++++++++++++++++++++++----------------
 xen/include/public/io/tpmif.h     |  45 +++--------
 5 files changed, 191 insertions(+), 183 deletions(-)
 --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
index ff86732..ec9eda4 100644
--- a/extras/mini-os/include/tpmback.h
+++ b/extras/mini-os/include/tpmback.h
@@ -43,6 +43,7 @@
 
 struct tpmcmd {
    domid_t domid;		/* Domid of the frontend */
+   uint8_t locality;    /* Locality requested by the frontend */
    unsigned int handle;	/* Handle of the frontend */
    unsigned char uuid[16];			/* uuid of the tpm interface */
 
 --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
index fd2cb17..a0c7c4d 100644
--- a/extras/mini-os/include/tpmfront.h
+++ b/extras/mini-os/include/tpmfront.h
@@ -37,9 +37,7 @@ struct tpmfront_dev {
    grant_ref_t ring_ref;
    evtchn_port_t evtchn;
 
-   tpmif_tx_interface_t* tx;
-
-   void** pages;
+   vtpm_shared_page_t *page;
 
    domid_t bedomid;
    char* nodename;
@@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
  * */
 int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
 
+/* Set the locality used for communicating with a vTPM */
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
+
 #ifdef HAVE_LIBC
 #include <sys/stat.h>
 /* POSIX IO functions:
 --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
index 658fed1..2d31061 100644
--- a/extras/mini-os/tpmback.c
+++ b/extras/mini-os/tpmback.c
@@ -86,10 +86,7 @@ struct tpmif {
    evtchn_port_t evtchn;
 
    /* Shared page */
-   tpmif_tx_interface_t* tx;
-
-   /* pointer to TPMIF_RX_RING_SIZE pages */
-   void** pages;
+   vtpm_shared_page_t *page;
 
    enum xenbus_state state;
    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
@@ -266,6 +263,7 @@ int insert_tpmif(tpmif_t* tpmif)
    unsigned int i, j;
    tpmif_t* tmp;
    char* err;
+   char path[512];
 
    local_irq_save(flags);
 
@@ -303,6 +301,16 @@ int insert_tpmif(tpmif_t* tpmif)
 
    local_irq_restore(flags);
 
+   snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
+   if ((err = xenbus_write(XBT_NIL, path, "1")))
+   {
+      /* if we got an error here we should carefully remove the interface and then return */
+      TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
+      free(err);
+      remove_tpmif(tpmif);
+      goto error_post_irq;
+   }
+
    /*Listen for state changes on the new interface */
    if((err = xenbus_watch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path, >pmdev.events)))
    {
@@ -312,7 +320,6 @@ int insert_tpmif(tpmif_t* tpmif)
       remove_tpmif(tpmif);
       goto error_post_irq;
    }
-
    return 0;
 error:
    local_irq_restore(flags);
@@ -386,8 +393,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
    tpmif->fe_state_path = NULL;
    tpmif->state = XenbusStateInitialising;
    tpmif->status = DISCONNECTED;
-   tpmif->tx = NULL;
-   tpmif->pages = NULL;
+   tpmif->page = NULL;
    tpmif->flags = 0;
    memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
    return tpmif;
@@ -395,9 +401,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
 
 void __free_tpmif(tpmif_t* tpmif)
 {
-   if(tpmif->pages) {
-      free(tpmif->pages);
-   }
    if(tpmif->fe_path) {
       free(tpmif->fe_path);
    }
@@ -430,12 +433,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
       goto error;
    }
 
-   /* allocate pages to be used for shared mapping */
-   if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
-      goto error;
-   }
-   memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
-
    if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
       goto error;
    }
@@ -486,7 +483,7 @@ void free_tpmif(tpmif_t* tpmif)
       tpmif->status = DISCONNECTING;
       mask_evtchn(tpmif->evtchn);
 
-      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1)) {
+      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
 	 TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
       }
 
@@ -529,9 +526,10 @@ void free_tpmif(tpmif_t* tpmif)
 void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
 {
    tpmif_t* tpmif = (tpmif_t*) data;
-   tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
-   /* Throw away 0 size events, these can trigger from event channel unmasking */
-   if(tx->size == 0)
+   vtpm_shared_page_t* pg = tpmif->page;
+
+   /* Only pay attention if the request is ready */
+   if (pg->state == 0)
       return;
 
    TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
@@ -584,12 +582,26 @@ int connect_fe(tpmif_t* tpmif)
    }
    free(value);
 
+   /* Check that protocol v2 is being used */
+   snprintf(path, 512, "%s/feature-protocol-v2", tpmif->fe_path);
+   if((err = xenbus_read(XBT_NIL, path, &value))) {
+      TPMBACK_ERR("Unable to read %s during tpmback initialization! error = %s\n", path, err);
+      free(err);
+      return -1;
+   }
+   if(strcmp(value, "1")) {
+      TPMBACK_ERR("%s has an invalid value (%s)\n", path, value);
+      free(value);
+      return -1;
+   }
+   free(value);
+
+
    domid = tpmif->domid;
-   if((tpmif->tx = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
+   if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
       TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
       return -1;
    }
-   memset(tpmif->tx, 0, PAGE_SIZE);
 
    /*Bind the event channel */
    if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
@@ -618,10 +630,28 @@ error_post_evtchn:
    mask_evtchn(tpmif->evtchn);
    unbind_evtchn(tpmif->evtchn);
 error_post_map:
-   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1);
+   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
    return -1;
 }
 
+static void disconnect_fe(tpmif_t* tpmif)
+{
+   if (tpmif->status == CONNECTED) {
+      tpmif->status = DISCONNECTING;
+      mask_evtchn(tpmif->evtchn);
+
+      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
+	 TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
+      }
+
+      unbind_evtchn(tpmif->evtchn);
+   }
+   tpmif->status = DISCONNECTED;
+   tpmif_change_state(tpmif, XenbusStateReconfigured);
+
+   TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
+}
+
 static int frontend_changed(tpmif_t* tpmif)
 {
    int state = xenbus_read_integer(tpmif->fe_state_path);
@@ -874,6 +904,7 @@ void shutdown_tpmback(void)
 inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, unsigned char uuid[16])
 {
    tpmcmd->domid = domid;
+   tpmcmd->locality = -1;
    tpmcmd->handle = handle;
    memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
    tpmcmd->req = NULL;
@@ -884,12 +915,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, un
 
 tpmcmd_t* get_request(tpmif_t* tpmif) {
    tpmcmd_t* cmd;
-   tpmif_tx_request_t* tx;
-   int offset;
-   int tocopy;
-   int i;
-   uint32_t domid;
+   vtpm_shared_page_t* shr;
+   unsigned int offset;
    int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+   int i;
+#endif
 
    local_irq_save(flags);
 
@@ -899,35 +930,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
    }
    init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
 
-   tx = &tpmif->tx->ring[0].req;
-   cmd->req_len = tx->size;
+   shr = tpmif->page;
+   cmd->req_len = shr->length;
+   cmd->locality = shr->locality;
+   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+   if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
+      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+      goto error;
+   }
    /* Allocate the buffer */
    if(cmd->req_len) {
       if((cmd->req = malloc(cmd->req_len)) == NULL) {
 	 goto error;
       }
    }
-   /* Copy the bits from the shared pages */
-   offset = 0;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
-      tx = &tpmif->tx->ring[i].req;
-
-      /* Map the page with the data */
-      domid = (uint32_t)tpmif->domid;
-      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_READ)) == NULL) {
-	 TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", (unsigned int) tpmif->domid, tpmif->handle);
-	 goto error;
-      }
-
-      /* do the copy now */
-      tocopy = min(cmd->req_len - offset, PAGE_SIZE);
-      memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
-      offset += tocopy;
-
-      /* release the page */
-      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
-
-   }
+   /* Copy the bits from the shared page(s) */
+   memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
 
 #ifdef TPMBACK_PRINT_DEBUG
    TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
@@ -958,38 +976,24 @@ error:
 
 void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
 {
-   tpmif_tx_request_t* tx;
-   int offset;
-   int i;
-   uint32_t domid;
-   int tocopy;
+   vtpm_shared_page_t* shr;
+   unsigned int offset;
    int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+int i;
+#endif
 
    local_irq_save(flags);
 
-   tx = &tpmif->tx->ring[0].req;
-   tx->size = cmd->resp_len;
-
-   offset = 0;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
-      tx = &tpmif->tx->ring[i].req;
-
-      /* Map the page with the data */
-      domid = (uint32_t)tpmif->domid;
-      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_WRITE)) == NULL) {
-	 TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", (unsigned int) tpmif->domid, tpmif->handle);
-	 goto error;
-      }
-
-      /* do the copy now */
-      tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
-      memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
-      offset += tocopy;
-
-      /* release the page */
-      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
+   shr = tpmif->page;
+   shr->length = cmd->resp_len;
 
+   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+   if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
+      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+      goto error;
    }
+   memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
 
 #ifdef TPMBACK_PRINT_DEBUG
    TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
@@ -1003,6 +1007,7 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
 #endif
    /* clear the ready flag and send the event channel notice to the frontend */
    tpmif_req_finished(tpmif);
+   shr->state = 0;
    notify_remote_via_evtchn(tpmif->evtchn);
 error:
    local_irq_restore(flags);
 --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index 0218d7f..c1cbab3 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -153,6 +153,32 @@ static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
 
 }
 
+static int wait_for_backend_reconfig(xenbus_event_queue* events, char* path)
+{
+   int state;
+
+   TPMFRONT_LOG("Waiting for backend to reconfigure...\n");
+   while(1) {
+      state = xenbus_read_integer(path);
+      if ( state < 0)
+	 state = XenbusStateUnknown;
+      switch(state) {
+	 case XenbusStateUnknown:
+	    TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
+	    return -1;
+	 case XenbusStateClosed:
+	    TPMFRONT_LOG("Backend Closed\n");
+	    return 0;
+	 case XenbusStateReconfigured:
+	    TPMFRONT_LOG("Backend Reconfigured\n");
+	    return 0;
+	 default:
+	    xenbus_wait_for_watch(events);
+      }
+   }
+
+}
+
 static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
    char* err;
    int ret = 0;
@@ -175,8 +201,11 @@ static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState
       case XenbusStateClosed:
 	 ret = wait_for_backend_closed(&events, path);
 	 break;
-      default:
+      case XenbusStateReconfigured:
+	 ret = wait_for_backend_reconfig(&events, path);
 	 break;
+      default:
+         TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
    }
 
    if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
@@ -190,13 +219,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)
 {
    char* err;
    /* Create shared page */
-   dev->tx = (tpmif_tx_interface_t*) alloc_page();
-   if(dev->tx == NULL) {
+   dev->page = (vtpm_shared_page_t*) alloc_page();
+   if(dev->page == NULL) {
       TPMFRONT_ERR("Unable to allocate page for shared memory\n");
       goto error;
    }
-   memset(dev->tx, 0, PAGE_SIZE);
-   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 0);
+   memset(dev->page, 0, PAGE_SIZE);
+   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
    TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
 
    /*Create event channel */
@@ -228,7 +257,7 @@ error_postevtchn:
       unbind_evtchn(dev->evtchn);
 error_postmap:
       gnttab_end_access(dev->ring_ref);
-      free_page(dev->tx);
+      free_page(dev->page);
 error:
    return -1;
 }
@@ -240,7 +269,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
    char path[512];
    char* value, *err;
    unsigned long long ival;
-   int i;
 
    printk("============= Init TPM Front ================\n");
 
@@ -279,6 +307,15 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
       goto error;
    }
 
+   /* Publish protocol v2 feature */
+   snprintf(path, 512, "%s/feature-protocol-v2", dev->nodename);
+   if ((err = xenbus_write(XBT_NIL, path, "1")))
+   {
+      TPMFRONT_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
+	  free(err);
+      goto error;
+   }
+
    /* Create and publish grant reference and event channel */
    if (tpmfront_connect(dev)) {
       goto error;
@@ -289,18 +326,18 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
       goto error;
    }
 
-   /* Allocate pages that will contain the messages */
-   dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
-   if(dev->pages == NULL) {
+   snprintf(path, 512, "%s/feature-protocol-v2", dev->bepath);
+   if((err = xenbus_read(XBT_NIL, path, &value))) {
+      TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
+      free(err);
       goto error;
    }
-   memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
-   for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
-      dev->pages[i] = (void*)alloc_page();
-      if(dev->pages[i] == NULL) {
-	 goto error;
-      }
+   if(strcmp(value, "1")) {
+      TPMFRONT_ERR("%s has an invalid value (%s)\n", path, value);
+      free(value);
+      goto error;
    }
+   free(value);
 
    TPMFRONT_LOG("Initialization Completed successfully\n");
 
@@ -314,12 +351,10 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
 {
    char* err;
    char path[512];
-   int i;
-   tpmif_tx_request_t* tx;
    if(dev == NULL) {
       return;
    }
-   TPMFRONT_LOG("Shutting down tpmfront\n");
+   TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
    /* disconnect */
    if(dev->state == XenbusStateConnected) {
       dev->state = XenbusStateClosing;
@@ -349,27 +384,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
       /* Wait for the backend to close and unmap shared pages, ignore any errors */
       wait_for_backend_state_changed(dev, XenbusStateClosed);
 
-      /* Cleanup any shared pages */
-      if(dev->pages) {
-	 for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
-	    if(dev->pages[i]) {
-	       tx = &dev->tx->ring[i].req;
-	       if(tx->ref != 0) {
-		  gnttab_end_access(tx->ref);
-	       }
-	       free_page(dev->pages[i]);
-	    }
-	 }
-	 free(dev->pages);
-      }
-
       /* Close event channel and unmap shared page */
       mask_evtchn(dev->evtchn);
       unbind_evtchn(dev->evtchn);
       gnttab_end_access(dev->ring_ref);
 
-      free_page(dev->tx);
-
+      free_page(dev->page);
    }
 
    /* Cleanup memory usage */
@@ -387,13 +407,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
 
 int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
 {
+   unsigned int offset;
+   vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
    int i;
-   tpmif_tx_request_t* tx = NULL;
+#endif
    /* Error Checking */
    if(dev == NULL || dev->state != XenbusStateConnected) {
       TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
       return -1;
    }
+   shr = dev->page;
 
 #ifdef TPMFRONT_PRINT_DEBUG
    TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
@@ -407,19 +431,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
 #endif
 
    /* Copy to shared pages now */
-   for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
-      /* Share the page */
-      tx = &dev->tx->ring[i].req;
-      tx->unused = 0;
-      tx->addr = virt_to_mach(dev->pages[i]);
-      tx->ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->pages[i]), 0);
-      /* Copy the bits to the page */
-      tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
-      memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
-
-      /* Update counters */
-      length -= tx->size;
+   offset = sizeof(*shr);
+   if (length + offset > PAGE_SIZE) {
+      TPMFRONT_ERR("Message too long for shared page\n");
+      return -1;
    }
+   memcpy(offset + (uint8_t*)shr, msg, length);
+   shr->length = length;
+   barrier();
+   shr->state = 1;
+
    dev->waiting = 1;
    dev->resplen = 0;
 #ifdef HAVE_LIBC
@@ -434,44 +455,41 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
 }
 int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
 {
-   tpmif_tx_request_t* tx;
-   int i;
+   unsigned int offset;
+   vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+int i;
+#endif
    if(dev == NULL || dev->state != XenbusStateConnected) {
       TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
       return -1;
    }
    /*Wait for the response */
    wait_event(dev->waitq, (!dev->waiting));
+   shr = dev->page;
+   if (shr->state != 0)
+      goto quit;
 
    /* Initialize */
    *msg = NULL;
-   *length = 0;
+   *length = shr->length;
+   offset = sizeof(*shr);
 
-   /* special case, just quit */
-   tx = &dev->tx->ring[0].req;
-   if(tx->size == 0 ) {
-       goto quit;
-   }
-   /* Get the total size */
-   tx = &dev->tx->ring[0].req;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
-      tx = &dev->tx->ring[i].req;
-      *length += tx->size;
+   if (*length + offset > PAGE_SIZE) {
+      TPMFRONT_ERR("Reply too long for shared page\n");
+      return -1;
    }
+
    /* Alloc the buffer */
    if(dev->respbuf) {
       free(dev->respbuf);
    }
    *msg = dev->respbuf = malloc(*length);
    dev->resplen = *length;
+
    /* Copy the bits */
-   tx = &dev->tx->ring[0].req;
-   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
-      tx = &dev->tx->ring[i].req;
-      memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
-      gnttab_end_access(tx->ref);
-      tx->ref = 0;
-   }
+   memcpy(*msg, offset + (uint8_t*)shr, *length);
+
 #ifdef TPMFRONT_PRINT_DEBUG
    TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
    for(i = 0; i < *length; ++i) {
@@ -504,6 +522,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t*
    return 0;
 }
 
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
+{
+   if (!dev || !dev->page)
+      return -1;
+   dev->page->locality = locality;
+   return 0;
+}
+
 #ifdef HAVE_LIBC
 #include <errno.h>
 int tpmfront_open(struct tpmfront_dev* dev)
diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h
index 02ccdab..afc9181 100644
--- a/xen/include/public/io/tpmif.h
+++ b/xen/include/public/io/tpmif.h
@@ -1,7 +1,7 @@
 /******************************************************************************
  * tpmif.h
  *
- * TPM I/O interface for Xen guest OSes.
+ * TPM I/O interface for Xen guest OSes, v2
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -21,48 +21,23 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Copyright (c) 2005, IBM Corporation
- *
- * Author: Stefan Berger, stefanb@us.ibm.com
- * Grant table support: Mahadevan Gomathisankaran
- *
- * This code has been derived from tools/libxc/xen/io/netif.h
- *
- * Copyright (c) 2003-2004, Keir Fraser
  */
 
 #ifndef __XEN_PUBLIC_IO_TPMIF_H__
 #define __XEN_PUBLIC_IO_TPMIF_H__
 
-#include "../grant_table.h"
+struct vtpm_shared_page {
+    uint16_t length;         /* request/response length in bytes */
 
-struct tpmif_tx_request {
-    unsigned long addr;   /* Machine address of packet.   */
-    grant_ref_t ref;      /* grant table access reference */
-    uint16_t unused;
-    uint16_t size;        /* Packet size in bytes.        */
-};
-typedef struct tpmif_tx_request tpmif_tx_request_t;
-
-/*
- * The TPMIF_TX_RING_SIZE defines the number of pages the
- * front-end and backend can exchange (= size of array).
- */
-typedef uint32_t TPMIF_RING_IDX;
-
-#define TPMIF_TX_RING_SIZE 1
-
-/* This structure must fit in a memory page. */
-
-struct tpmif_ring {
-    struct tpmif_tx_request req;
-};
-typedef struct tpmif_ring tpmif_ring_t;
+    uint8_t state;           /* 0 - response ready / idle
+                              * 1 - request ready / working */
+    uint8_t locality;        /* for the current request */
+    uint8_t padding[3];
 
-struct tpmif_tx_interface {
-    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
+    uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
+    uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
 };
-typedef struct tpmif_tx_interface tpmif_tx_interface_t;
+typedef struct vtpm_shared_page vtpm_shared_page_t;
 
 #endif
 
-- 
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  2012-11-27 15:14   ` [PATCH 0/4] stubdom/vtpm improvements Daniel De Graaf
  2012-11-27 15:14     ` [PATCH 1/4] stubdom: Change vTPM shared page ABI Daniel De Graaf
@ 2012-11-27 15:14     ` Daniel De Graaf
  2012-11-27 16:44       ` Samuel Thibault
  2012-11-29 18:53       ` Matthew Fioravante
  2012-11-27 15:14     ` [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM Daniel De Graaf
                       ` (2 subsequent siblings)
  4 siblings, 2 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 15:14 UTC (permalink / raw)
  To: matthew.fioravante; +Cc: dgdegra, Ian.Campbell, xen-devel
Allow the vtpm device to be disconnected and reconnected so that a
bootloader (like pv-grub) can submit measurements and return the vtpm
device to its initial state before booting the target kernel.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
  |  2 +-
           |  2 +-
           |  5 +++++
          | 15 +++++++++------
 stubdom/vtpm/vtpm.c               |  2 +-
 5 files changed, 17 insertions(+), 9 deletions(-)
 --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
index a0c7c4d..913faa4 100644
--- a/extras/mini-os/include/tpmfront.h
+++ b/extras/mini-os/include/tpmfront.h
@@ -61,7 +61,7 @@ struct tpmfront_dev {
 /*Initialize frontend */
 struct tpmfront_dev* init_tpmfront(const char* nodename);
 /*Shutdown frontend */
-void shutdown_tpmfront(struct tpmfront_dev* dev);
+void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig);
 
 /* Send a tpm command to the backend and wait for the response
  *
 --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
index 3cc3340..03da4f0 100644
--- a/extras/mini-os/lib/sys.c
+++ b/extras/mini-os/lib/sys.c
@@ -459,7 +459,7 @@ int close(int fd)
 #endif
 #ifdef CONFIG_TPMFRONT
 	case FTYPE_TPMFRONT:
-            shutdown_tpmfront(files[fd].tpmfront.dev);
+            shutdown_tpmfront(files[fd].tpmfront.dev, 0);
 	    files[fd].type = FTYPE_NONE;
 	    return 0;
 #endif
 --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
index 2d31061..ea42235 100644
--- a/extras/mini-os/tpmback.c
+++ b/extras/mini-os/tpmback.c
@@ -664,6 +664,7 @@ static int frontend_changed(tpmif_t* tpmif)
    switch (state) {
       case XenbusStateInitialising:
       case XenbusStateInitialised:
+      case XenbusStateReconfigured:
 	 break;
 
       case XenbusStateConnected:
@@ -678,6 +679,10 @@ static int frontend_changed(tpmif_t* tpmif)
 	 tpmif_change_state(tpmif, XenbusStateClosing);
 	 break;
 
+      case XenbusStateReconfiguring:
+         disconnect_fe(tpmif);
+	 break;
+
       case XenbusStateUnknown: /* keep it here */
       case XenbusStateClosed:
 	 free_tpmif(tpmif);
 --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index c1cbab3..b725ba0 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -344,10 +344,10 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
    return dev;
 
 error:
-   shutdown_tpmfront(dev);
+   shutdown_tpmfront(dev, 0);
    return NULL;
 }
-void shutdown_tpmfront(struct tpmfront_dev* dev)
+void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig)
 {
    char* err;
    char path[512];
@@ -357,8 +357,7 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
    TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
    /* disconnect */
    if(dev->state == XenbusStateConnected) {
-      dev->state = XenbusStateClosing;
-      //FIXME: Transaction for this?
+      dev->state = for_reconfig ? XenbusStateReconfiguring : XenbusStateClosing;
       /* Tell backend we are closing */
       if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
 	 free(err);
@@ -374,15 +373,19 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
 	 free(err);
       }
 
+      if (for_reconfig)
+         wait_for_backend_state_changed(dev, XenbusStateReconfigured);
+
       /* Tell backend we are closed */
-      dev->state = XenbusStateClosed;
+      dev->state = for_reconfig ? XenbusStateInitialising : XenbusStateClosed;
       if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
 	 TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
 	 free(err);
       }
 
       /* Wait for the backend to close and unmap shared pages, ignore any errors */
-      wait_for_backend_state_changed(dev, XenbusStateClosed);
+      if (!for_reconfig)
+         wait_for_backend_state_changed(dev, XenbusStateClosed);
 
       /* Close event channel and unmap shared page */
       mask_evtchn(dev->evtchn);
diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
index 71aef78..c33e078 100644
--- a/stubdom/vtpm/vtpm.c
+++ b/stubdom/vtpm/vtpm.c
@@ -394,7 +394,7 @@ abort_postvtpmblk:
 abort_postrng:
 
    /* Close devices */
-   shutdown_tpmfront(tpmfront_dev);
+   shutdown_tpmfront(tpmfront_dev, 0);
 abort_posttpmfront:
    shutdown_tpmback();
 
-- 
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM
  2012-11-27 15:14   ` [PATCH 0/4] stubdom/vtpm improvements Daniel De Graaf
  2012-11-27 15:14     ` [PATCH 1/4] stubdom: Change vTPM shared page ABI Daniel De Graaf
  2012-11-27 15:14     ` [PATCH 2/4] stubdom/vtpm: Add reconfiguration support Daniel De Graaf
@ 2012-11-27 15:14     ` Daniel De Graaf
  2012-11-27 16:41       ` Samuel Thibault
  2012-11-27 18:08       ` Matthew Fioravante
  2012-11-27 15:14     ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Daniel De Graaf
  2012-11-27 16:46     ` [PATCH 0/4] stubdom/vtpm improvements Samuel Thibault
  4 siblings, 2 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 15:14 UTC (permalink / raw)
  To: matthew.fioravante; +Cc: dgdegra, Ian.Campbell, xen-devel
This allows a domU with an arbitrary kernel and initrd to take advantage
of the static root of trust provided by a vTPM.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
 stubdom/grub/Makefile   |   2 +-
 stubdom/grub/kexec.c    |  62 ++++++++++++
 stubdom/grub/minios.cfg |   1 +
 stubdom/grub/sha1.c     | 260 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 stubdom/grub/sha1.c
diff --git a/stubdom/grub/Makefile b/stubdom/grub/Makefile
index d6e3a1e..f1b5c3e 100644
--- a/stubdom/grub/Makefile
+++ b/stubdom/grub/Makefile
@@ -59,7 +59,7 @@ NETBOOT_SOURCES:=$(addprefix netboot/,$(NETBOOT_SOURCES))
 
 $(BOOT): DEF_CPPFLAGS+=-D__ASSEMBLY__
 
-PV_GRUB_SOURCES = kexec.c mini-os.c
+PV_GRUB_SOURCES = sha1.c kexec.c mini-os.c
 
 SOURCES = $(NETBOOT_SOURCES) $(STAGE2_SOURCES) $(PV_GRUB_SOURCES)
 
diff --git a/stubdom/grub/kexec.c b/stubdom/grub/kexec.c
index b21c91a..ba48cb7 100644
--- a/stubdom/grub/kexec.c
+++ b/stubdom/grub/kexec.c
@@ -117,6 +117,66 @@ int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to)
     return 0;
 }
 
+static inline uint16_t be16(uint16_t v)
+{
+	return (v >> 8) | (v << 8);
+}
+
+static inline uint32_t be32(uint32_t v)
+{
+	return (be16(v) << 16) | be16(v >> 16);
+}
+
+void sha_compute(uint32_t *buf, void *src, uint32_t len);
+
+#include <tpmfront.h>
+
+#define TPM_TAG_RQU_COMMAND 0xC1
+#define TPM_ORD_Extend 20
+
+struct pcr_extend_cmd {
+	uint16_t tag;
+	uint32_t size;
+	uint32_t ord;
+
+	uint32_t pcr;
+	uint32_t hash[5];
+} __attribute__((packed));
+
+static void tpm_hash2pcr(struct xc_dom_image *dom, char *cmdline)
+{
+	struct tpmfront_dev* tpm = init_tpmfront(NULL);
+	uint8_t *resp;
+	size_t resplen = 0;
+	struct pcr_extend_cmd cmd;
+
+	/* If all guests have access to a vTPM, it may be useful to replace this
+	 * with ASSERT(tpm) to prevent configuration errors from allowing a guest
+	 * to boot without a TPM (or with a TPM that has not been sent any
+	 * measurements, which could allow forging the measurements).
+	 */
+	if (!tpm)
+		return;
+
+	cmd.tag = be16(TPM_TAG_RQU_COMMAND);
+	cmd.size = be32(sizeof(cmd));
+	cmd.ord = be32(TPM_ORD_Extend);
+	cmd.pcr = be32(4); // PCR #4 for kernel
+	sha_compute(cmd.hash, dom->kernel_blob, dom->kernel_size);
+
+	tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
+
+	cmd.pcr = be32(5); // PCR #5 for cmdline
+	sha_compute(cmd.hash, cmdline, strlen(cmdline));
+	tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
+
+	cmd.pcr = be32(5); // PCR #5 for initrd
+	sha_compute(cmd.hash, dom->ramdisk_blob, dom->ramdisk_size);
+	tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
+
+	shutdown_tpmfront(tpm, 1);
+}
+
 void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags)
 {
     struct xc_dom_image *dom;
@@ -151,6 +211,8 @@ void kexec(void *kernel, long kernel_size, void *module, long module_size, char
     dom->console_evtchn = start_info.console.domU.evtchn;
     dom->xenstore_evtchn = start_info.store_evtchn;
 
+    tpm_hash2pcr(dom, cmdline);
+
     if ( (rc = xc_dom_boot_xen_init(dom, xc_handle, domid)) != 0 ) {
         grub_printf("xc_dom_boot_xen_init returned %d\n", rc);
         errnum = ERR_BOOT_FAILURE;
diff --git a/stubdom/grub/minios.cfg b/stubdom/grub/minios.cfg
index 40cfa68..8df4909 100644
--- a/stubdom/grub/minios.cfg
+++ b/stubdom/grub/minios.cfg
@@ -1,2 +1,3 @@
 CONFIG_START_NETWORK=n
 CONFIG_SPARSE_BSS=n
+CONFIG_TPMFRONT=y
diff --git a/stubdom/grub/sha1.c b/stubdom/grub/sha1.c
new file mode 100644
index 0000000..2ad2e07
--- /dev/null
+++ b/stubdom/grub/sha1.c
@@ -0,0 +1,260 @@
+/*
+ * SHA1 routine optimized to do word accesses rather than byte accesses,
+ * and to avoid unnecessary copies into the context array.
+ *
+ * This was based on the git SHA1 implementation.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+static inline uint16_t be16(uint16_t v)
+{
+	return (v >> 8) | (v << 8);
+}
+
+static inline uint32_t be32(uint32_t v)
+{
+	return (be16(v) << 16) | be16(v >> 16);
+}
+
+static inline uint32_t get_unaligned_be32(uint32_t *v)
+{
+	return be32(*v);
+}
+
+/*
+ * rol32 - rotate a 32-bit value left
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint32_t rol32(uint32_t word, unsigned int shift)
+{
+    return (word << shift) | (word >> (32 - shift));
+}
+
+/*
+ * ror32 - rotate a 32-bit value right
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline uint32_t ror32(uint32_t word, unsigned int shift)
+{
+    return (word >> shift) | (word << (32 - shift));
+}
+
+
+/*
+ * If you have 32 registers or more, the compiler can (and should)
+ * try to change the array[] accesses into registers. However, on
+ * machines with less than ~25 registers, that won't really work,
+ * and at least gcc will make an unholy mess of it.
+ *
+ * So to avoid that mess which just slows things down, we force
+ * the stores to memory to actually happen (we might be better off
+ * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
+ * suggested by Artur Skawina - that will also make gcc unable to
+ * try to do the silly "optimize away loads" part because it won't
+ * see what the value will be).
+ *
+ * Ben Herrenschmidt reports that on PPC, the C version comes close
+ * to the optimized asm with this (ie on PPC you don't want that
+ * 'volatile', since there are lots of registers).
+ *
+ * On ARM we get the best code generation by forcing a full memory barrier
+ * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
+ * the stack frame size simply explode and performance goes down the drain.
+ */
+
+#if 1
+  #define setW(x, val) (*(volatile uint32_t *)&W(x) = (val))
+#else
+  #define setW(x, val) (W(x) = (val))
+#endif
+
+/* This "rolls" over the 512-bit array */
+#define W(x) (array[(x)&15])
+
+/*
+ * Where do we get the source from? The first 16 iterations get it from
+ * the input data, the next mix it from the 512-bit array.
+ */
+#define SHA_SRC(t) get_unaligned_be32((uint32_t *)data + t)
+#define SHA_MIX(t) rol32(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
+
+#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
+	uint32_t TEMP = input(t); setW(t, TEMP); \
+	E += TEMP + rol32(A,5) + (fn) + (constant); \
+	B = ror32(B, 2); } while (0)
+
+#define T_0_15(t, A, B, C, D, E)  SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
+#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
+#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) ,  0xca62c1d6, A, B, C, D, E )
+
+/**
+ * sha_transform - single block SHA1 transform
+ *
+ * @digest: 160 bit digest to update
+ * @data:   512 bits of data to hash
+ * @array:  16 words of workspace (see note)
+ *
+ * This function generates a SHA1 digest for a single 512-bit block.
+ * Be warned, it does not handle padding and message digest, do not
+ * confuse it with the full FIPS 180-1 digest algorithm for variable
+ * length messages.
+ *
+ * Note: If the hash is security sensitive, the caller should be sure
+ * to clear the workspace. This is left to the caller to avoid
+ * unnecessary clears between chained hashing operations.
+ */
+void sha_transform(uint32_t *digest, const char *data, uint32_t *array)
+{
+	uint32_t A, B, C, D, E;
+
+	A = digest[0];
+	B = digest[1];
+	C = digest[2];
+	D = digest[3];
+	E = digest[4];
+
+	/* Round 1 - iterations 0-16 take their input from 'data' */
+	T_0_15( 0, A, B, C, D, E);
+	T_0_15( 1, E, A, B, C, D);
+	T_0_15( 2, D, E, A, B, C);
+	T_0_15( 3, C, D, E, A, B);
+	T_0_15( 4, B, C, D, E, A);
+	T_0_15( 5, A, B, C, D, E);
+	T_0_15( 6, E, A, B, C, D);
+	T_0_15( 7, D, E, A, B, C);
+	T_0_15( 8, C, D, E, A, B);
+	T_0_15( 9, B, C, D, E, A);
+	T_0_15(10, A, B, C, D, E);
+	T_0_15(11, E, A, B, C, D);
+	T_0_15(12, D, E, A, B, C);
+	T_0_15(13, C, D, E, A, B);
+	T_0_15(14, B, C, D, E, A);
+	T_0_15(15, A, B, C, D, E);
+
+	/* Round 1 - tail. Input from 512-bit mixing array */
+	T_16_19(16, E, A, B, C, D);
+	T_16_19(17, D, E, A, B, C);
+	T_16_19(18, C, D, E, A, B);
+	T_16_19(19, B, C, D, E, A);
+
+	/* Round 2 */
+	T_20_39(20, A, B, C, D, E);
+	T_20_39(21, E, A, B, C, D);
+	T_20_39(22, D, E, A, B, C);
+	T_20_39(23, C, D, E, A, B);
+	T_20_39(24, B, C, D, E, A);
+	T_20_39(25, A, B, C, D, E);
+	T_20_39(26, E, A, B, C, D);
+	T_20_39(27, D, E, A, B, C);
+	T_20_39(28, C, D, E, A, B);
+	T_20_39(29, B, C, D, E, A);
+	T_20_39(30, A, B, C, D, E);
+	T_20_39(31, E, A, B, C, D);
+	T_20_39(32, D, E, A, B, C);
+	T_20_39(33, C, D, E, A, B);
+	T_20_39(34, B, C, D, E, A);
+	T_20_39(35, A, B, C, D, E);
+	T_20_39(36, E, A, B, C, D);
+	T_20_39(37, D, E, A, B, C);
+	T_20_39(38, C, D, E, A, B);
+	T_20_39(39, B, C, D, E, A);
+
+	/* Round 3 */
+	T_40_59(40, A, B, C, D, E);
+	T_40_59(41, E, A, B, C, D);
+	T_40_59(42, D, E, A, B, C);
+	T_40_59(43, C, D, E, A, B);
+	T_40_59(44, B, C, D, E, A);
+	T_40_59(45, A, B, C, D, E);
+	T_40_59(46, E, A, B, C, D);
+	T_40_59(47, D, E, A, B, C);
+	T_40_59(48, C, D, E, A, B);
+	T_40_59(49, B, C, D, E, A);
+	T_40_59(50, A, B, C, D, E);
+	T_40_59(51, E, A, B, C, D);
+	T_40_59(52, D, E, A, B, C);
+	T_40_59(53, C, D, E, A, B);
+	T_40_59(54, B, C, D, E, A);
+	T_40_59(55, A, B, C, D, E);
+	T_40_59(56, E, A, B, C, D);
+	T_40_59(57, D, E, A, B, C);
+	T_40_59(58, C, D, E, A, B);
+	T_40_59(59, B, C, D, E, A);
+
+	/* Round 4 */
+	T_60_79(60, A, B, C, D, E);
+	T_60_79(61, E, A, B, C, D);
+	T_60_79(62, D, E, A, B, C);
+	T_60_79(63, C, D, E, A, B);
+	T_60_79(64, B, C, D, E, A);
+	T_60_79(65, A, B, C, D, E);
+	T_60_79(66, E, A, B, C, D);
+	T_60_79(67, D, E, A, B, C);
+	T_60_79(68, C, D, E, A, B);
+	T_60_79(69, B, C, D, E, A);
+	T_60_79(70, A, B, C, D, E);
+	T_60_79(71, E, A, B, C, D);
+	T_60_79(72, D, E, A, B, C);
+	T_60_79(73, C, D, E, A, B);
+	T_60_79(74, B, C, D, E, A);
+	T_60_79(75, A, B, C, D, E);
+	T_60_79(76, E, A, B, C, D);
+	T_60_79(77, D, E, A, B, C);
+	T_60_79(78, C, D, E, A, B);
+	T_60_79(79, B, C, D, E, A);
+
+	digest[0] += A;
+	digest[1] += B;
+	digest[2] += C;
+	digest[3] += D;
+	digest[4] += E;
+}
+
+/**
+ * sha_init - initialize the vectors for a SHA1 digest
+ * @buf: vector to initialize
+ */
+void sha_init(uint32_t *buf)
+{
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+	buf[4] = 0xc3d2e1f0;
+}
+
+void sha_compute(uint32_t *buf, void *src, uint32_t len)
+{
+	uint32_t pos = 0;
+	uint8_t final[64];
+	uint32_t work[16];
+	sha_init(buf);
+	while (len >= pos + 64) {
+		sha_transform(buf, src + pos, work);
+		pos += 64;
+	}
+	memcpy(final, src + pos, len - pos);
+	// done with src; pos is now relative to final
+	pos = len - pos;
+	final[pos++] = 0x80;
+	memset(final + pos, 0, sizeof(final) - pos);
+	if (pos > 56) {
+		sha_transform(buf, (void*)final, work);
+		memset(final, 0, sizeof(final));
+	}
+	*(uint32_t*)(final + 60) = be32(len << 3);
+	sha_transform(buf, (void*)final, work);
+	buf[0] = be32(buf[0]);
+	buf[1] = be32(buf[1]);
+	buf[2] = be32(buf[2]);
+	buf[3] = be32(buf[3]);
+	buf[4] = be32(buf[4]);
+}
-- 
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 15:14   ` [PATCH 0/4] stubdom/vtpm improvements Daniel De Graaf
                       ` (2 preceding siblings ...)
  2012-11-27 15:14     ` [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM Daniel De Graaf
@ 2012-11-27 15:14     ` Daniel De Graaf
  2012-11-27 16:42       ` Samuel Thibault
                         ` (2 more replies)
  2012-11-27 16:46     ` [PATCH 0/4] stubdom/vtpm improvements Samuel Thibault
  4 siblings, 3 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 15:14 UTC (permalink / raw)
  To: matthew.fioravante; +Cc: dgdegra, Ian.Campbell, xen-devel
The vTPM protocol now contains a field allowing the locality of a
command to be specified; pass this to the TPM when processing a packet.
This also enables a single vTPM to provide multiple tpmback interfaces
so that several closely related domains can share a vTPM (for example, a
qemu device stubdom and its target domain).
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
 stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
 stubdom/vtpm/vtpm.c        | 16 +++---------
 2 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
index b84eff1..31ace1a 100644
--- a/stubdom/tpmemu-0.7.4.patch
+++ b/stubdom/tpmemu-0.7.4.patch
@@ -1,9 +1,60 @@
-diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c	2012-04-27 10:55:46.581963398 -0400
-+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c	2012-04-27 10:56:02.193034152 -0400
-@@ -249,7 +249,7 @@
+diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
+index 60bbb90..f8f7f0f 100644
+--- a/tpm/tpm_capability.c
++++ b/tpm/tpm_capability.c
+@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
+                              UINT32 setValueSize, BOOL ownerAuth,
+                              BOOL deactivated, BOOL disabled)
+ {
++  if (tpmData.stany.flags.localityModifier != 8)
++    return TPM_BAD_PARAMETER;
+   /* set the capability area with the specified data, on failure
+      deactivate the TPM */
+   switch (subCap) {
+diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
+index 288d1ce..9e1cfb4 100644
+--- a/tpm/tpm_cmd_handler.c
++++ b/tpm/tpm_cmd_handler.c
+@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
+   tpm_extern_release();
+ }
+ 
+-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
+ {
+   TPM_REQUEST req;
+   TPM_RESPONSE rsp;
+@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
+   UINT32 len;
+   BOOL free_out;
+ 
+-  debug("tpm_handle_command()");
++  debug("tpm_handle_command(%d)", locality);
++  if (locality != -1)
++    tpmData.stany.flags.localityModifier = locality;
+ 
+   /* we need the whole packet at once, otherwise unmarshalling will fail */
+   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
+diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
+index eed749e..4c228bd 100644
+--- a/tpm/tpm_emulator.h
++++ b/tpm/tpm_emulator.h
+@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
+  * its usage. In case of an error, all internally allocated memory
+  * is released and the the state of out and out_size is unspecified.
+  */ 
+-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
+ 
+ #endif /* _TPM_EMULATOR_H_ */
+ 
+diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
+index aabe6c3..440a01b 100644
+--- a/tpm/tpm_emulator_extern.c
++++ b/tpm/tpm_emulator_extern.c
+@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
  #else /* TPM_NO_EXTERN */
-
+ 
  int (*tpm_extern_init)(void)                                      = NULL;
 -int (*tpm_extern_release)(void)                                   = NULL;
 +void (*tpm_extern_release)(void)                                   = NULL;
diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
index c33e078..dcfc3b9 100644
--- a/stubdom/vtpm/vtpm.c
+++ b/stubdom/vtpm/vtpm.c
@@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
 
 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");
@@ -162,15 +160,7 @@ static void main_loop(void) {
       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);
+   tpmcmd = tpmback_req_any();
    while(tpmcmd) {
       /* Handle the request */
       if(tpmcmd->req_len) {
@@ -183,7 +173,7 @@ static void main_loop(void) {
          }
          /* If not disabled, do the command */
          else {
-            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
+            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
                error("tpm_handle_command() failed");
                create_error_response(tpmcmd, TPM_FAIL);
             }
@@ -194,7 +184,7 @@ static void main_loop(void) {
       tpmback_resp(tpmcmd);
 
       /* Wait for the next request */
-      tpmcmd = tpmback_req(domid, handle);
+      tpmcmd = tpmback_req_any();
 
    }
 
-- 
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* Re: [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM
  2012-11-27 15:14     ` [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM Daniel De Graaf
@ 2012-11-27 16:41       ` Samuel Thibault
  2012-11-27 18:08       ` Matthew Fioravante
  1 sibling, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-27 16:41 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: matthew.fioravante, Ian.Campbell, xen-devel
Daniel De Graaf, le Tue 27 Nov 2012 10:14:45 -0500, a écrit :
> +static inline uint16_t be16(uint16_t v)
> +{
> +	return (v >> 8) | (v << 8);
> +}
> +
> +static inline uint32_t be32(uint32_t v)
> +{
> +	return (be16(v) << 16) | be16(v >> 16);
> +}
Better use the existing bswap_16 and bswap_32.
> +void sha_compute(uint32_t *buf, void *src, uint32_t len);
> +++ b/stubdom/grub/sha1.c
I guess it could find its way in mini-os/lib?
BTW, what is the licence and copyright of this implementation?  We need
to be sure about that.
> @@ -0,0 +1,260 @@
> +/*
> + * SHA1 routine optimized to do word accesses rather than byte accesses,
> + * and to avoid unnecessary copies into the context array.
> + *
> + * This was based on the git SHA1 implementation.
> + */
> +
> +#include <stdint.h>
> +#include <string.h>
> +
> +static inline uint16_t be16(uint16_t v)
> +{
> +	return (v >> 8) | (v << 8);
> +}
> +
> +static inline uint32_t be32(uint32_t v)
> +{
> +	return (be16(v) << 16) | be16(v >> 16);
> +}
Ditto bswap_16/32
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 15:14     ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Daniel De Graaf
@ 2012-11-27 16:42       ` Samuel Thibault
  2012-11-27 18:19       ` Matthew Fioravante
  2012-11-29 19:09       ` Matthew Fioravante
  2 siblings, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-27 16:42 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: matthew.fioravante, Ian.Campbell, xen-devel
I let Matthew comment on patches 1 and 4.
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  2012-11-27 15:14     ` [PATCH 2/4] stubdom/vtpm: Add reconfiguration support Daniel De Graaf
@ 2012-11-27 16:44       ` Samuel Thibault
  2012-11-29 18:53       ` Matthew Fioravante
  1 sibling, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-27 16:44 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: matthew.fioravante, Ian.Campbell, xen-devel
Daniel De Graaf, le Tue 27 Nov 2012 10:14:44 -0500, a écrit :
> -void shutdown_tpmfront(struct tpmfront_dev* dev)
> +void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig)
Do we really need to explicit "for_reconfig"?  We didn't need it for
fbfront/blkfront/etc. (we just needed to fix some bugs), is tpm anything
particular here?
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 0/4] stubdom/vtpm improvements
  2012-11-27 15:14   ` [PATCH 0/4] stubdom/vtpm improvements Daniel De Graaf
                       ` (3 preceding siblings ...)
  2012-11-27 15:14     ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Daniel De Graaf
@ 2012-11-27 16:46     ` Samuel Thibault
  4 siblings, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-27 16:46 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: matthew.fioravante, Ian.Campbell, xen-devel
Daniel De Graaf, le Tue 27 Nov 2012 10:14:42 -0500, a écrit :
> Since pv-grub is already GPL, there should be no licensing issues
> created by adding the vTPM code and the Linux SHA1 implementation.
Ah, I should have read this before :)
Yes, the GPL licence shouldn't pose problem (and thus the sha1
implementation should stay in grub/, and not go to mini-os/lib as I
suggested.
We still need to know the copyright for the file.
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM
  2012-11-27 15:14     ` [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM Daniel De Graaf
  2012-11-27 16:41       ` Samuel Thibault
@ 2012-11-27 18:08       ` Matthew Fioravante
  2012-11-27 18:36         ` Samuel Thibault
  2012-11-27 18:53         ` Daniel De Graaf
  1 sibling, 2 replies; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-27 18:08 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 14462 bytes --]
On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
> This allows a domU with an arbitrary kernel and initrd to take advantage
> of the static root of trust provided by a vTPM.
Do you have any documentation updates for how to use it? They could be 
added to the vtpm documentation if thats the most appropriate location.
How exactly does this work? Is it intended for HVM domains whos stubdom 
is connected to a vtpm? I've never tried to use vtpm with HVMs yet, so 
I'd be very surprised if it just works. Does it work for PVM domains?
I'm not terribly familiar with how grub in stubdom works.
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   stubdom/grub/Makefile   |   2 +-
>   stubdom/grub/kexec.c    |  62 ++++++++++++
>   stubdom/grub/minios.cfg |   1 +
>   stubdom/grub/sha1.c     | 260 ++++++++++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 324 insertions(+), 1 deletion(-)
>   create mode 100644 stubdom/grub/sha1.c
>
> diff --git a/stubdom/grub/Makefile b/stubdom/grub/Makefile
> index d6e3a1e..f1b5c3e 100644
> --- a/stubdom/grub/Makefile
> +++ b/stubdom/grub/Makefile
> @@ -59,7 +59,7 @@ NETBOOT_SOURCES:=$(addprefix netboot/,$(NETBOOT_SOURCES))
>
>   $(BOOT): DEF_CPPFLAGS+=-D__ASSEMBLY__
>
> -PV_GRUB_SOURCES = kexec.c mini-os.c
> +PV_GRUB_SOURCES = sha1.c kexec.c mini-os.c
>
>   SOURCES = $(NETBOOT_SOURCES) $(STAGE2_SOURCES) $(PV_GRUB_SOURCES)
>
> diff --git a/stubdom/grub/kexec.c b/stubdom/grub/kexec.c
> index b21c91a..ba48cb7 100644
> --- a/stubdom/grub/kexec.c
> +++ b/stubdom/grub/kexec.c
> @@ -117,6 +117,66 @@ int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to)
>       return 0;
>   }
>
> +static inline uint16_t be16(uint16_t v)
> +{
> +       return (v >> 8) | (v << 8);
> +}
> +
> +static inline uint32_t be32(uint32_t v)
> +{
> +       return (be16(v) << 16) | be16(v >> 16);
> +}
> +
> +void sha_compute(uint32_t *buf, void *src, uint32_t len);
> +
> +#include <tpmfront.h>
> +
> +#define TPM_TAG_RQU_COMMAND 0xC1
> +#define TPM_ORD_Extend 20
> +
> +struct pcr_extend_cmd {
> +       uint16_t tag;
> +       uint32_t size;
> +       uint32_t ord;
> +
> +       uint32_t pcr;
> +       uint32_t hash[5];
> +} __attribute__((packed));
> +
> +static void tpm_hash2pcr(struct xc_dom_image *dom, char *cmdline)
> +{
> +       struct tpmfront_dev* tpm = init_tpmfront(NULL);
> +       uint8_t *resp;
> +       size_t resplen = 0;
> +       struct pcr_extend_cmd cmd;
> +
> +       /* If all guests have access to a vTPM, it may be useful to replace this
> +        * with ASSERT(tpm) to prevent configuration errors from allowing a guest
> +        * to boot without a TPM (or with a TPM that has not been sent any
> +        * measurements, which could allow forging the measurements).
> +        */
> +       if (!tpm)
> +               return;
> +
> +       cmd.tag = be16(TPM_TAG_RQU_COMMAND);
> +       cmd.size = be32(sizeof(cmd));
> +       cmd.ord = be32(TPM_ORD_Extend);
> +       cmd.pcr = be32(4); // PCR #4 for kernel
> +       sha_compute(cmd.hash, dom->kernel_blob, dom->kernel_size);
> +
> +       tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
> +
> +       cmd.pcr = be32(5); // PCR #5 for cmdline
> +       sha_compute(cmd.hash, cmdline, strlen(cmdline));
> +       tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
> +
> +       cmd.pcr = be32(5); // PCR #5 for initrd
> +       sha_compute(cmd.hash, dom->ramdisk_blob, dom->ramdisk_size);
> +       tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
> +
> +       shutdown_tpmfront(tpm, 1);
> +}
Does this actually work? vtpm-stubdom will shut itself down when the 
frontend tpm disconnects. Is it really ok to connect and disconnect 
these devices at will?
> +
>   void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags)
>   {
>       struct xc_dom_image *dom;
> @@ -151,6 +211,8 @@ void kexec(void *kernel, long kernel_size, void *module, long module_size, char
>       dom->console_evtchn = start_info.console.domU.evtchn;
>       dom->xenstore_evtchn = start_info.store_evtchn;
>
> +    tpm_hash2pcr(dom, cmdline);
> +
>       if ( (rc = xc_dom_boot_xen_init(dom, xc_handle, domid)) != 0 ) {
>           grub_printf("xc_dom_boot_xen_init returned %d\n", rc);
>           errnum = ERR_BOOT_FAILURE;
> diff --git a/stubdom/grub/minios.cfg b/stubdom/grub/minios.cfg
> index 40cfa68..8df4909 100644
> --- a/stubdom/grub/minios.cfg
> +++ b/stubdom/grub/minios.cfg
> @@ -1,2 +1,3 @@
>   CONFIG_START_NETWORK=n
>   CONFIG_SPARSE_BSS=n
> +CONFIG_TPMFRONT=y
> diff --git a/stubdom/grub/sha1.c b/stubdom/grub/sha1.c
> new file mode 100644
> index 0000000..2ad2e07
> --- /dev/null
> +++ b/stubdom/grub/sha1.c
> @@ -0,0 +1,260 @@
> +/*
> + * SHA1 routine optimized to do word accesses rather than byte accesses,
> + * and to avoid unnecessary copies into the context array.
> + *
> + * This was based on the git SHA1 implementation.
> + */
> +
> +#include <stdint.h>
> +#include <string.h>
> +
> +static inline uint16_t be16(uint16_t v)
> +{
> +       return (v >> 8) | (v << 8);
> +}
> +
> +static inline uint32_t be32(uint32_t v)
> +{
> +       return (be16(v) << 16) | be16(v >> 16);
> +}
> +
> +static inline uint32_t get_unaligned_be32(uint32_t *v)
> +{
> +       return be32(*v);
> +}
These exist in mini-os byteorder.h now.
> +
> +/*
> + * rol32 - rotate a 32-bit value left
> + *
> + * @word: value to rotate
> + * @shift: bits to roll
> + */
> +static inline uint32_t rol32(uint32_t word, unsigned int shift)
> +{
> +    return (word << shift) | (word >> (32 - shift));
> +}
> +
> +/*
> + * ror32 - rotate a 32-bit value right
> + *
> + * @word: value to rotate
> + * @shift: bits to roll
> + */
> +static inline uint32_t ror32(uint32_t word, unsigned int shift)
> +{
> +    return (word >> shift) | (word << (32 - shift));
> +}
> +
> +
> +/*
> + * If you have 32 registers or more, the compiler can (and should)
> + * try to change the array[] accesses into registers. However, on
> + * machines with less than ~25 registers, that won't really work,
> + * and at least gcc will make an unholy mess of it.
> + *
> + * So to avoid that mess which just slows things down, we force
> + * the stores to memory to actually happen (we might be better off
> + * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
> + * suggested by Artur Skawina - that will also make gcc unable to
> + * try to do the silly "optimize away loads" part because it won't
> + * see what the value will be).
> + *
> + * Ben Herrenschmidt reports that on PPC, the C version comes close
> + * to the optimized asm with this (ie on PPC you don't want that
> + * 'volatile', since there are lots of registers).
> + *
> + * On ARM we get the best code generation by forcing a full memory barrier
> + * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
> + * the stack frame size simply explode and performance goes down the drain.
> + */
> +
> +#if 1
> +  #define setW(x, val) (*(volatile uint32_t *)&W(x) = (val))
> +#else
> +  #define setW(x, val) (W(x) = (val))
> +#endif
> +
> +/* This "rolls" over the 512-bit array */
> +#define W(x) (array[(x)&15])
> +
> +/*
> + * Where do we get the source from? The first 16 iterations get it from
> + * the input data, the next mix it from the 512-bit array.
> + */
> +#define SHA_SRC(t) get_unaligned_be32((uint32_t *)data + t)
> +#define SHA_MIX(t) rol32(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
> +
> +#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
> +       uint32_t TEMP = input(t); setW(t, TEMP); \
> +       E += TEMP + rol32(A,5) + (fn) + (constant); \
> +       B = ror32(B, 2); } while (0)
> +
> +#define T_0_15(t, A, B, C, D, E)  SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
> +#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
> +#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
> +#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
> +#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) ,  0xca62c1d6, A, B, C, D, E )
> +
> +/**
> + * sha_transform - single block SHA1 transform
> + *
> + * @digest: 160 bit digest to update
> + * @data:   512 bits of data to hash
> + * @array:  16 words of workspace (see note)
> + *
> + * This function generates a SHA1 digest for a single 512-bit block.
> + * Be warned, it does not handle padding and message digest, do not
> + * confuse it with the full FIPS 180-1 digest algorithm for variable
> + * length messages.
> + *
> + * Note: If the hash is security sensitive, the caller should be sure
> + * to clear the workspace. This is left to the caller to avoid
> + * unnecessary clears between chained hashing operations.
> + */
> +void sha_transform(uint32_t *digest, const char *data, uint32_t *array)
> +{
> +       uint32_t A, B, C, D, E;
> +
> +       A = digest[0];
> +       B = digest[1];
> +       C = digest[2];
> +       D = digest[3];
> +       E = digest[4];
> +
> +       /* Round 1 - iterations 0-16 take their input from 'data' */
> +       T_0_15( 0, A, B, C, D, E);
> +       T_0_15( 1, E, A, B, C, D);
> +       T_0_15( 2, D, E, A, B, C);
> +       T_0_15( 3, C, D, E, A, B);
> +       T_0_15( 4, B, C, D, E, A);
> +       T_0_15( 5, A, B, C, D, E);
> +       T_0_15( 6, E, A, B, C, D);
> +       T_0_15( 7, D, E, A, B, C);
> +       T_0_15( 8, C, D, E, A, B);
> +       T_0_15( 9, B, C, D, E, A);
> +       T_0_15(10, A, B, C, D, E);
> +       T_0_15(11, E, A, B, C, D);
> +       T_0_15(12, D, E, A, B, C);
> +       T_0_15(13, C, D, E, A, B);
> +       T_0_15(14, B, C, D, E, A);
> +       T_0_15(15, A, B, C, D, E);
> +
> +       /* Round 1 - tail. Input from 512-bit mixing array */
> +       T_16_19(16, E, A, B, C, D);
> +       T_16_19(17, D, E, A, B, C);
> +       T_16_19(18, C, D, E, A, B);
> +       T_16_19(19, B, C, D, E, A);
> +
> +       /* Round 2 */
> +       T_20_39(20, A, B, C, D, E);
> +       T_20_39(21, E, A, B, C, D);
> +       T_20_39(22, D, E, A, B, C);
> +       T_20_39(23, C, D, E, A, B);
> +       T_20_39(24, B, C, D, E, A);
> +       T_20_39(25, A, B, C, D, E);
> +       T_20_39(26, E, A, B, C, D);
> +       T_20_39(27, D, E, A, B, C);
> +       T_20_39(28, C, D, E, A, B);
> +       T_20_39(29, B, C, D, E, A);
> +       T_20_39(30, A, B, C, D, E);
> +       T_20_39(31, E, A, B, C, D);
> +       T_20_39(32, D, E, A, B, C);
> +       T_20_39(33, C, D, E, A, B);
> +       T_20_39(34, B, C, D, E, A);
> +       T_20_39(35, A, B, C, D, E);
> +       T_20_39(36, E, A, B, C, D);
> +       T_20_39(37, D, E, A, B, C);
> +       T_20_39(38, C, D, E, A, B);
> +       T_20_39(39, B, C, D, E, A);
> +
> +       /* Round 3 */
> +       T_40_59(40, A, B, C, D, E);
> +       T_40_59(41, E, A, B, C, D);
> +       T_40_59(42, D, E, A, B, C);
> +       T_40_59(43, C, D, E, A, B);
> +       T_40_59(44, B, C, D, E, A);
> +       T_40_59(45, A, B, C, D, E);
> +       T_40_59(46, E, A, B, C, D);
> +       T_40_59(47, D, E, A, B, C);
> +       T_40_59(48, C, D, E, A, B);
> +       T_40_59(49, B, C, D, E, A);
> +       T_40_59(50, A, B, C, D, E);
> +       T_40_59(51, E, A, B, C, D);
> +       T_40_59(52, D, E, A, B, C);
> +       T_40_59(53, C, D, E, A, B);
> +       T_40_59(54, B, C, D, E, A);
> +       T_40_59(55, A, B, C, D, E);
> +       T_40_59(56, E, A, B, C, D);
> +       T_40_59(57, D, E, A, B, C);
> +       T_40_59(58, C, D, E, A, B);
> +       T_40_59(59, B, C, D, E, A);
> +
> +       /* Round 4 */
> +       T_60_79(60, A, B, C, D, E);
> +       T_60_79(61, E, A, B, C, D);
> +       T_60_79(62, D, E, A, B, C);
> +       T_60_79(63, C, D, E, A, B);
> +       T_60_79(64, B, C, D, E, A);
> +       T_60_79(65, A, B, C, D, E);
> +       T_60_79(66, E, A, B, C, D);
> +       T_60_79(67, D, E, A, B, C);
> +       T_60_79(68, C, D, E, A, B);
> +       T_60_79(69, B, C, D, E, A);
> +       T_60_79(70, A, B, C, D, E);
> +       T_60_79(71, E, A, B, C, D);
> +       T_60_79(72, D, E, A, B, C);
> +       T_60_79(73, C, D, E, A, B);
> +       T_60_79(74, B, C, D, E, A);
> +       T_60_79(75, A, B, C, D, E);
> +       T_60_79(76, E, A, B, C, D);
> +       T_60_79(77, D, E, A, B, C);
> +       T_60_79(78, C, D, E, A, B);
> +       T_60_79(79, B, C, D, E, A);
> +
> +       digest[0] += A;
> +       digest[1] += B;
> +       digest[2] += C;
> +       digest[3] += D;
> +       digest[4] += E;
> +}
> +
> +/**
> + * sha_init - initialize the vectors for a SHA1 digest
> + * @buf: vector to initialize
> + */
> +void sha_init(uint32_t *buf)
> +{
> +       buf[0] = 0x67452301;
> +       buf[1] = 0xefcdab89;
> +       buf[2] = 0x98badcfe;
> +       buf[3] = 0x10325476;
> +       buf[4] = 0xc3d2e1f0;
> +}
> +
> +void sha_compute(uint32_t *buf, void *src, uint32_t len)
> +{
> +       uint32_t pos = 0;
> +       uint8_t final[64];
> +       uint32_t work[16];
> +       sha_init(buf);
> +       while (len >= pos + 64) {
> +               sha_transform(buf, src + pos, work);
> +               pos += 64;
> +       }
> +       memcpy(final, src + pos, len - pos);
> +       // done with src; pos is now relative to final
> +       pos = len - pos;
> +       final[pos++] = 0x80;
> +       memset(final + pos, 0, sizeof(final) - pos);
> +       if (pos > 56) {
> +               sha_transform(buf, (void*)final, work);
> +               memset(final, 0, sizeof(final));
> +       }
> +       *(uint32_t*)(final + 60) = be32(len << 3);
> +       sha_transform(buf, (void*)final, work);
> +       buf[0] = be32(buf[0]);
> +       buf[1] = be32(buf[1]);
> +       buf[2] = be32(buf[2]);
> +       buf[3] = be32(buf[3]);
> +       buf[4] = be32(buf[4]);
> +}
There also exists a sha1 routine in polarssl. You can just link in the 
polarssl sha1 object file without the entire library. This is what 
vtpm-stubdom and vtpmmgrdom do to get the crypto pieces they need. 
Checkout their makefiles for details.
Is there any reason using polarssl would be sub-optimal?
> --
> 1.7.11.7
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 15:14     ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Daniel De Graaf
  2012-11-27 16:42       ` Samuel Thibault
@ 2012-11-27 18:19       ` Matthew Fioravante
  2012-11-27 19:02         ` Daniel De Graaf
  2012-11-29 19:09       ` Matthew Fioravante
  2 siblings, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-27 18:19 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 6140 bytes --]
On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
> The vTPM protocol now contains a field allowing the locality of a
> command to be specified; pass this to the TPM when processing a packet.
> This also enables a single vTPM to provide multiple tpmback interfaces
> so that several closely related domains can share a vTPM (for example, a
> qemu device stubdom and its target domain).
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>   stubdom/vtpm/vtpm.c        | 16 +++---------
>   2 files changed, 59 insertions(+), 18 deletions(-)
>
> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
> index b84eff1..31ace1a 100644
> --- a/stubdom/tpmemu-0.7.4.patch
> +++ b/stubdom/tpmemu-0.7.4.patch
> @@ -1,9 +1,60 @@
> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c	2012-04-27 10:55:46.581963398 -0400
> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c	2012-04-27 10:56:02.193034152 -0400
> -@@ -249,7 +249,7 @@
> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
> +index 60bbb90..f8f7f0f 100644
> +--- a/tpm/tpm_capability.c
> ++++ b/tpm/tpm_capability.c
> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
> +                              UINT32 setValueSize, BOOL ownerAuth,
> +                              BOOL deactivated, BOOL disabled)
> + {
> ++  if (tpmData.stany.flags.localityModifier != 8)
> ++    return TPM_BAD_PARAMETER;
> +   /* set the capability area with the specified data, on failure
> +      deactivate the TPM */
> +   switch (subCap) {
> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
> +index 288d1ce..9e1cfb4 100644
> +--- a/tpm/tpm_cmd_handler.c
> ++++ b/tpm/tpm_cmd_handler.c
> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
> +   tpm_extern_release();
> + }
> +
> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
> + {
> +   TPM_REQUEST req;
> +   TPM_RESPONSE rsp;
> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
> +   UINT32 len;
> +   BOOL free_out;
> +
> +-  debug("tpm_handle_command()");
> ++  debug("tpm_handle_command(%d)", locality);
> ++  if (locality != -1)
> ++    tpmData.stany.flags.localityModifier = locality;
> +
> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
> +index eed749e..4c228bd 100644
> +--- a/tpm/tpm_emulator.h
> ++++ b/tpm/tpm_emulator.h
> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
> +  * its usage. In case of an error, all internally allocated memory
> +  * is released and the the state of out and out_size is unspecified.
> +  */
> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
> +
> + #endif /* _TPM_EMULATOR_H_ */
> +
> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
> +index aabe6c3..440a01b 100644
> +--- a/tpm/tpm_emulator_extern.c
> ++++ b/tpm/tpm_emulator_extern.c
> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>    #else /* TPM_NO_EXTERN */
> -
> +
>    int (*tpm_extern_init)(void)                                      = NULL;
>   -int (*tpm_extern_release)(void)                                   = NULL;
>   +void (*tpm_extern_release)(void)                                   = NULL;
> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
> index c33e078..dcfc3b9 100644
> --- a/stubdom/vtpm/vtpm.c
> +++ b/stubdom/vtpm/vtpm.c
> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>   
>   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");
> @@ -162,15 +160,7 @@ static void main_loop(void) {
>         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);
> +   tpmcmd = tpmback_req_any();
>      while(tpmcmd) {
>         /* Handle the request */
>         if(tpmcmd->req_len) {
> @@ -183,7 +173,7 @@ static void main_loop(void) {
>            }
>            /* If not disabled, do the command */
>            else {
> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>                  error("tpm_handle_command() failed");
>                  create_error_response(tpmcmd, TPM_FAIL);
>               }
> @@ -194,7 +184,7 @@ static void main_loop(void) {
>         tpmback_resp(tpmcmd);
>   
>         /* Wait for the next request */
> -      tpmcmd = tpmback_req(domid, handle);
> +      tpmcmd = tpmback_req_any();
>   
>      }
Before the vtpm would shut down on its own when the host domain 
disconnects. This occurs because tpmback_req() returns NULL if the 
frontend disconnected. Using tpmback_req_any(), this is no longer the 
case which now means the user has to shut down the vtpm manually. How 
are you handling vtpm shutdown on your end?
>   
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM
  2012-11-27 18:08       ` Matthew Fioravante
@ 2012-11-27 18:36         ` Samuel Thibault
  2012-11-27 18:53         ` Daniel De Graaf
  1 sibling, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-27 18:36 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Daniel De Graaf, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
Matthew Fioravante, le Tue 27 Nov 2012 13:08:19 -0500, a écrit :
> How exactly does this work? Is it intended for HVM domains whos stubdom is
> connected to a vtpm? I've never tried to use vtpm with HVMs yet, so I'd be
> very surprised if it just works. Does it work for PVM domains?
> 
> I'm not terribly familiar with how grub in stubdom works.
Grub in stubdom is for bootloading PV guests only, not HVM. It's simply
the PV version of grub.
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM
  2012-11-27 18:08       ` Matthew Fioravante
  2012-11-27 18:36         ` Samuel Thibault
@ 2012-11-27 18:53         ` Daniel De Graaf
  1 sibling, 0 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 18:53 UTC (permalink / raw)
  To: Matthew Fioravante; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/27/2012 01:08 PM, Matthew Fioravante wrote:
> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>> This allows a domU with an arbitrary kernel and initrd to take advantage
>> of the static root of trust provided by a vTPM.
> Do you have any documentation updates for how to use it? They could be added to the vtpm documentation if thats the most appropriate location.
Not much documentation is really needed - you just launch a domain with the
pv-grub kernel and a vTPM, and this patch will write the measurements of the
kernel, initrd, and command line to PCRs 4/5, similar to trusted grub on real
hardware.
 
> How exactly does this work? Is it intended for HVM domains whos stubdom is connected to a vtpm? I've never tried to use vtpm with HVMs yet, so I'd be very surprised if it just works. Does it work for PVM domains?
> 
> I'm not terribly familiar with how grub in stubdom works.
This is PV only. The pv-grub stubdom is constructed similar to any other PV domain,
but the pv-grub kernel is specified instead of a normal Linux kernel. The pv-grub
kernel then loads a grub.conf from the guest's disk image and loads the Linux
kernel and initrd specified by the guest; this is more secure than pygrub which
does the loading in dom0, and more flexible than requiring the user to pick from
a list of pre-approved non-malicious kernels. If the pv-grub domain is created on
command by a measured domain builder/initrd combination, you can produce a static
chain of trust extending down to the hardware TPM without involving every UID 0
process in dom0.
[...]
>> +       cmd.pcr = be32(4); // PCR #4 for kernel
>> +       sha_compute(cmd.hash, dom->kernel_blob, dom->kernel_size);
>> +
>> +       tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
>> +
>> +       cmd.pcr = be32(5); // PCR #5 for cmdline
>> +       sha_compute(cmd.hash, cmdline, strlen(cmdline));
>> +       tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
>> +
>> +       cmd.pcr = be32(5); // PCR #5 for initrd
>> +       sha_compute(cmd.hash, dom->ramdisk_blob, dom->ramdisk_size);
>> +       tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen);
>> +
>> +       shutdown_tpmfront(tpm, 1);
>> +}
> Does this actually work? vtpm-stubdom will shut itself down when the frontend tpm disconnects. Is it really ok to connect and disconnect these devices at will?
Hmm, apparently this part may depend on the change from tpmback_req to
tpmback_req_any to avoid the shutdown on disconnect. That might not be
required (shutdown for reconfigure shouldn't start returning NULL for
requests) but I also haven't tested that it works without #4.
[...]
>> +++ b/stubdom/grub/sha1.c
[...]
> There also exists a sha1 routine in polarssl. You can just link in the polarssl sha1 object file without the entire library. This is what vtpm-stubdom and vtpmmgrdom do to get the crypto pieces they need. Checkout their makefiles for details.
> Is there any reason using polarssl would be sub-optimal?
No, I think rewriting this to use the polarssl functions would be useful; I
didn't notice the polarssl function was available when this patch was created.
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 18:19       ` Matthew Fioravante
@ 2012-11-27 19:02         ` Daniel De Graaf
  2012-11-27 19:48           ` Matthew Fioravante
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 19:02 UTC (permalink / raw)
  To: Matthew Fioravante; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/27/2012 01:19 PM, Matthew Fioravante wrote:
> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>> The vTPM protocol now contains a field allowing the locality of a
>> command to be specified; pass this to the TPM when processing a packet.
>> This also enables a single vTPM to provide multiple tpmback interfaces
>> so that several closely related domains can share a vTPM (for example, a
>> qemu device stubdom and its target domain).
>>
>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>> ---
>>   stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>   stubdom/vtpm/vtpm.c        | 16 +++---------
>>   2 files changed, 59 insertions(+), 18 deletions(-)
>>
>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>> index b84eff1..31ace1a 100644
>> --- a/stubdom/tpmemu-0.7.4.patch
>> +++ b/stubdom/tpmemu-0.7.4.patch
>> @@ -1,9 +1,60 @@
>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>> -@@ -249,7 +249,7 @@
>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>> +index 60bbb90..f8f7f0f 100644
>> +--- a/tpm/tpm_capability.c
>> ++++ b/tpm/tpm_capability.c
>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>> +                              UINT32 setValueSize, BOOL ownerAuth,
>> +                              BOOL deactivated, BOOL disabled)
>> + {
>> ++  if (tpmData.stany.flags.localityModifier != 8)
>> ++    return TPM_BAD_PARAMETER;
>> +   /* set the capability area with the specified data, on failure
>> +      deactivate the TPM */
>> +   switch (subCap) {
>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>> +index 288d1ce..9e1cfb4 100644
>> +--- a/tpm/tpm_cmd_handler.c
>> ++++ b/tpm/tpm_cmd_handler.c
>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>> +   tpm_extern_release();
>> + }
>> +
>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>> + {
>> +   TPM_REQUEST req;
>> +   TPM_RESPONSE rsp;
>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>> +   UINT32 len;
>> +   BOOL free_out;
>> +
>> +-  debug("tpm_handle_command()");
>> ++  debug("tpm_handle_command(%d)", locality);
>> ++  if (locality != -1)
>> ++    tpmData.stany.flags.localityModifier = locality;
>> +
>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>> +index eed749e..4c228bd 100644
>> +--- a/tpm/tpm_emulator.h
>> ++++ b/tpm/tpm_emulator.h
>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>> +  * its usage. In case of an error, all internally allocated memory
>> +  * is released and the the state of out and out_size is unspecified.
>> +  */
>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>> +
>> + #endif /* _TPM_EMULATOR_H_ */
>> +
>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>> +index aabe6c3..440a01b 100644
>> +--- a/tpm/tpm_emulator_extern.c
>> ++++ b/tpm/tpm_emulator_extern.c
>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>    #else /* TPM_NO_EXTERN */
>> -
>> +
>>    int (*tpm_extern_init)(void)                                      = NULL;
>>   -int (*tpm_extern_release)(void)                                   = NULL;
>>   +void (*tpm_extern_release)(void)                                   = NULL;
>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>> index c33e078..dcfc3b9 100644
>> --- a/stubdom/vtpm/vtpm.c
>> +++ b/stubdom/vtpm/vtpm.c
>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>     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");
>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>         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);
>> +   tpmcmd = tpmback_req_any();
>>      while(tpmcmd) {
>>         /* Handle the request */
>>         if(tpmcmd->req_len) {
>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>            }
>>            /* If not disabled, do the command */
>>            else {
>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>                  error("tpm_handle_command() failed");
>>                  create_error_response(tpmcmd, TPM_FAIL);
>>               }
>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>         tpmback_resp(tpmcmd);
>>           /* Wait for the next request */
>> -      tpmcmd = tpmback_req(domid, handle);
>> +      tpmcmd = tpmback_req_any();
>>        }
> Before the vtpm would shut down on its own when the host domain disconnects. This occurs because tpmback_req() returns NULL if the frontend disconnected. Using tpmback_req_any(), this is no longer the case which now means the user has to shut down the vtpm manually. How are you handling vtpm shutdown on your end?
When a domain shuts down, "xl destroy" is called on its paired vTPM (by some
scripting that may need to be incorporated into libxl). A graceful shutdown
is not really needed at this point, although it might be needed in the short
term if the save-state operation is not atomic - but a method of recovering
from this type of failure is needed for vTPMs anyway.
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 19:02         ` Daniel De Graaf
@ 2012-11-27 19:48           ` Matthew Fioravante
  2012-11-27 20:04             ` Samuel Thibault
                               ` (2 more replies)
  0 siblings, 3 replies; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-27 19:48 UTC (permalink / raw)
  To: Daniel De Graaf, Samuel Thibault
  Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 7741 bytes --]
On 11/27/2012 02:02 PM, Daniel De Graaf wrote:
> On 11/27/2012 01:19 PM, Matthew Fioravante wrote:
>> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>>> The vTPM protocol now contains a field allowing the locality of a
>>> command to be specified; pass this to the TPM when processing a packet.
>>> This also enables a single vTPM to provide multiple tpmback interfaces
>>> so that several closely related domains can share a vTPM (for example, a
>>> qemu device stubdom and its target domain).
>>>
>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>> ---
>>>    stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>>    stubdom/vtpm/vtpm.c        | 16 +++---------
>>>    2 files changed, 59 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>>> index b84eff1..31ace1a 100644
>>> --- a/stubdom/tpmemu-0.7.4.patch
>>> +++ b/stubdom/tpmemu-0.7.4.patch
>>> @@ -1,9 +1,60 @@
>>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>>> -@@ -249,7 +249,7 @@
>>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>>> +index 60bbb90..f8f7f0f 100644
>>> +--- a/tpm/tpm_capability.c
>>> ++++ b/tpm/tpm_capability.c
>>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>>> +                              UINT32 setValueSize, BOOL ownerAuth,
>>> +                              BOOL deactivated, BOOL disabled)
>>> + {
>>> ++  if (tpmData.stany.flags.localityModifier != 8)
>>> ++    return TPM_BAD_PARAMETER;
>>> +   /* set the capability area with the specified data, on failure
>>> +      deactivate the TPM */
>>> +   switch (subCap) {
>>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>>> +index 288d1ce..9e1cfb4 100644
>>> +--- a/tpm/tpm_cmd_handler.c
>>> ++++ b/tpm/tpm_cmd_handler.c
>>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>>> +   tpm_extern_release();
>>> + }
>>> +
>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>>> + {
>>> +   TPM_REQUEST req;
>>> +   TPM_RESPONSE rsp;
>>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>>> +   UINT32 len;
>>> +   BOOL free_out;
>>> +
>>> +-  debug("tpm_handle_command()");
>>> ++  debug("tpm_handle_command(%d)", locality);
>>> ++  if (locality != -1)
>>> ++    tpmData.stany.flags.localityModifier = locality;
>>> +
>>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>>> +index eed749e..4c228bd 100644
>>> +--- a/tpm/tpm_emulator.h
>>> ++++ b/tpm/tpm_emulator.h
>>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>>> +  * its usage. In case of an error, all internally allocated memory
>>> +  * is released and the the state of out and out_size is unspecified.
>>> +  */
>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>>> +
>>> + #endif /* _TPM_EMULATOR_H_ */
>>> +
>>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>>> +index aabe6c3..440a01b 100644
>>> +--- a/tpm/tpm_emulator_extern.c
>>> ++++ b/tpm/tpm_emulator_extern.c
>>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>>     #else /* TPM_NO_EXTERN */
>>> -
>>> +
>>>     int (*tpm_extern_init)(void)                                      = NULL;
>>>    -int (*tpm_extern_release)(void)                                   = NULL;
>>>    +void (*tpm_extern_release)(void)                                   = NULL;
>>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>>> index c33e078..dcfc3b9 100644
>>> --- a/stubdom/vtpm/vtpm.c
>>> +++ b/stubdom/vtpm/vtpm.c
>>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>>      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");
>>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>>          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);
>>> +   tpmcmd = tpmback_req_any();
>>>       while(tpmcmd) {
>>>          /* Handle the request */
>>>          if(tpmcmd->req_len) {
>>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>>             }
>>>             /* If not disabled, do the command */
>>>             else {
>>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>>                   error("tpm_handle_command() failed");
>>>                   create_error_response(tpmcmd, TPM_FAIL);
>>>                }
>>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>>          tpmback_resp(tpmcmd);
>>>            /* Wait for the next request */
>>> -      tpmcmd = tpmback_req(domid, handle);
>>> +      tpmcmd = tpmback_req_any();
>>>         }
>> Before the vtpm would shut down on its own when the host domain disconnects. This occurs because tpmback_req() returns NULL if the frontend disconnected. Using tpmback_req_any(), this is no longer the case which now means the user has to shut down the vtpm manually. How are you handling vtpm shutdown on your end?
> When a domain shuts down, "xl destroy" is called on its paired vTPM (by some
> scripting that may need to be incorporated into libxl). A graceful shutdown
> is not really needed at this point, although it might be needed in the short
> term if the save-state operation is not atomic - but a method of recovering
> from this type of failure is needed for vTPMs anyway.
This is kind of a difficult problem. The save state operation is not by 
any means atomic and it is very possible that the guest shuts down and 
xl destroy is called before the save operation completes. This is 
especially true if the guest is an embedded or even a mini-os domain 
using tpmfront that shuts down very quickly. Its the reason why now the 
vtpm shuts itself down after the guest disconnects.
What is really needed is a way to do an xl shutdown on mini-os domains 
to let vtpm-stubdom shutdown correctly. From what I understand there is 
not yet any support for this in mini-os. How tricky would it be to add 
that? Samuel any ideas?
If thats not possible, another potential hack could be writing a key in 
xenstore to trigger the shutdown or setting up some other kind of event 
channel mechanism between the vtpm domain and libxl.
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 19:48           ` Matthew Fioravante
@ 2012-11-27 20:04             ` Samuel Thibault
  2012-11-27 20:11             ` Daniel De Graaf
  2012-11-28 21:58             ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Samuel Thibault
  2 siblings, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-27 20:04 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Daniel De Graaf, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
Matthew Fioravante, le Tue 27 Nov 2012 14:48:29 -0500, a écrit :
> What is really needed is a way to do an xl shutdown on mini-os domains to
> let vtpm-stubdom shutdown correctly. From what I understand there is not yet
> any support for this in mini-os. How tricky would it be to add that? Samuel
> any ideas?
You mean add support to mini-os for clean shutdown?  That's quite
trivial, IIRC it's a matter of reacting to a xenstore write.
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 19:48           ` Matthew Fioravante
  2012-11-27 20:04             ` Samuel Thibault
@ 2012-11-27 20:11             ` Daniel De Graaf
  2012-11-27 20:21               ` Matthew Fioravante
  2012-11-28 21:58             ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Samuel Thibault
  2 siblings, 1 reply; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 20:11 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Samuel Thibault, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/27/2012 02:48 PM, Matthew Fioravante wrote:
> On 11/27/2012 02:02 PM, Daniel De Graaf wrote:
>> On 11/27/2012 01:19 PM, Matthew Fioravante wrote:
>>> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>>>> The vTPM protocol now contains a field allowing the locality of a
>>>> command to be specified; pass this to the TPM when processing a packet.
>>>> This also enables a single vTPM to provide multiple tpmback interfaces
>>>> so that several closely related domains can share a vTPM (for example, a
>>>> qemu device stubdom and its target domain).
>>>>
>>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>>> ---
>>>>    stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>>>    stubdom/vtpm/vtpm.c        | 16 +++---------
>>>>    2 files changed, 59 insertions(+), 18 deletions(-)
>>>>
>>>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>>>> index b84eff1..31ace1a 100644
>>>> --- a/stubdom/tpmemu-0.7.4.patch
>>>> +++ b/stubdom/tpmemu-0.7.4.patch
>>>> @@ -1,9 +1,60 @@
>>>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>>>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>>>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>>>> -@@ -249,7 +249,7 @@
>>>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>>>> +index 60bbb90..f8f7f0f 100644
>>>> +--- a/tpm/tpm_capability.c
>>>> ++++ b/tpm/tpm_capability.c
>>>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>>>> +                              UINT32 setValueSize, BOOL ownerAuth,
>>>> +                              BOOL deactivated, BOOL disabled)
>>>> + {
>>>> ++  if (tpmData.stany.flags.localityModifier != 8)
>>>> ++    return TPM_BAD_PARAMETER;
>>>> +   /* set the capability area with the specified data, on failure
>>>> +      deactivate the TPM */
>>>> +   switch (subCap) {
>>>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>>>> +index 288d1ce..9e1cfb4 100644
>>>> +--- a/tpm/tpm_cmd_handler.c
>>>> ++++ b/tpm/tpm_cmd_handler.c
>>>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>>>> +   tpm_extern_release();
>>>> + }
>>>> +
>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>>>> + {
>>>> +   TPM_REQUEST req;
>>>> +   TPM_RESPONSE rsp;
>>>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>>>> +   UINT32 len;
>>>> +   BOOL free_out;
>>>> +
>>>> +-  debug("tpm_handle_command()");
>>>> ++  debug("tpm_handle_command(%d)", locality);
>>>> ++  if (locality != -1)
>>>> ++    tpmData.stany.flags.localityModifier = locality;
>>>> +
>>>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>>>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>>>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>>>> +index eed749e..4c228bd 100644
>>>> +--- a/tpm/tpm_emulator.h
>>>> ++++ b/tpm/tpm_emulator.h
>>>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>>>> +  * its usage. In case of an error, all internally allocated memory
>>>> +  * is released and the the state of out and out_size is unspecified.
>>>> +  */
>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>>>> +
>>>> + #endif /* _TPM_EMULATOR_H_ */
>>>> +
>>>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>>>> +index aabe6c3..440a01b 100644
>>>> +--- a/tpm/tpm_emulator_extern.c
>>>> ++++ b/tpm/tpm_emulator_extern.c
>>>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>>>     #else /* TPM_NO_EXTERN */
>>>> -
>>>> +
>>>>     int (*tpm_extern_init)(void)                                      = NULL;
>>>>    -int (*tpm_extern_release)(void)                                   = NULL;
>>>>    +void (*tpm_extern_release)(void)                                   = NULL;
>>>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>>>> index c33e078..dcfc3b9 100644
>>>> --- a/stubdom/vtpm/vtpm.c
>>>> +++ b/stubdom/vtpm/vtpm.c
>>>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>>>      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");
>>>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>>>          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);
>>>> +   tpmcmd = tpmback_req_any();
>>>>       while(tpmcmd) {
>>>>          /* Handle the request */
>>>>          if(tpmcmd->req_len) {
>>>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>>>             }
>>>>             /* If not disabled, do the command */
>>>>             else {
>>>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>>>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>>>                   error("tpm_handle_command() failed");
>>>>                   create_error_response(tpmcmd, TPM_FAIL);
>>>>                }
>>>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>>>          tpmback_resp(tpmcmd);
>>>>            /* Wait for the next request */
>>>> -      tpmcmd = tpmback_req(domid, handle);
>>>> +      tpmcmd = tpmback_req_any();
>>>>         }
>>> Before the vtpm would shut down on its own when the host domain disconnects. This occurs because tpmback_req() returns NULL if the frontend disconnected. Using tpmback_req_any(), this is no longer the case which now means the user has to shut down the vtpm manually. How are you handling vtpm shutdown on your end?
>> When a domain shuts down, "xl destroy" is called on its paired vTPM (by some
>> scripting that may need to be incorporated into libxl). A graceful shutdown
>> is not really needed at this point, although it might be needed in the short
>> term if the save-state operation is not atomic - but a method of recovering
>> from this type of failure is needed for vTPMs anyway.
> This is kind of a difficult problem. The save state operation is not by any means atomic and it is very possible that the guest shuts down and xl destroy is called before the save operation completes. This is especially true if the guest is an embedded or even a mini-os domain using tpmfront that shuts down very quickly. Its the reason why now the vtpm shuts itself down after the guest disconnects.
> 
> What is really needed is a way to do an xl shutdown on mini-os domains to let vtpm-stubdom shutdown correctly. From what I understand there is not yet any support for this in mini-os. How tricky would it be to add that? Samuel any ideas?
> 
> If thats not possible, another potential hack could be writing a key in xenstore to trigger the shutdown or setting up some other kind of event channel mechanism between the vtpm domain and libxl.
> 
I have approached this problem from the opposite direction, while looking at
adding protection from vTPM state rollback. The method that I am currently
considering is to have two "slots" in the vTPM disk image - one active and
and one inactive. The save process would then consist of writing a new save
state to the inactive slot, ensuring it has been committed to disk, and then
requesting the TPM Manager atomically update the state encryption key to the
new value. When loading, the key obtained from the TPM manager will only be
able to decrypt one of the two state images; the successful one is the active
image. Since the vTPM's saved state is not expected to be very large, this 
doesn't waste a significant amount of disk space.
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 20:11             ` Daniel De Graaf
@ 2012-11-27 20:21               ` Matthew Fioravante
  2012-11-27 20:30                 ` Daniel De Graaf
  0 siblings, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-27 20:21 UTC (permalink / raw)
  To: Daniel De Graaf
  Cc: Samuel Thibault, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 9164 bytes --]
On 11/27/2012 03:11 PM, Daniel De Graaf wrote:
> On 11/27/2012 02:48 PM, Matthew Fioravante wrote:
>> On 11/27/2012 02:02 PM, Daniel De Graaf wrote:
>>> On 11/27/2012 01:19 PM, Matthew Fioravante wrote:
>>>> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>>>>> The vTPM protocol now contains a field allowing the locality of a
>>>>> command to be specified; pass this to the TPM when processing a packet.
>>>>> This also enables a single vTPM to provide multiple tpmback interfaces
>>>>> so that several closely related domains can share a vTPM (for example, a
>>>>> qemu device stubdom and its target domain).
>>>>>
>>>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>>>> ---
>>>>>     stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>>>>     stubdom/vtpm/vtpm.c        | 16 +++---------
>>>>>     2 files changed, 59 insertions(+), 18 deletions(-)
>>>>>
>>>>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>>>>> index b84eff1..31ace1a 100644
>>>>> --- a/stubdom/tpmemu-0.7.4.patch
>>>>> +++ b/stubdom/tpmemu-0.7.4.patch
>>>>> @@ -1,9 +1,60 @@
>>>>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>>>>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>>>>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>>>>> -@@ -249,7 +249,7 @@
>>>>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>>>>> +index 60bbb90..f8f7f0f 100644
>>>>> +--- a/tpm/tpm_capability.c
>>>>> ++++ b/tpm/tpm_capability.c
>>>>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>>>>> +                              UINT32 setValueSize, BOOL ownerAuth,
>>>>> +                              BOOL deactivated, BOOL disabled)
>>>>> + {
>>>>> ++  if (tpmData.stany.flags.localityModifier != 8)
>>>>> ++    return TPM_BAD_PARAMETER;
>>>>> +   /* set the capability area with the specified data, on failure
>>>>> +      deactivate the TPM */
>>>>> +   switch (subCap) {
>>>>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>>>>> +index 288d1ce..9e1cfb4 100644
>>>>> +--- a/tpm/tpm_cmd_handler.c
>>>>> ++++ b/tpm/tpm_cmd_handler.c
>>>>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>>>>> +   tpm_extern_release();
>>>>> + }
>>>>> +
>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>>>>> + {
>>>>> +   TPM_REQUEST req;
>>>>> +   TPM_RESPONSE rsp;
>>>>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>>>>> +   UINT32 len;
>>>>> +   BOOL free_out;
>>>>> +
>>>>> +-  debug("tpm_handle_command()");
>>>>> ++  debug("tpm_handle_command(%d)", locality);
>>>>> ++  if (locality != -1)
>>>>> ++    tpmData.stany.flags.localityModifier = locality;
>>>>> +
>>>>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>>>>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>>>>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>>>>> +index eed749e..4c228bd 100644
>>>>> +--- a/tpm/tpm_emulator.h
>>>>> ++++ b/tpm/tpm_emulator.h
>>>>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>>>>> +  * its usage. In case of an error, all internally allocated memory
>>>>> +  * is released and the the state of out and out_size is unspecified.
>>>>> +  */
>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>>>>> +
>>>>> + #endif /* _TPM_EMULATOR_H_ */
>>>>> +
>>>>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>>>>> +index aabe6c3..440a01b 100644
>>>>> +--- a/tpm/tpm_emulator_extern.c
>>>>> ++++ b/tpm/tpm_emulator_extern.c
>>>>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>>>>      #else /* TPM_NO_EXTERN */
>>>>> -
>>>>> +
>>>>>      int (*tpm_extern_init)(void)                                      = NULL;
>>>>>     -int (*tpm_extern_release)(void)                                   = NULL;
>>>>>     +void (*tpm_extern_release)(void)                                   = NULL;
>>>>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>>>>> index c33e078..dcfc3b9 100644
>>>>> --- a/stubdom/vtpm/vtpm.c
>>>>> +++ b/stubdom/vtpm/vtpm.c
>>>>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>>>>       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");
>>>>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>>>>           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);
>>>>> +   tpmcmd = tpmback_req_any();
>>>>>        while(tpmcmd) {
>>>>>           /* Handle the request */
>>>>>           if(tpmcmd->req_len) {
>>>>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>>>>              }
>>>>>              /* If not disabled, do the command */
>>>>>              else {
>>>>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>>>>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>>>>                    error("tpm_handle_command() failed");
>>>>>                    create_error_response(tpmcmd, TPM_FAIL);
>>>>>                 }
>>>>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>>>>           tpmback_resp(tpmcmd);
>>>>>             /* Wait for the next request */
>>>>> -      tpmcmd = tpmback_req(domid, handle);
>>>>> +      tpmcmd = tpmback_req_any();
>>>>>          }
>>>> Before the vtpm would shut down on its own when the host domain disconnects. This occurs because tpmback_req() returns NULL if the frontend disconnected. Using tpmback_req_any(), this is no longer the case which now means the user has to shut down the vtpm manually. How are you handling vtpm shutdown on your end?
>>> When a domain shuts down, "xl destroy" is called on its paired vTPM (by some
>>> scripting that may need to be incorporated into libxl). A graceful shutdown
>>> is not really needed at this point, although it might be needed in the short
>>> term if the save-state operation is not atomic - but a method of recovering
>>> from this type of failure is needed for vTPMs anyway.
>> This is kind of a difficult problem. The save state operation is not by any means atomic and it is very possible that the guest shuts down and xl destroy is called before the save operation completes. This is especially true if the guest is an embedded or even a mini-os domain using tpmfront that shuts down very quickly. Its the reason why now the vtpm shuts itself down after the guest disconnects.
>>
>> What is really needed is a way to do an xl shutdown on mini-os domains to let vtpm-stubdom shutdown correctly. From what I understand there is not yet any support for this in mini-os. How tricky would it be to add that? Samuel any ideas?
>>
>> If thats not possible, another potential hack could be writing a key in xenstore to trigger the shutdown or setting up some other kind of event channel mechanism between the vtpm domain and libxl.
>>
> I have approached this problem from the opposite direction, while looking at
> adding protection from vTPM state rollback. The method that I am currently
> considering is to have two "slots" in the vTPM disk image - one active and
> and one inactive. The save process would then consist of writing a new save
> state to the inactive slot, ensuring it has been committed to disk, and then
> requesting the TPM Manager atomically update the state encryption key to the
> new value. When loading, the key obtained from the TPM manager will only be
> able to decrypt one of the two state images; the successful one is the active
> image. Since the vTPM's saved state is not expected to be very large, this
> doesn't waste a significant amount of disk space.
>
I like that idea in general, but it still doesn't solve the shutdown 
race condition. You might not get a corrupted disk but you can still get 
inadvertently rolled back. Adding a xenstore watch as samuel suggested 
and doing a clean shutdown would be ideal.
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 20:21               ` Matthew Fioravante
@ 2012-11-27 20:30                 ` Daniel De Graaf
  2012-11-27 20:34                   ` Matthew Fioravante
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 20:30 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Samuel Thibault, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/27/2012 03:21 PM, Matthew Fioravante wrote:
> On 11/27/2012 03:11 PM, Daniel De Graaf wrote:
>> On 11/27/2012 02:48 PM, Matthew Fioravante wrote:
>>> On 11/27/2012 02:02 PM, Daniel De Graaf wrote:
>>>> On 11/27/2012 01:19 PM, Matthew Fioravante wrote:
>>>>> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>>>>>> The vTPM protocol now contains a field allowing the locality of a
>>>>>> command to be specified; pass this to the TPM when processing a packet.
>>>>>> This also enables a single vTPM to provide multiple tpmback interfaces
>>>>>> so that several closely related domains can share a vTPM (for example, a
>>>>>> qemu device stubdom and its target domain).
>>>>>>
>>>>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>>>>> ---
>>>>>>     stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>>>>>     stubdom/vtpm/vtpm.c        | 16 +++---------
>>>>>>     2 files changed, 59 insertions(+), 18 deletions(-)
>>>>>>
>>>>>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>>>>>> index b84eff1..31ace1a 100644
>>>>>> --- a/stubdom/tpmemu-0.7.4.patch
>>>>>> +++ b/stubdom/tpmemu-0.7.4.patch
>>>>>> @@ -1,9 +1,60 @@
>>>>>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>>>>>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>>>>>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>>>>>> -@@ -249,7 +249,7 @@
>>>>>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>>>>>> +index 60bbb90..f8f7f0f 100644
>>>>>> +--- a/tpm/tpm_capability.c
>>>>>> ++++ b/tpm/tpm_capability.c
>>>>>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>>>>>> +                              UINT32 setValueSize, BOOL ownerAuth,
>>>>>> +                              BOOL deactivated, BOOL disabled)
>>>>>> + {
>>>>>> ++  if (tpmData.stany.flags.localityModifier != 8)
>>>>>> ++    return TPM_BAD_PARAMETER;
>>>>>> +   /* set the capability area with the specified data, on failure
>>>>>> +      deactivate the TPM */
>>>>>> +   switch (subCap) {
>>>>>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>>>>>> +index 288d1ce..9e1cfb4 100644
>>>>>> +--- a/tpm/tpm_cmd_handler.c
>>>>>> ++++ b/tpm/tpm_cmd_handler.c
>>>>>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>>>>>> +   tpm_extern_release();
>>>>>> + }
>>>>>> +
>>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>>>>>> + {
>>>>>> +   TPM_REQUEST req;
>>>>>> +   TPM_RESPONSE rsp;
>>>>>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>>>>>> +   UINT32 len;
>>>>>> +   BOOL free_out;
>>>>>> +
>>>>>> +-  debug("tpm_handle_command()");
>>>>>> ++  debug("tpm_handle_command(%d)", locality);
>>>>>> ++  if (locality != -1)
>>>>>> ++    tpmData.stany.flags.localityModifier = locality;
>>>>>> +
>>>>>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>>>>>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>>>>>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>>>>>> +index eed749e..4c228bd 100644
>>>>>> +--- a/tpm/tpm_emulator.h
>>>>>> ++++ b/tpm/tpm_emulator.h
>>>>>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>>>>>> +  * its usage. In case of an error, all internally allocated memory
>>>>>> +  * is released and the the state of out and out_size is unspecified.
>>>>>> +  */
>>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>>>>>> +
>>>>>> + #endif /* _TPM_EMULATOR_H_ */
>>>>>> +
>>>>>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>>>>>> +index aabe6c3..440a01b 100644
>>>>>> +--- a/tpm/tpm_emulator_extern.c
>>>>>> ++++ b/tpm/tpm_emulator_extern.c
>>>>>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>>>>>      #else /* TPM_NO_EXTERN */
>>>>>> -
>>>>>> +
>>>>>>      int (*tpm_extern_init)(void)                                      = NULL;
>>>>>>     -int (*tpm_extern_release)(void)                                   = NULL;
>>>>>>     +void (*tpm_extern_release)(void)                                   = NULL;
>>>>>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>>>>>> index c33e078..dcfc3b9 100644
>>>>>> --- a/stubdom/vtpm/vtpm.c
>>>>>> +++ b/stubdom/vtpm/vtpm.c
>>>>>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>>>>>       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");
>>>>>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>>>>>           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);
>>>>>> +   tpmcmd = tpmback_req_any();
>>>>>>        while(tpmcmd) {
>>>>>>           /* Handle the request */
>>>>>>           if(tpmcmd->req_len) {
>>>>>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>>>>>              }
>>>>>>              /* If not disabled, do the command */
>>>>>>              else {
>>>>>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>>>>>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>>>>>                    error("tpm_handle_command() failed");
>>>>>>                    create_error_response(tpmcmd, TPM_FAIL);
>>>>>>                 }
>>>>>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>>>>>           tpmback_resp(tpmcmd);
>>>>>>             /* Wait for the next request */
>>>>>> -      tpmcmd = tpmback_req(domid, handle);
>>>>>> +      tpmcmd = tpmback_req_any();
>>>>>>          }
>>>>> Before the vtpm would shut down on its own when the host domain disconnects. This occurs because tpmback_req() returns NULL if the frontend disconnected. Using tpmback_req_any(), this is no longer the case which now means the user has to shut down the vtpm manually. How are you handling vtpm shutdown on your end?
>>>> When a domain shuts down, "xl destroy" is called on its paired vTPM (by some
>>>> scripting that may need to be incorporated into libxl). A graceful shutdown
>>>> is not really needed at this point, although it might be needed in the short
>>>> term if the save-state operation is not atomic - but a method of recovering
>>>> from this type of failure is needed for vTPMs anyway.
>>> This is kind of a difficult problem. The save state operation is not by any means atomic and it is very possible that the guest shuts down and xl destroy is called before the save operation completes. This is especially true if the guest is an embedded or even a mini-os domain using tpmfront that shuts down very quickly. Its the reason why now the vtpm shuts itself down after the guest disconnects.
>>>
>>> What is really needed is a way to do an xl shutdown on mini-os domains to let vtpm-stubdom shutdown correctly. From what I understand there is not yet any support for this in mini-os. How tricky would it be to add that? Samuel any ideas?
>>>
>>> If thats not possible, another potential hack could be writing a key in xenstore to trigger the shutdown or setting up some other kind of event channel mechanism between the vtpm domain and libxl.
>>>
>> I have approached this problem from the opposite direction, while looking at
>> adding protection from vTPM state rollback. The method that I am currently
>> considering is to have two "slots" in the vTPM disk image - one active and
>> and one inactive. The save process would then consist of writing a new save
>> state to the inactive slot, ensuring it has been committed to disk, and then
>> requesting the TPM Manager atomically update the state encryption key to the
>> new value. When loading, the key obtained from the TPM manager will only be
>> able to decrypt one of the two state images; the successful one is the active
>> image. Since the vTPM's saved state is not expected to be very large, this
>> doesn't waste a significant amount of disk space.
>>
> I like that idea in general, but it still doesn't solve the shutdown race condition. You might not get a corrupted disk but you can still get inadvertently rolled back. Adding a xenstore watch as samuel suggested and doing a clean shutdown would be ideal.
 
If you run the save before you send back the TPM response, you won't have any
races - if a domain dies without getting a TPM response, the it's valid for
the command to not have completed. The TPM emulator does execute the save
prior to returning the result packet, so this race is already avoided.
That's not to say that handling shutdowns properly is useless, of course; other
minios domains may need it, and a graceful shutdown is easier to clean up after
if not all peers of the vTPM are shutting down at the same time.
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 20:30                 ` Daniel De Graaf
@ 2012-11-27 20:34                   ` Matthew Fioravante
  2012-11-27 20:40                     ` Daniel De Graaf
  0 siblings, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-27 20:34 UTC (permalink / raw)
  To: Daniel De Graaf
  Cc: Samuel Thibault, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 10384 bytes --]
On 11/27/2012 03:30 PM, Daniel De Graaf wrote:
> On 11/27/2012 03:21 PM, Matthew Fioravante wrote:
>> On 11/27/2012 03:11 PM, Daniel De Graaf wrote:
>>> On 11/27/2012 02:48 PM, Matthew Fioravante wrote:
>>>> On 11/27/2012 02:02 PM, Daniel De Graaf wrote:
>>>>> On 11/27/2012 01:19 PM, Matthew Fioravante wrote:
>>>>>> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>>>>>>> The vTPM protocol now contains a field allowing the locality of a
>>>>>>> command to be specified; pass this to the TPM when processing a packet.
>>>>>>> This also enables a single vTPM to provide multiple tpmback interfaces
>>>>>>> so that several closely related domains can share a vTPM (for example, a
>>>>>>> qemu device stubdom and its target domain).
>>>>>>>
>>>>>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>>>>>> ---
>>>>>>>      stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>>>>>>      stubdom/vtpm/vtpm.c        | 16 +++---------
>>>>>>>      2 files changed, 59 insertions(+), 18 deletions(-)
>>>>>>>
>>>>>>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>>>>>>> index b84eff1..31ace1a 100644
>>>>>>> --- a/stubdom/tpmemu-0.7.4.patch
>>>>>>> +++ b/stubdom/tpmemu-0.7.4.patch
>>>>>>> @@ -1,9 +1,60 @@
>>>>>>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>>>>>>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>>>>>>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>>>>>>> -@@ -249,7 +249,7 @@
>>>>>>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>>>>>>> +index 60bbb90..f8f7f0f 100644
>>>>>>> +--- a/tpm/tpm_capability.c
>>>>>>> ++++ b/tpm/tpm_capability.c
>>>>>>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>>>>>>> +                              UINT32 setValueSize, BOOL ownerAuth,
>>>>>>> +                              BOOL deactivated, BOOL disabled)
>>>>>>> + {
>>>>>>> ++  if (tpmData.stany.flags.localityModifier != 8)
>>>>>>> ++    return TPM_BAD_PARAMETER;
>>>>>>> +   /* set the capability area with the specified data, on failure
>>>>>>> +      deactivate the TPM */
>>>>>>> +   switch (subCap) {
>>>>>>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>>>>>>> +index 288d1ce..9e1cfb4 100644
>>>>>>> +--- a/tpm/tpm_cmd_handler.c
>>>>>>> ++++ b/tpm/tpm_cmd_handler.c
>>>>>>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>>>>>>> +   tpm_extern_release();
>>>>>>> + }
>>>>>>> +
>>>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>>>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>>>>>>> + {
>>>>>>> +   TPM_REQUEST req;
>>>>>>> +   TPM_RESPONSE rsp;
>>>>>>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>>>>>>> +   UINT32 len;
>>>>>>> +   BOOL free_out;
>>>>>>> +
>>>>>>> +-  debug("tpm_handle_command()");
>>>>>>> ++  debug("tpm_handle_command(%d)", locality);
>>>>>>> ++  if (locality != -1)
>>>>>>> ++    tpmData.stany.flags.localityModifier = locality;
>>>>>>> +
>>>>>>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>>>>>>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>>>>>>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>>>>>>> +index eed749e..4c228bd 100644
>>>>>>> +--- a/tpm/tpm_emulator.h
>>>>>>> ++++ b/tpm/tpm_emulator.h
>>>>>>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>>>>>>> +  * its usage. In case of an error, all internally allocated memory
>>>>>>> +  * is released and the the state of out and out_size is unspecified.
>>>>>>> +  */
>>>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>>>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>>>>>>> +
>>>>>>> + #endif /* _TPM_EMULATOR_H_ */
>>>>>>> +
>>>>>>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>>>>>>> +index aabe6c3..440a01b 100644
>>>>>>> +--- a/tpm/tpm_emulator_extern.c
>>>>>>> ++++ b/tpm/tpm_emulator_extern.c
>>>>>>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>>>>>>       #else /* TPM_NO_EXTERN */
>>>>>>> -
>>>>>>> +
>>>>>>>       int (*tpm_extern_init)(void)                                      = NULL;
>>>>>>>      -int (*tpm_extern_release)(void)                                   = NULL;
>>>>>>>      +void (*tpm_extern_release)(void)                                   = NULL;
>>>>>>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>>>>>>> index c33e078..dcfc3b9 100644
>>>>>>> --- a/stubdom/vtpm/vtpm.c
>>>>>>> +++ b/stubdom/vtpm/vtpm.c
>>>>>>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>>>>>>        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");
>>>>>>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>>>>>>            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);
>>>>>>> +   tpmcmd = tpmback_req_any();
>>>>>>>         while(tpmcmd) {
>>>>>>>            /* Handle the request */
>>>>>>>            if(tpmcmd->req_len) {
>>>>>>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>>>>>>               }
>>>>>>>               /* If not disabled, do the command */
>>>>>>>               else {
>>>>>>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>>>>>>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>>>>>>                     error("tpm_handle_command() failed");
>>>>>>>                     create_error_response(tpmcmd, TPM_FAIL);
>>>>>>>                  }
>>>>>>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>>>>>>            tpmback_resp(tpmcmd);
>>>>>>>              /* Wait for the next request */
>>>>>>> -      tpmcmd = tpmback_req(domid, handle);
>>>>>>> +      tpmcmd = tpmback_req_any();
>>>>>>>           }
>>>>>> Before the vtpm would shut down on its own when the host domain disconnects. This occurs because tpmback_req() returns NULL if the frontend disconnected. Using tpmback_req_any(), this is no longer the case which now means the user has to shut down the vtpm manually. How are you handling vtpm shutdown on your end?
>>>>> When a domain shuts down, "xl destroy" is called on its paired vTPM (by some
>>>>> scripting that may need to be incorporated into libxl). A graceful shutdown
>>>>> is not really needed at this point, although it might be needed in the short
>>>>> term if the save-state operation is not atomic - but a method of recovering
>>>>> from this type of failure is needed for vTPMs anyway.
>>>> This is kind of a difficult problem. The save state operation is not by any means atomic and it is very possible that the guest shuts down and xl destroy is called before the save operation completes. This is especially true if the guest is an embedded or even a mini-os domain using tpmfront that shuts down very quickly. Its the reason why now the vtpm shuts itself down after the guest disconnects.
>>>>
>>>> What is really needed is a way to do an xl shutdown on mini-os domains to let vtpm-stubdom shutdown correctly. From what I understand there is not yet any support for this in mini-os. How tricky would it be to add that? Samuel any ideas?
>>>>
>>>> If thats not possible, another potential hack could be writing a key in xenstore to trigger the shutdown or setting up some other kind of event channel mechanism between the vtpm domain and libxl.
>>>>
>>> I have approached this problem from the opposite direction, while looking at
>>> adding protection from vTPM state rollback. The method that I am currently
>>> considering is to have two "slots" in the vTPM disk image - one active and
>>> and one inactive. The save process would then consist of writing a new save
>>> state to the inactive slot, ensuring it has been committed to disk, and then
>>> requesting the TPM Manager atomically update the state encryption key to the
>>> new value. When loading, the key obtained from the TPM manager will only be
>>> able to decrypt one of the two state images; the successful one is the active
>>> image. Since the vTPM's saved state is not expected to be very large, this
>>> doesn't waste a significant amount of disk space.
>>>
>> I like that idea in general, but it still doesn't solve the shutdown race condition. You might not get a corrupted disk but you can still get inadvertently rolled back. Adding a xenstore watch as samuel suggested and doing a clean shutdown would be ideal.
>   
> If you run the save before you send back the TPM response, you won't have any
> races - if a domain dies without getting a TPM response, the it's valid for
> the command to not have completed. The TPM emulator does execute the save
> prior to returning the result packet, so this race is already avoided.
>
> That's not to say that handling shutdowns properly is useless, of course; other
> minios domains may need it, and a graceful shutdown is easier to clean up after
> if not all peers of the vTPM are shutting down at the same time.
Ok I follow you now. Do you already have patches to do the disk 
mirroring and destroy the vtpm from libxl? I think we will want to 
include this so these new features don't break the automatic vtpm 
shutdown model already in place.
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 20:34                   ` Matthew Fioravante
@ 2012-11-27 20:40                     ` Daniel De Graaf
  2012-11-27 22:16                       ` [PATCH] stubdom/vtpm: make state save operation atomic Daniel De Graaf
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 20:40 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Samuel Thibault, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/27/2012 03:34 PM, Matthew Fioravante wrote:
> On 11/27/2012 03:30 PM, Daniel De Graaf wrote:
>> On 11/27/2012 03:21 PM, Matthew Fioravante wrote:
>>> On 11/27/2012 03:11 PM, Daniel De Graaf wrote:
>>>> On 11/27/2012 02:48 PM, Matthew Fioravante wrote:
>>>>> On 11/27/2012 02:02 PM, Daniel De Graaf wrote:
>>>>>> On 11/27/2012 01:19 PM, Matthew Fioravante wrote:
>>>>>>> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>>>>>>>> The vTPM protocol now contains a field allowing the locality of a
>>>>>>>> command to be specified; pass this to the TPM when processing a packet.
>>>>>>>> This also enables a single vTPM to provide multiple tpmback interfaces
>>>>>>>> so that several closely related domains can share a vTPM (for example, a
>>>>>>>> qemu device stubdom and its target domain).
>>>>>>>>
>>>>>>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>>>>>>> ---
>>>>>>>>      stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>>>>>>>      stubdom/vtpm/vtpm.c        | 16 +++---------
>>>>>>>>      2 files changed, 59 insertions(+), 18 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>>>>>>>> index b84eff1..31ace1a 100644
>>>>>>>> --- a/stubdom/tpmemu-0.7.4.patch
>>>>>>>> +++ b/stubdom/tpmemu-0.7.4.patch
>>>>>>>> @@ -1,9 +1,60 @@
>>>>>>>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>>>>>>>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>>>>>>>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>>>>>>>> -@@ -249,7 +249,7 @@
>>>>>>>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>>>>>>>> +index 60bbb90..f8f7f0f 100644
>>>>>>>> +--- a/tpm/tpm_capability.c
>>>>>>>> ++++ b/tpm/tpm_capability.c
>>>>>>>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>>>>>>>> +                              UINT32 setValueSize, BOOL ownerAuth,
>>>>>>>> +                              BOOL deactivated, BOOL disabled)
>>>>>>>> + {
>>>>>>>> ++  if (tpmData.stany.flags.localityModifier != 8)
>>>>>>>> ++    return TPM_BAD_PARAMETER;
>>>>>>>> +   /* set the capability area with the specified data, on failure
>>>>>>>> +      deactivate the TPM */
>>>>>>>> +   switch (subCap) {
>>>>>>>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>>>>>>>> +index 288d1ce..9e1cfb4 100644
>>>>>>>> +--- a/tpm/tpm_cmd_handler.c
>>>>>>>> ++++ b/tpm/tpm_cmd_handler.c
>>>>>>>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>>>>>>>> +   tpm_extern_release();
>>>>>>>> + }
>>>>>>>> +
>>>>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>>>>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>>>>>>>> + {
>>>>>>>> +   TPM_REQUEST req;
>>>>>>>> +   TPM_RESPONSE rsp;
>>>>>>>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>>>>>>>> +   UINT32 len;
>>>>>>>> +   BOOL free_out;
>>>>>>>> +
>>>>>>>> +-  debug("tpm_handle_command()");
>>>>>>>> ++  debug("tpm_handle_command(%d)", locality);
>>>>>>>> ++  if (locality != -1)
>>>>>>>> ++    tpmData.stany.flags.localityModifier = locality;
>>>>>>>> +
>>>>>>>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>>>>>>>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>>>>>>>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>>>>>>>> +index eed749e..4c228bd 100644
>>>>>>>> +--- a/tpm/tpm_emulator.h
>>>>>>>> ++++ b/tpm/tpm_emulator.h
>>>>>>>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>>>>>>>> +  * its usage. In case of an error, all internally allocated memory
>>>>>>>> +  * is released and the the state of out and out_size is unspecified.
>>>>>>>> +  */
>>>>>>>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>>>>>>>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>>>>>>>> +
>>>>>>>> + #endif /* _TPM_EMULATOR_H_ */
>>>>>>>> +
>>>>>>>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>>>>>>>> +index aabe6c3..440a01b 100644
>>>>>>>> +--- a/tpm/tpm_emulator_extern.c
>>>>>>>> ++++ b/tpm/tpm_emulator_extern.c
>>>>>>>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>>>>>>>       #else /* TPM_NO_EXTERN */
>>>>>>>> -
>>>>>>>> +
>>>>>>>>       int (*tpm_extern_init)(void)                                      = NULL;
>>>>>>>>      -int (*tpm_extern_release)(void)                                   = NULL;
>>>>>>>>      +void (*tpm_extern_release)(void)                                   = NULL;
>>>>>>>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>>>>>>>> index c33e078..dcfc3b9 100644
>>>>>>>> --- a/stubdom/vtpm/vtpm.c
>>>>>>>> +++ b/stubdom/vtpm/vtpm.c
>>>>>>>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>>>>>>>        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");
>>>>>>>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>>>>>>>            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);
>>>>>>>> +   tpmcmd = tpmback_req_any();
>>>>>>>>         while(tpmcmd) {
>>>>>>>>            /* Handle the request */
>>>>>>>>            if(tpmcmd->req_len) {
>>>>>>>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>>>>>>>               }
>>>>>>>>               /* If not disabled, do the command */
>>>>>>>>               else {
>>>>>>>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>>>>>>>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>>>>>>>                     error("tpm_handle_command() failed");
>>>>>>>>                     create_error_response(tpmcmd, TPM_FAIL);
>>>>>>>>                  }
>>>>>>>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>>>>>>>            tpmback_resp(tpmcmd);
>>>>>>>>              /* Wait for the next request */
>>>>>>>> -      tpmcmd = tpmback_req(domid, handle);
>>>>>>>> +      tpmcmd = tpmback_req_any();
>>>>>>>>           }
>>>>>>> Before the vtpm would shut down on its own when the host domain disconnects. This occurs because tpmback_req() returns NULL if the frontend disconnected. Using tpmback_req_any(), this is no longer the case which now means the user has to shut down the vtpm manually. How are you handling vtpm shutdown on your end?
>>>>>> When a domain shuts down, "xl destroy" is called on its paired vTPM (by some
>>>>>> scripting that may need to be incorporated into libxl). A graceful shutdown
>>>>>> is not really needed at this point, although it might be needed in the short
>>>>>> term if the save-state operation is not atomic - but a method of recovering
>>>>>> from this type of failure is needed for vTPMs anyway.
>>>>> This is kind of a difficult problem. The save state operation is not by any means atomic and it is very possible that the guest shuts down and xl destroy is called before the save operation completes. This is especially true if the guest is an embedded or even a mini-os domain using tpmfront that shuts down very quickly. Its the reason why now the vtpm shuts itself down after the guest disconnects.
>>>>>
>>>>> What is really needed is a way to do an xl shutdown on mini-os domains to let vtpm-stubdom shutdown correctly. From what I understand there is not yet any support for this in mini-os. How tricky would it be to add that? Samuel any ideas?
>>>>>
>>>>> If thats not possible, another potential hack could be writing a key in xenstore to trigger the shutdown or setting up some other kind of event channel mechanism between the vtpm domain and libxl.
>>>>>
>>>> I have approached this problem from the opposite direction, while looking at
>>>> adding protection from vTPM state rollback. The method that I am currently
>>>> considering is to have two "slots" in the vTPM disk image - one active and
>>>> and one inactive. The save process would then consist of writing a new save
>>>> state to the inactive slot, ensuring it has been committed to disk, and then
>>>> requesting the TPM Manager atomically update the state encryption key to the
>>>> new value. When loading, the key obtained from the TPM manager will only be
>>>> able to decrypt one of the two state images; the successful one is the active
>>>> image. Since the vTPM's saved state is not expected to be very large, this
>>>> doesn't waste a significant amount of disk space.
>>>>
>>> I like that idea in general, but it still doesn't solve the shutdown race condition. You might not get a corrupted disk but you can still get inadvertently rolled back. Adding a xenstore watch as samuel suggested and doing a clean shutdown would be ideal.
>>   If you run the save before you send back the TPM response, you won't have any
>> races - if a domain dies without getting a TPM response, the it's valid for
>> the command to not have completed. The TPM emulator does execute the save
>> prior to returning the result packet, so this race is already avoided.
>>
>> That's not to say that handling shutdowns properly is useless, of course; other
>> minios domains may need it, and a graceful shutdown is easier to clean up after
>> if not all peers of the vTPM are shutting down at the same time.
> Ok I follow you now. Do you already have patches to do the disk mirroring and destroy the vtpm from libxl? I think we will want to include this so these new features don't break the automatic vtpm shutdown model already in place.
> 
No, I haven't implemented either of those yet. The destroy that I'm using is not
based on libxl (it assumes both the vtpm and client domain are being created by a
dedicated domain-builder domain, and so don't have a libxl watcher process).
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 1/4] stubdom: Change vTPM shared page ABI
  2012-11-27 15:14     ` [PATCH 1/4] stubdom: Change vTPM shared page ABI Daniel De Graaf
@ 2012-11-27 21:29       ` Matthew Fioravante
  2012-11-27 22:08         ` Daniel De Graaf
  2012-11-29 14:14       ` Matthew Fioravante
  1 sibling, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-27 21:29 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 26244 bytes --]
I can't get this patch to apply. It looks like your editor or something 
else is converting tabs to whitespace. For instance the line in tpmback.h
     domid_t domid;              /* Domid of the frontend */
has tabs between domid; and /*. It looks like this also happened to your 
linux patch.
On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
> This changes the vTPM shared page ABI from a copy of the Xen network
> interface to a single-page interface that better reflects the expected
> behavior of a TPM: only a single request packet can be sent at any given
> time, and every packet sent generates a single response packet. This
> protocol change should also increase efficiency as it avoids mapping and
> unmapping grants when possible.
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   extras/mini-os/include/tpmback.h  |   1 +
>   extras/mini-os/include/tpmfront.h |   7 +-
>   extras/mini-os/tpmback.c          | 159 +++++++++++++++++++------------------
>   extras/mini-os/tpmfront.c         | 162 ++++++++++++++++++++++----------------
>   xen/include/public/io/tpmif.h     |  45 +++--------
>   5 files changed, 191 insertions(+), 183 deletions(-)
>
> diff --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
> index ff86732..ec9eda4 100644
> --- a/extras/mini-os/include/tpmback.h
> +++ b/extras/mini-os/include/tpmback.h
> @@ -43,6 +43,7 @@
>
>   struct tpmcmd {
>      domid_t domid;              /* Domid of the frontend */
> +   uint8_t locality;    /* Locality requested by the frontend */
>      unsigned int handle;        /* Handle of the frontend */
>      unsigned char uuid[16];                     /* uuid of the tpm interface */
>
> diff --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
> index fd2cb17..a0c7c4d 100644
> --- a/extras/mini-os/include/tpmfront.h
> +++ b/extras/mini-os/include/tpmfront.h
> @@ -37,9 +37,7 @@ struct tpmfront_dev {
>      grant_ref_t ring_ref;
>      evtchn_port_t evtchn;
>
> -   tpmif_tx_interface_t* tx;
> -
> -   void** pages;
> +   vtpm_shared_page_t *page;
>
>      domid_t bedomid;
>      char* nodename;
> @@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
>    * */
>   int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
>
> +/* Set the locality used for communicating with a vTPM */
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
> +
>   #ifdef HAVE_LIBC
>   #include <sys/stat.h>
>   /* POSIX IO functions:
> diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
> index 658fed1..2d31061 100644
> --- a/extras/mini-os/tpmback.c
> +++ b/extras/mini-os/tpmback.c
> @@ -86,10 +86,7 @@ struct tpmif {
>      evtchn_port_t evtchn;
>
>      /* Shared page */
> -   tpmif_tx_interface_t* tx;
> -
> -   /* pointer to TPMIF_RX_RING_SIZE pages */
> -   void** pages;
> +   vtpm_shared_page_t *page;
>
>      enum xenbus_state state;
>      enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
> @@ -266,6 +263,7 @@ int insert_tpmif(tpmif_t* tpmif)
>      unsigned int i, j;
>      tpmif_t* tmp;
>      char* err;
> +   char path[512];
>
>      local_irq_save(flags);
>
> @@ -303,6 +301,16 @@ int insert_tpmif(tpmif_t* tpmif)
>
>      local_irq_restore(flags);
>
> +   snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
> +   if ((err = xenbus_write(XBT_NIL, path, "1")))
> +   {
> +      /* if we got an error here we should carefully remove the interface and then return */
> +      TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> +      free(err);
> +      remove_tpmif(tpmif);
> +      goto error_post_irq;
> +   }
> +
>      /*Listen for state changes on the new interface */
>      if((err = xenbus_watch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path, >pmdev.events)))
>      {
> @@ -312,7 +320,6 @@ int insert_tpmif(tpmif_t* tpmif)
>         remove_tpmif(tpmif);
>         goto error_post_irq;
>      }
> -
>      return 0;
>   error:
>      local_irq_restore(flags);
> @@ -386,8 +393,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
>      tpmif->fe_state_path = NULL;
>      tpmif->state = XenbusStateInitialising;
>      tpmif->status = DISCONNECTED;
> -   tpmif->tx = NULL;
> -   tpmif->pages = NULL;
> +   tpmif->page = NULL;
>      tpmif->flags = 0;
>      memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
>      return tpmif;
> @@ -395,9 +401,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
>
>   void __free_tpmif(tpmif_t* tpmif)
>   {
> -   if(tpmif->pages) {
> -      free(tpmif->pages);
> -   }
>      if(tpmif->fe_path) {
>         free(tpmif->fe_path);
>      }
> @@ -430,12 +433,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
>         goto error;
>      }
>
> -   /* allocate pages to be used for shared mapping */
> -   if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
> -      goto error;
> -   }
> -   memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -
>      if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
>         goto error;
>      }
> @@ -486,7 +483,7 @@ void free_tpmif(tpmif_t* tpmif)
>         tpmif->status = DISCONNECTING;
>         mask_evtchn(tpmif->evtchn);
>
> -      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1)) {
> +      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
>           TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
>         }
>
> @@ -529,9 +526,10 @@ void free_tpmif(tpmif_t* tpmif)
>   void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
>   {
>      tpmif_t* tpmif = (tpmif_t*) data;
> -   tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
> -   /* Throw away 0 size events, these can trigger from event channel unmasking */
> -   if(tx->size == 0)
> +   vtpm_shared_page_t* pg = tpmif->page;
> +
> +   /* Only pay attention if the request is ready */
> +   if (pg->state == 0)
>         return;
>
>      TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
> @@ -584,12 +582,26 @@ int connect_fe(tpmif_t* tpmif)
>      }
>      free(value);
>
> +   /* Check that protocol v2 is being used */
> +   snprintf(path, 512, "%s/feature-protocol-v2", tpmif->fe_path);
> +   if((err = xenbus_read(XBT_NIL, path, &value))) {
> +      TPMBACK_ERR("Unable to read %s during tpmback initialization! error = %s\n", path, err);
> +      free(err);
> +      return -1;
> +   }
> +   if(strcmp(value, "1")) {
> +      TPMBACK_ERR("%s has an invalid value (%s)\n", path, value);
> +      free(value);
> +      return -1;
> +   }
> +   free(value);
> +
> +
>      domid = tpmif->domid;
> -   if((tpmif->tx = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
> +   if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
>         TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
>         return -1;
>      }
> -   memset(tpmif->tx, 0, PAGE_SIZE);
>
>      /*Bind the event channel */
>      if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
> @@ -618,10 +630,28 @@ error_post_evtchn:
>      mask_evtchn(tpmif->evtchn);
>      unbind_evtchn(tpmif->evtchn);
>   error_post_map:
> -   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1);
> +   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
>      return -1;
>   }
>
> +static void disconnect_fe(tpmif_t* tpmif)
> +{
> +   if (tpmif->status == CONNECTED) {
> +      tpmif->status = DISCONNECTING;
> +      mask_evtchn(tpmif->evtchn);
> +
> +      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
> +        TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      }
> +
> +      unbind_evtchn(tpmif->evtchn);
> +   }
> +   tpmif->status = DISCONNECTED;
> +   tpmif_change_state(tpmif, XenbusStateReconfigured);
> +
> +   TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
> +}
> +
>   static int frontend_changed(tpmif_t* tpmif)
>   {
>      int state = xenbus_read_integer(tpmif->fe_state_path);
> @@ -874,6 +904,7 @@ void shutdown_tpmback(void)
>   inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, unsigned char uuid[16])
>   {
>      tpmcmd->domid = domid;
> +   tpmcmd->locality = -1;
>      tpmcmd->handle = handle;
>      memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
>      tpmcmd->req = NULL;
> @@ -884,12 +915,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, un
>
>   tpmcmd_t* get_request(tpmif_t* tpmif) {
>      tpmcmd_t* cmd;
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int tocopy;
> -   int i;
> -   uint32_t domid;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>      int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +   int i;
> +#endif
>
>      local_irq_save(flags);
>
> @@ -899,35 +930,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
>      }
>      init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
>
> -   tx = &tpmif->tx->ring[0].req;
> -   cmd->req_len = tx->size;
> +   shr = tpmif->page;
> +   cmd->req_len = shr->length;
> +   cmd->locality = shr->locality;
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
> +   }
>      /* Allocate the buffer */
>      if(cmd->req_len) {
>         if((cmd->req = malloc(cmd->req_len)) == NULL) {
>           goto error;
>         }
>      }
> -   /* Copy the bits from the shared pages */
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_READ)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->req_len - offset, PAGE_SIZE);
> -      memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
> -
> -   }
> +   /* Copy the bits from the shared page(s) */
> +   memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
>
>   #ifdef TPMBACK_PRINT_DEBUG
>      TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
> @@ -958,38 +976,24 @@ error:
>
>   void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>   {
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int i;
> -   uint32_t domid;
> -   int tocopy;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>      int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +int i;
> +#endif
>
>      local_irq_save(flags);
>
> -   tx = &tpmif->tx->ring[0].req;
> -   tx->size = cmd->resp_len;
> -
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_WRITE)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
> -      memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
> +   shr = tpmif->page;
> +   shr->length = cmd->resp_len;
>
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
>      }
> +   memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
>
>   #ifdef TPMBACK_PRINT_DEBUG
>      TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
> @@ -1003,6 +1007,7 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>   #endif
>      /* clear the ready flag and send the event channel notice to the frontend */
>      tpmif_req_finished(tpmif);
> +   shr->state = 0;
>      notify_remote_via_evtchn(tpmif->evtchn);
>   error:
>      local_irq_restore(flags);
> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
> index 0218d7f..c1cbab3 100644
> --- a/extras/mini-os/tpmfront.c
> +++ b/extras/mini-os/tpmfront.c
> @@ -153,6 +153,32 @@ static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
>
>   }
>
> +static int wait_for_backend_reconfig(xenbus_event_queue* events, char* path)
> +{
> +   int state;
> +
> +   TPMFRONT_LOG("Waiting for backend to reconfigure...\n");
> +   while(1) {
> +      state = xenbus_read_integer(path);
> +      if ( state < 0)
> +        state = XenbusStateUnknown;
> +      switch(state) {
> +        case XenbusStateUnknown:
> +           TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
> +           return -1;
> +        case XenbusStateClosed:
> +           TPMFRONT_LOG("Backend Closed\n");
> +           return 0;
> +        case XenbusStateReconfigured:
> +           TPMFRONT_LOG("Backend Reconfigured\n");
> +           return 0;
> +        default:
> +           xenbus_wait_for_watch(events);
> +      }
> +   }
> +
> +}
> +
>   static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
>      char* err;
>      int ret = 0;
> @@ -175,8 +201,11 @@ static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState
>         case XenbusStateClosed:
>           ret = wait_for_backend_closed(&events, path);
>           break;
> -      default:
> +      case XenbusStateReconfigured:
> +        ret = wait_for_backend_reconfig(&events, path);
>           break;
> +      default:
> +         TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
>      }
>
>      if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
> @@ -190,13 +219,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)
>   {
>      char* err;
>      /* Create shared page */
> -   dev->tx = (tpmif_tx_interface_t*) alloc_page();
> -   if(dev->tx == NULL) {
> +   dev->page = (vtpm_shared_page_t*) alloc_page();
> +   if(dev->page == NULL) {
>         TPMFRONT_ERR("Unable to allocate page for shared memory\n");
>         goto error;
>      }
> -   memset(dev->tx, 0, PAGE_SIZE);
> -   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 0);
> +   memset(dev->page, 0, PAGE_SIZE);
> +   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
>      TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
>
>      /*Create event channel */
> @@ -228,7 +257,7 @@ error_postevtchn:
>         unbind_evtchn(dev->evtchn);
>   error_postmap:
>         gnttab_end_access(dev->ring_ref);
> -      free_page(dev->tx);
> +      free_page(dev->page);
>   error:
>      return -1;
>   }
> @@ -240,7 +269,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>      char path[512];
>      char* value, *err;
>      unsigned long long ival;
> -   int i;
>
>      printk("============= Init TPM Front ================\n");
>
> @@ -279,6 +307,15 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>         goto error;
>      }
>
> +   /* Publish protocol v2 feature */
> +   snprintf(path, 512, "%s/feature-protocol-v2", dev->nodename);
> +   if ((err = xenbus_write(XBT_NIL, path, "1")))
> +   {
> +      TPMFRONT_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> +         free(err);
> +      goto error;
> +   }
> +
>      /* Create and publish grant reference and event channel */
>      if (tpmfront_connect(dev)) {
>         goto error;
> @@ -289,18 +326,18 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>         goto error;
>      }
>
> -   /* Allocate pages that will contain the messages */
> -   dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   if(dev->pages == NULL) {
> +   snprintf(path, 512, "%s/feature-protocol-v2", dev->bepath);
> +   if((err = xenbus_read(XBT_NIL, path, &value))) {
> +      TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
> +      free(err);
>         goto error;
>      }
> -   memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -      dev->pages[i] = (void*)alloc_page();
> -      if(dev->pages[i] == NULL) {
> -        goto error;
> -      }
> +   if(strcmp(value, "1")) {
> +      TPMFRONT_ERR("%s has an invalid value (%s)\n", path, value);
> +      free(value);
> +      goto error;
>      }
> +   free(value);
>
>      TPMFRONT_LOG("Initialization Completed successfully\n");
>
> @@ -314,12 +351,10 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>   {
>      char* err;
>      char path[512];
> -   int i;
> -   tpmif_tx_request_t* tx;
>      if(dev == NULL) {
>         return;
>      }
> -   TPMFRONT_LOG("Shutting down tpmfront\n");
> +   TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
>      /* disconnect */
>      if(dev->state == XenbusStateConnected) {
>         dev->state = XenbusStateClosing;
> @@ -349,27 +384,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>         /* Wait for the backend to close and unmap shared pages, ignore any errors */
>         wait_for_backend_state_changed(dev, XenbusStateClosed);
>
> -      /* Cleanup any shared pages */
> -      if(dev->pages) {
> -        for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -           if(dev->pages[i]) {
> -              tx = &dev->tx->ring[i].req;
> -              if(tx->ref != 0) {
> -                 gnttab_end_access(tx->ref);
> -              }
> -              free_page(dev->pages[i]);
> -           }
> -        }
> -        free(dev->pages);
> -      }
> -
>         /* Close event channel and unmap shared page */
>         mask_evtchn(dev->evtchn);
>         unbind_evtchn(dev->evtchn);
>         gnttab_end_access(dev->ring_ref);
>
> -      free_page(dev->tx);
> -
> +      free_page(dev->page);
>      }
>
>      /* Cleanup memory usage */
> @@ -387,13 +407,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>
>   int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   {
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
>      int i;
> -   tpmif_tx_request_t* tx = NULL;
> +#endif
>      /* Error Checking */
>      if(dev == NULL || dev->state != XenbusStateConnected) {
>         TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
>         return -1;
>      }
> +   shr = dev->page;
>
>   #ifdef TPMFRONT_PRINT_DEBUG
>      TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
> @@ -407,19 +431,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   #endif
>
>      /* Copy to shared pages now */
> -   for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
> -      /* Share the page */
> -      tx = &dev->tx->ring[i].req;
> -      tx->unused = 0;
> -      tx->addr = virt_to_mach(dev->pages[i]);
> -      tx->ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->pages[i]), 0);
> -      /* Copy the bits to the page */
> -      tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
> -      memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
> -
> -      /* Update counters */
> -      length -= tx->size;
> +   offset = sizeof(*shr);
> +   if (length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Message too long for shared page\n");
> +      return -1;
>      }
> +   memcpy(offset + (uint8_t*)shr, msg, length);
> +   shr->length = length;
> +   barrier();
> +   shr->state = 1;
> +
>      dev->waiting = 1;
>      dev->resplen = 0;
>   #ifdef HAVE_LIBC
> @@ -434,44 +455,41 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   }
>   int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
>   {
> -   tpmif_tx_request_t* tx;
> -   int i;
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
> +int i;
> +#endif
>      if(dev == NULL || dev->state != XenbusStateConnected) {
>         TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
>         return -1;
>      }
>      /*Wait for the response */
>      wait_event(dev->waitq, (!dev->waiting));
> +   shr = dev->page;
> +   if (shr->state != 0)
> +      goto quit;
>
>      /* Initialize */
>      *msg = NULL;
> -   *length = 0;
> +   *length = shr->length;
> +   offset = sizeof(*shr);
>
> -   /* special case, just quit */
> -   tx = &dev->tx->ring[0].req;
> -   if(tx->size == 0 ) {
> -       goto quit;
> -   }
> -   /* Get the total size */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      *length += tx->size;
> +   if (*length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Reply too long for shared page\n");
> +      return -1;
>      }
> +
>      /* Alloc the buffer */
>      if(dev->respbuf) {
>         free(dev->respbuf);
>      }
>      *msg = dev->respbuf = malloc(*length);
>      dev->resplen = *length;
> +
>      /* Copy the bits */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
> -      gnttab_end_access(tx->ref);
> -      tx->ref = 0;
> -   }
> +   memcpy(*msg, offset + (uint8_t*)shr, *length);
> +
>   #ifdef TPMFRONT_PRINT_DEBUG
>      TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
>      for(i = 0; i < *length; ++i) {
> @@ -504,6 +522,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t*
>      return 0;
>   }
>
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
> +{
> +   if (!dev || !dev->page)
> +      return -1;
> +   dev->page->locality = locality;
> +   return 0;
> +}
> +
>   #ifdef HAVE_LIBC
>   #include <errno.h>
>   int tpmfront_open(struct tpmfront_dev* dev)
> diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h
> index 02ccdab..afc9181 100644
> --- a/xen/include/public/io/tpmif.h
> +++ b/xen/include/public/io/tpmif.h
> @@ -1,7 +1,7 @@
>   /******************************************************************************
>    * tpmif.h
>    *
> - * TPM I/O interface for Xen guest OSes.
> + * TPM I/O interface for Xen guest OSes, v2
>    *
>    * Permission is hereby granted, free of charge, to any person obtaining a copy
>    * of this software and associated documentation files (the "Software"), to
> @@ -21,48 +21,23 @@
>    * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>    * DEALINGS IN THE SOFTWARE.
>    *
> - * Copyright (c) 2005, IBM Corporation
> - *
> - * Author: Stefan Berger, stefanb@us.ibm.com
> - * Grant table support: Mahadevan Gomathisankaran
> - *
> - * This code has been derived from tools/libxc/xen/io/netif.h
> - *
> - * Copyright (c) 2003-2004, Keir Fraser
>    */
>
>   #ifndef __XEN_PUBLIC_IO_TPMIF_H__
>   #define __XEN_PUBLIC_IO_TPMIF_H__
>
> -#include "../grant_table.h"
> +struct vtpm_shared_page {
> +    uint16_t length;         /* request/response length in bytes */
>
> -struct tpmif_tx_request {
> -    unsigned long addr;   /* Machine address of packet.   */
> -    grant_ref_t ref;      /* grant table access reference */
> -    uint16_t unused;
> -    uint16_t size;        /* Packet size in bytes.        */
> -};
> -typedef struct tpmif_tx_request tpmif_tx_request_t;
> -
> -/*
> - * The TPMIF_TX_RING_SIZE defines the number of pages the
> - * front-end and backend can exchange (= size of array).
> - */
> -typedef uint32_t TPMIF_RING_IDX;
> -
> -#define TPMIF_TX_RING_SIZE 1
> -
> -/* This structure must fit in a memory page. */
> -
> -struct tpmif_ring {
> -    struct tpmif_tx_request req;
> -};
> -typedef struct tpmif_ring tpmif_ring_t;
> +    uint8_t state;           /* 0 - response ready / idle
> +                              * 1 - request ready / working */
> +    uint8_t locality;        /* for the current request */
> +    uint8_t padding[3];
>
> -struct tpmif_tx_interface {
> -    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
> +    uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
> +    uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
>   };
> -typedef struct tpmif_tx_interface tpmif_tx_interface_t;
> +typedef struct vtpm_shared_page vtpm_shared_page_t;
>
>   #endif
>
> --
> 1.7.11.7
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 1/4] stubdom: Change vTPM shared page ABI
  2012-11-27 21:29       ` Matthew Fioravante
@ 2012-11-27 22:08         ` Daniel De Graaf
  0 siblings, 0 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 22:08 UTC (permalink / raw)
  To: Matthew Fioravante; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/27/2012 04:29 PM, Matthew Fioravante wrote:
> I can't get this patch to apply. It looks like your editor or something else is converting tabs to whitespace. For instance the line in tpmback.h
> 
>     domid_t domid;              /* Domid of the frontend */
> 
> has tabs between domid; and /*. It looks like this also happened to your linux patch.
The problem looks like it's on your end; my patch has a tab character there,
and it shows up with a tab character in my copy of the xen-devel list.
As a quick workaround, I have pushed these patches to my github repository:
https://github.com/danieldg/xen-unstable/commits/vtpm
> 
> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>> This changes the vTPM shared page ABI from a copy of the Xen network
>> interface to a single-page interface that better reflects the expected
>> behavior of a TPM: only a single request packet can be sent at any given
>> time, and every packet sent generates a single response packet. This
>> protocol change should also increase efficiency as it avoids mapping and
>> unmapping grants when possible.
>>
>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>> ---
>>   extras/mini-os/include/tpmback.h  |   1 +
>>   extras/mini-os/include/tpmfront.h |   7 +-
>>   extras/mini-os/tpmback.c          | 159 +++++++++++++++++++------------------
>>   extras/mini-os/tpmfront.c         | 162 ++++++++++++++++++++++----------------
>>   xen/include/public/io/tpmif.h     |  45 +++--------
>>   5 files changed, 191 insertions(+), 183 deletions(-)
>>
>> diff --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
>> index ff86732..ec9eda4 100644
>> --- a/extras/mini-os/include/tpmback.h
>> +++ b/extras/mini-os/include/tpmback.h
>> @@ -43,6 +43,7 @@
>>
>>   struct tpmcmd {
>>      domid_t domid;              /* Domid of the frontend */
>> +   uint8_t locality;    /* Locality requested by the frontend */
>>      unsigned int handle;        /* Handle of the frontend */
>>      unsigned char uuid[16];                     /* uuid of the tpm interface */
^ permalink raw reply	[flat|nested] 53+ messages in thread
* [PATCH] stubdom/vtpm: make state save operation atomic
  2012-11-27 20:40                     ` Daniel De Graaf
@ 2012-11-27 22:16                       ` Daniel De Graaf
  2012-11-29 18:07                         ` Matthew Fioravante
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-27 22:16 UTC (permalink / raw)
  To: matthew.fioravante
  Cc: samuel.thibault, Daniel De Graaf, Ian.Campbell, xen-devel
This changes the save format of the vtpm stubdom to include two copies
of the saved data: one active, and one inactive. When saving the state,
data is written to the inactive slot before updating the key and hash
saved with the TPM Manager, which determines the active slot when the
vTPM starts up.
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
 stubdom/vtpm/vtpmblk.c | 66 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 54 insertions(+), 12 deletions(-)
diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c
index b343bd8..f988606 100644
--- a/stubdom/vtpm/vtpmblk.c
+++ b/stubdom/vtpm/vtpmblk.c
@@ -23,6 +23,8 @@
 
 /*Encryption key and block sizes */
 #define BLKSZ 16
+/* Maximum size of one saved-state slot */
+#define SLOT_SIZE 32768
 
 static struct blkfront_dev* blkdev = NULL;
 static int blkfront_fd = -1;
@@ -59,15 +61,20 @@ void shutdown_vtpmblk(void)
    blkdev = NULL;
 }
 
-int write_vtpmblk_raw(uint8_t *data, size_t data_length)
+static int write_vtpmblk_raw(uint8_t *data, size_t data_length, int slot)
 {
    int rc;
    uint32_t lenbuf;
    debug("Begin Write data=%p len=%u", data, data_length);
 
+   if (data_length > SLOT_SIZE - 4) {
+      error("write(data) cannot fit in data slot (%d). Increase SLOT_SIZE.", data_length);
+      return -1;
+   }
+
    lenbuf = cpu_to_be32((uint32_t)data_length);
 
-   lseek(blkfront_fd, 0, SEEK_SET);
+   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
    if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
       error("write(length) failed! error was %s", strerror(errno));
       return -1;
@@ -82,12 +89,12 @@ int write_vtpmblk_raw(uint8_t *data, size_t data_length)
    return 0;
 }
 
-int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
+static int read_vtpmblk_raw(uint8_t **data, size_t *data_length, int slot)
 {
    int rc;
    uint32_t lenbuf;
 
-   lseek(blkfront_fd, 0, SEEK_SET);
+   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
    if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
       error("read(length) failed! error was %s", strerror(errno));
       return -1;
@@ -97,6 +104,10 @@ int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
       error("read 0 data_length for NVM");
       return -1;
    }
+   if(*data_length > SLOT_SIZE - 4) {
+      error("read invalid data_length for NVM");
+      return -1;
+   }
 
    *data = tpm_malloc(*data_length);
    if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
@@ -221,6 +232,8 @@ egress:
    return rc;
 }
 
+static int active_slot = -1;
+
 int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
    int rc;
    uint8_t* cipher = NULL;
@@ -228,12 +241,15 @@ int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_
    uint8_t hashkey[HASHKEYSZ];
    uint8_t* symkey = hashkey + HASHSZ;
 
+   /* Switch to the other slot */
+   active_slot = !active_slot;
+
    /* 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))) {
+   if((rc = write_vtpmblk_raw(cipher, cipher_len, active_slot))) {
       goto abort_egress;
    }
    /* Get sha1 hash of data */
@@ -256,7 +272,8 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
    size_t cipher_len = 0;
    size_t keysize;
    uint8_t* hashkey = NULL;
-   uint8_t hash[HASHSZ];
+   uint8_t hash0[HASHSZ];
+   uint8_t hash1[HASHSZ];
    uint8_t* symkey;
 
    /* Retreive the hash and the key from the manager */
@@ -270,14 +287,32 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
    }
    symkey = hashkey + HASHSZ;
 
-   /* Read from disk now */
-   if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
+   active_slot = 0;
+   /* Read slot 0 from disk now */
+   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 0))) {
+      goto abort_egress;
+   }
+
+   /* Compute the hash of the cipher text and compare */
+   sha1(cipher, cipher_len, hash0);
+   if(!memcmp(hash0, hashkey, HASHSZ))
+      goto valid;
+
+   free(cipher);
+   cipher = NULL;
+
+   active_slot = 1;
+   /* Read slot 1 from disk now */
+   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 1))) {
       goto abort_egress;
    }
 
    /* Compute the hash of the cipher text and compare */
-   sha1(cipher, cipher_len, hash);
-   if(memcmp(hash, hashkey, HASHSZ)) {
+   sha1(cipher, cipher_len, hash1);
+   if(!memcmp(hash1, hashkey, HASHSZ))
+      goto valid;
+
+   {
       int i;
       error("NVM Storage Checksum failed!");
       printf("Expected: ");
@@ -285,14 +320,20 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
 	 printf("%02hhX ", hashkey[i]);
       }
       printf("\n");
-      printf("Actual:   ");
+      printf("Slot 0:   ");
+      for(i = 0; i < HASHSZ; ++i) {
+	 printf("%02hhX ", hash0[i]);
+      }
+      printf("\n");
+      printf("Slot 1:   ");
       for(i = 0; i < HASHSZ; ++i) {
-	 printf("%02hhX ", hash[i]);
+	 printf("%02hhX ", hash1[i]);
       }
       printf("\n");
       rc = -1;
       goto abort_egress;
    }
+valid:
 
    /* Decrypt the blob */
    if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
@@ -300,6 +341,7 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
    }
    goto egress;
 abort_egress:
+   active_slot = -1;
 egress:
    free(cipher);
    free(hashkey);
-- 
1.7.11.7
^ permalink raw reply related	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-23 11:04   ` [PATCH RFC] stubdom: " Ian Campbell
  2012-11-23 16:15     ` Daniel De Graaf
@ 2012-11-28 20:46     ` Konrad Rzeszutek Wilk
  2012-11-28 22:22       ` Matthew Fioravante
  1 sibling, 1 reply; 53+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-11-28 20:46 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Fioravante, Matthew E., Daniel De Graaf, xen-devel@lists.xen.org
On Fri, Nov 23, 2012 at 11:04:06AM +0000, Ian Campbell wrote:
> On Tue, 2012-11-20 at 16:16 +0000, Fioravante, Matthew E. wrote:
> > This was something I've been wanting to do for a while so I'm very
> > happy you went ahead and fixed it yourself. Once you submit the linux
> > version I'll test it on my system.
> > 
> > Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
> 
> Do we need to synchronise with anything else (Linux drivers?) or I can I
> just throw this into the tree once it is done?
> 
> Are we hanging any existing users of the tpm stuff out to dry? Could we
> get a feature-protocol-v2 flag in xenstore so users at least get an
> error message from either the front or backend to give a hint why it
> isn't working?
We could cop out and just name this new driver differently. Then
we would not have to deal with the older ones.
> 
> >  void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
> > -   tpmif_tx_request_t* tx;
> > -   int offset;
> > -   int i;
> > -   uint32_t domid;
> > -   int tocopy;
> > +   vtpm_shared_page_t* shr;
> > +   unsigned int offset;
> >     int flags;
> > +#ifdef TPMBACK_PRINT_DEBUG
> > +int i;
> > +#endif
> 
> Dodgy indentation? (I saw a bunch of these)
> 
> > - * Copyright (c) 2005, IBM Corporation
> > - *
> > - * Author: Stefan Berger, stefanb@us.ibm.com
> > - * Grant table support: Mahadevan Gomathisankaran
> 
> Did you really remove everything these guys wrote?
> 
> > - * This code has been derived from tools/libxc/xen/io/netif.h
> > - *
> > - * Copyright (c) 2003-2004, Keir Fraser
> 
> I guess I can buy this bit no longer being true given that you reworked
> the whole protocol.
> 
> Ian
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
> 
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 19:48           ` Matthew Fioravante
  2012-11-27 20:04             ` Samuel Thibault
  2012-11-27 20:11             ` Daniel De Graaf
@ 2012-11-28 21:58             ` Samuel Thibault
  2 siblings, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-28 21:58 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Daniel De Graaf, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
Matthew Fioravante, le Tue 27 Nov 2012 14:48:29 -0500, a écrit :
> What is really needed is a way to do an xl shutdown on mini-os domains to
> let vtpm-stubdom shutdown correctly. From what I understand there is not yet
> any support for this in mini-os. How tricky would it be to add that? Samuel
> any ideas?
I have just posted a patch for this.
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-28 20:46     ` Konrad Rzeszutek Wilk
@ 2012-11-28 22:22       ` Matthew Fioravante
  2012-11-29  7:53         ` Ian Campbell
  2012-11-30 16:11         ` Konrad Rzeszutek Wilk
  0 siblings, 2 replies; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-28 22:22 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Daniel De Graaf, Ian Campbell, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 2069 bytes --]
On 11/28/2012 03:46 PM, Konrad Rzeszutek Wilk wrote:
> On Fri, Nov 23, 2012 at 11:04:06AM +0000, Ian Campbell wrote:
>> On Tue, 2012-11-20 at 16:16 +0000, Fioravante, Matthew E. wrote:
>>> This was something I've been wanting to do for a while so I'm very
>>> happy you went ahead and fixed it yourself. Once you submit the linux
>>> version I'll test it on my system.
>>>
>>> Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
>> Do we need to synchronise with anything else (Linux drivers?) or I can I
>> just throw this into the tree once it is done?
>>
>> Are we hanging any existing users of the tpm stuff out to dry? Could we
>> get a feature-protocol-v2 flag in xenstore so users at least get an
>> error message from either the front or backend to give a hint why it
>> isn't working?
> We could cop out and just name this new driver differently. Then
> we would not have to deal with the older ones.
I've already done that with my patch on the linux mailing list. The old 
frontend driver name was tpm_xenu.ko, the new one is xen-tpmfront.ko.
>
>>>   void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
>>> -   tpmif_tx_request_t* tx;
>>> -   int offset;
>>> -   int i;
>>> -   uint32_t domid;
>>> -   int tocopy;
>>> +   vtpm_shared_page_t* shr;
>>> +   unsigned int offset;
>>>      int flags;
>>> +#ifdef TPMBACK_PRINT_DEBUG
>>> +int i;
>>> +#endif
>> Dodgy indentation? (I saw a bunch of these)
>>
>>> - * Copyright (c) 2005, IBM Corporation
>>> - *
>>> - * Author: Stefan Berger, stefanb@us.ibm.com
>>> - * Grant table support: Mahadevan Gomathisankaran
>> Did you really remove everything these guys wrote?
>>
>>> - * This code has been derived from tools/libxc/xen/io/netif.h
>>> - *
>>> - * Copyright (c) 2003-2004, Keir Fraser
>> I guess I can buy this bit no longer being true given that you reworked
>> the whole protocol.
>>
>> Ian
>>
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xen.org
>> http://lists.xen.org/xen-devel
>>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-28 22:22       ` Matthew Fioravante
@ 2012-11-29  7:53         ` Ian Campbell
  2012-11-30 16:11         ` Konrad Rzeszutek Wilk
  1 sibling, 0 replies; 53+ messages in thread
From: Ian Campbell @ 2012-11-29  7:53 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Konrad Rzeszutek Wilk, Daniel De Graaf, xen-devel@lists.xen.org
On Wed, 2012-11-28 at 22:22 +0000, Matthew Fioravante wrote:
> On 11/28/2012 03:46 PM, Konrad Rzeszutek Wilk wrote:
> > We could cop out and just name this new driver differently. Then
> > we would not have to deal with the older ones.
> I've already done that with my patch on the linux mailing list. The old 
> frontend driver name was tpm_xenu.ko, the new one is xen-tpmfront.ko.
The name of the driver module isn't really relevant here, what matters
is the name component of the xenstore paths used to trigger the creation
the front and back devices, if they end up loading mutually
incomprehensible versions of front and back then I expect that the
failure case will be pretty hard to diagnose.
The code I'm talking about is a handful of lines in both front and back,
with $OTHEREND substituted as appropriate:
	err = xenbus_printf(xbt, dev->nodename, "feature-protocol-v2", "1");
        if (err) {
                message = "writing feature-protocol-v2";
                goto abort_transaction;
        }
	...
        if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-protocol-v2", "%d", &val) < 0) {
		printk(KERN_WARN "Warning: $OTHEREND does not appear to support feature-protocol-v2\n");
		printk(KERN_WARN "Perhaps it is running the obsolete out of tree vtpm driver?\n");
		return -EFOOBAR;
	}
Tweak the actual wording to taste.
If there is a better/more descriptive name for the new protocol than
"protocol-v2" that would be better, or you could put the 2 into the
value (e.g. protocol = 2) and check via that instead (a bit more future
proof perhaps?).
Ian.
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 1/4] stubdom: Change vTPM shared page ABI
  2012-11-27 15:14     ` [PATCH 1/4] stubdom: Change vTPM shared page ABI Daniel De Graaf
  2012-11-27 21:29       ` Matthew Fioravante
@ 2012-11-29 14:14       ` Matthew Fioravante
  2012-12-07 21:25         ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-29 14:14 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 27578 bytes --]
Ok I've taken time to look at your patch. I had to make some minor 
changes to make it work but other than that I was able to test it and it 
worked.
Comments inlined.
On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
> This changes the vTPM shared page ABI from a copy of the Xen network
> interface to a single-page interface that better reflects the expected
> behavior of a TPM: only a single request packet can be sent at any given
> time, and every packet sent generates a single response packet. This
> protocol change should also increase efficiency as it avoids mapping and
> unmapping grants when possible.
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   extras/mini-os/include/tpmback.h  |   1 +
>   extras/mini-os/include/tpmfront.h |   7 +-
>   extras/mini-os/tpmback.c          | 159 +++++++++++++++++++------------------
>   extras/mini-os/tpmfront.c         | 162 ++++++++++++++++++++++----------------
>   xen/include/public/io/tpmif.h     |  45 +++--------
>   5 files changed, 191 insertions(+), 183 deletions(-)
>
> diff --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
> index ff86732..ec9eda4 100644
> --- a/extras/mini-os/include/tpmback.h
> +++ b/extras/mini-os/include/tpmback.h
> @@ -43,6 +43,7 @@
>
>   struct tpmcmd {
>      domid_t domid;              /* Domid of the frontend */
> +   uint8_t locality;    /* Locality requested by the frontend */
>      unsigned int handle;        /* Handle of the frontend */
>      unsigned char uuid[16];                     /* uuid of the tpm interface */
>
> diff --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
> index fd2cb17..a0c7c4d 100644
> --- a/extras/mini-os/include/tpmfront.h
> +++ b/extras/mini-os/include/tpmfront.h
> @@ -37,9 +37,7 @@ struct tpmfront_dev {
>      grant_ref_t ring_ref;
>      evtchn_port_t evtchn;
>
> -   tpmif_tx_interface_t* tx;
> -
> -   void** pages;
> +   vtpm_shared_page_t *page;
>
>      domid_t bedomid;
>      char* nodename;
> @@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
>    * */f
>   int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
>
> +/* Set the locality used for communicating with a vTPM */
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
> +
>   #ifdef HAVE_LIBC
>   #include <sys/stat.h>
>   /* POSIX IO functions:
> diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
> index 658fed1..2d31061 100644
> --- a/extras/mini-os/tpmback.c
> +++ b/extras/mini-os/tpmback.c
> @@ -86,10 +86,7 @@ struct tpmif {
>      evtchn_port_t evtchn;
>
>      /* Shared page */
> -   tpmif_tx_interface_t* tx;
> -
> -   /* pointer to TPMIF_RX_RING_SIZE pages */
> -   void** pages;
> +   vtpm_shared_page_t *page;
>
>      enum xenbus_state state;
>      enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
> @@ -266,6 +263,7 @@ int insert_tpmif(tpmif_t* tpmif)
>      unsigned int i, j;
>      tpmif_t* tmp;
>      char* err;
> +   char path[512];
>
>      local_irq_save(flags);
>
> @@ -303,6 +301,16 @@ int insert_tpmif(tpmif_t* tpmif)
>
>      local_irq_restore(flags);
>
> +   snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
> +   if ((err = xenbus_write(XBT_NIL, path, "1")))
> +   {
> +      /* if we got an error here we should carefully remove the interface and then return */
> +      TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> +      free(err);
> +      remove_tpmif(tpmif);
> +      goto error_post_irq;
> +   }
> +
My preference is still to do away with the versioning stuff since tpm is 
just getting released. Its not even in linux yet so there is no 
confusion. We can even merge the linux patches together and resubmit as 
one if thats preferrable. Konrad, Ian, your final votes on that?
If we do go the versioning route, I'd rather a feature-protocol key with 
value=2 or something like that to make it upgradable. Also don't forget 
to add this to the linux side, its not in the patch you sent me yet.
>      /*Listen for state changes on the new interface */
>      if((err = xenbus_watch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path, >pmdev.events)))
>      {
> @@ -312,7 +320,6 @@ int insert_tpmif(tpmif_t* tpmif)
>         remove_tpmif(tpmif);
>         goto error_post_irq;
>      }
> -
>      return 0;
>   error:
>      local_irq_restore(flags);
> @@ -386,8 +393,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
>      tpmif->fe_state_path = NULL;
>      tpmif->state = XenbusStateInitialising;
>      tpmif->status = DISCONNECTED;
> -   tpmif->tx = NULL;
> -   tpmif->pages = NULL;
> +   tpmif->page = NULL;
>      tpmif->flags = 0;
>      memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
>      return tpmif;
> @@ -395,9 +401,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
>
>   void __free_tpmif(tpmif_t* tpmif)
>   {
> -   if(tpmif->pages) {
> -      free(tpmif->pages);
> -   }
>      if(tpmif->fe_path) {
>         free(tpmif->fe_path);
>      }
> @@ -430,12 +433,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
>         goto error;
>      }
>
> -   /* allocate pages to be used for shared mapping */
> -   if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
> -      goto error;
> -   }
> -   memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -
>      if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
>         goto error;
>      }
> @@ -486,7 +483,7 @@ void free_tpmif(tpmif_t* tpmif)
>         tpmif->status = DISCONNECTING;
>         mask_evtchn(tpmif->evtchn);
>
> -      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1)) {
> +      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
>           TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
>         }
>
> @@ -529,9 +526,10 @@ void free_tpmif(tpmif_t* tpmif)
>   void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
>   {
>      tpmif_t* tpmif = (tpmif_t*) data;
> -   tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
> -   /* Throw away 0 size events, these can trigger from event channel unmasking */
> -   if(tx->size == 0)
> +   vtpm_shared_page_t* pg = tpmif->page;
> +
> +   /* Only pay attention if the request is ready */
> +   if (pg->state == 0)
>         return;
>
>      TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
> @@ -584,12 +582,26 @@ int connect_fe(tpmif_t* tpmif)
>      }
>      free(value);
>
> +   /* Check that protocol v2 is being used */
> +   snprintf(path, 512, "%s/feature-protocol-v2", tpmif->fe_path);
> +   if((err = xenbus_read(XBT_NIL, path, &value))) {
> +      TPMBACK_ERR("Unable to read %s during tpmback initialization! error = %s\n", path, err);
> +      free(err);
> +      return -1;
> +   }
> +   if(strcmp(value, "1")) {
> +      TPMBACK_ERR("%s has an invalid value (%s)\n", path, value);
> +      free(value);
> +      return -1;
> +   }
> +   free(value);
> +
> +
>      domid = tpmif->domid;
> -   if((tpmif->tx = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
> +   if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
>         TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
>         return -1;
>      }
> -   memset(tpmif->tx, 0, PAGE_SIZE);
>
>      /*Bind the event channel */
>      if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
> @@ -618,10 +630,28 @@ error_post_evtchn:
>      mask_evtchn(tpmif->evtchn);
>      unbind_evtchn(tpmif->evtchn);
>   error_post_map:
> -   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->tx, 1);
> +   gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
>      return -1;
>   }
>
> +static void disconnect_fe(tpmif_t* tpmif)
> +{
> +   if (tpmif->status == CONNECTED) {
> +      tpmif->status = DISCONNECTING;
> +      mask_evtchn(tpmif->evtchn);
> +
> +      if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
> +        TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      }
> +
> +      unbind_evtchn(tpmif->evtchn);
> +   }
> +   tpmif->status = DISCONNECTED;
> +   tpmif_change_state(tpmif, XenbusStateReconfigured);
> +
> +   TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
> +}
> +
This function is flagged by -Wunused-function. I think you meant to 
include this in your second patch that does the reconfig stuff.
>   static int frontend_changed(tpmif_t* tpmif)
>   {
>      int state = xenbus_read_integer(tpmif->fe_state_path);
> @@ -874,6 +904,7 @@ void shutdown_tpmback(void)
>   inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, unsigned char uuid[16])
>   {
>      tpmcmd->domid = domid;
> +   tpmcmd->locality = -1;
>      tpmcmd->handle = handle;
>      memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
>      tpmcmd->req = NULL;
> @@ -884,12 +915,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, un
>
>   tpmcmd_t* get_request(tpmif_t* tpmif) {
>      tpmcmd_t* cmd;
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int tocopy;
> -   int i;
> -   uint32_t domid;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>      int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +   int i;
> +#endif
>
>      local_irq_save(flags);
>
> @@ -899,35 +930,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
>      }
>      init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
>
> -   tx = &tpmif->tx->ring[0].req;
> -   cmd->req_len = tx->size;
> +   shr = tpmif->page;
> +   cmd->req_len = shr->length;
> +   cmd->locality = shr->locality;
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
> +   }
>      /* Allocate the buffer */
>      if(cmd->req_len) {
>         if((cmd->req = malloc(cmd->req_len)) == NULL) {
>           goto error;
>         }
>      }
> -   /* Copy the bits from the shared pages */
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_READ)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->req_len - offset, PAGE_SIZE);
> -      memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
> -
> -   }
> +   /* Copy the bits from the shared page(s) */
> +   memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
>
>   #ifdef TPMBACK_PRINT_DEBUG
>      TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
> @@ -958,38 +976,24 @@ error:
>
>   void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>   {
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int i;
> -   uint32_t domid;
> -   int tocopy;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>      int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +int i;
> +#endif
>
>      local_irq_save(flags);
>
> -   tx = &tpmif->tx->ring[0].req;
> -   tx->size = cmd->resp_len;
> -
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &tx->ref, PROT_WRITE)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
> -      memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(>pmdev.map, (unsigned long)tpmif->pages[i], 1);
> +   shr = tpmif->page;
> +   shr->length = cmd->resp_len;
>
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
>      }
> +   memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
>
>   #ifdef TPMBACK_PRINT_DEBUG
>      TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
> @@ -1003,6 +1007,7 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>   #endif
>      /* clear the ready flag and send the event channel notice to the frontend */
>      tpmif_req_finished(tpmif);
> +   shr->state = 0;
>      notify_remote_via_evtchn(tpmif->evtchn);
>   error:
>      local_irq_restore(flags);
> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
> index 0218d7f..c1cbab3 100644
> --- a/extras/mini-os/tpmfront.c
> +++ b/extras/mini-os/tpmfront.c
> @@ -153,6 +153,32 @@ static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
>
>   }
>
> +static int wait_for_backend_reconfig(xenbus_event_queue* events, char* path)
> +{
> +   int state;
> +
> +   TPMFRONT_LOG("Waiting for backend to reconfigure...\n");
> +   while(1) {
> +      state = xenbus_read_integer(path);
> +      if ( state < 0)
> +        state = XenbusStateUnknown;
> +      switch(state) {
> +        case XenbusStateUnknown:
> +           TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
> +           return -1;
> +        case XenbusStateClosed:
> +           TPMFRONT_LOG("Backend Closed\n");
> +           return 0;
> +        case XenbusStateReconfigured:
> +           TPMFRONT_LOG("Backend Reconfigured\n");
> +           return 0;
> +        default:
> +           xenbus_wait_for_watch(events);
> +      }
> +   }
> +
> +}
> +
Does this reconfigure stuff make sense without patch 2?
>   static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
>      char* err;
>      int ret = 0;
> @@ -175,8 +201,11 @@ static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState
>         case XenbusStateClosed:
>           ret = wait_for_backend_closed(&events, path);
>           break;
> -      default:
> +      case XenbusStateReconfigured:
> +        ret = wait_for_backend_reconfig(&events, path);
>           break;
> +      default:
> +         TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
>      }
See above comment
>
>      if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
> @@ -190,13 +219,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)
>   {
>      char* err;
>      /* Create shared page */
> -   dev->tx = (tpmif_tx_interface_t*) alloc_page();
> -   if(dev->tx == NULL) {
> +   dev->page = (vtpm_shared_page_t*) alloc_page();
> +   if(dev->page == NULL) {
>         TPMFRONT_ERR("Unable to allocate page for shared memory\n");
>         goto error;
>      }
> -   memset(dev->tx, 0, PAGE_SIZE);
> -   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 0);
> +   memset(dev->page, 0, PAGE_SIZE);
> +   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
>      TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
>
>      /*Create event channel */
> @@ -228,7 +257,7 @@ error_postevtchn:
>         unbind_evtchn(dev->evtchn);
>   error_postmap:
>         gnttab_end_access(dev->ring_ref);
> -      free_page(dev->tx);
> +      free_page(dev->page);
>   error:
>      return -1;
>   }
> @@ -240,7 +269,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>      char path[512];
>      char* value, *err;
>      unsigned long long ival;
> -   int i;
>
>      printk("============= Init TPM Front ================\n");
>
> @@ -279,6 +307,15 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>         goto error;
>      }
>
> +   /* Publish protocol v2 feature */
> +   snprintf(path, 512, "%s/feature-protocol-v2", dev->nodename);
> +   if ((err = xenbus_write(XBT_NIL, path, "1")))
> +   {
> +      TPMFRONT_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> +         free(err);
> +      goto error;
> +   }
> +
>      /* Create and publish grant reference and event channel */
>      if (tpmfront_connect(dev)) {
>         goto error;
> @@ -289,18 +326,18 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>         goto error;
>      }
>
> -   /* Allocate pages that will contain the messages */
> -   dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   if(dev->pages == NULL) {
> +   snprintf(path, 512, "%s/feature-protocol-v2", dev->bepath);
> +   if((err = xenbus_read(XBT_NIL, path, &value))) {
> +      TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
> +      free(err);
>         goto error;
>      }
> -   memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -      dev->pages[i] = (void*)alloc_page();
> -      if(dev->pages[i] == NULL) {
> -        goto error;
> -      }
> +   if(strcmp(value, "1")) {
> +      TPMFRONT_ERR("%s has an invalid value (%s)\n", path, value);
> +      free(value);
> +      goto error;
>      }
> +   free(value);
>
>      TPMFRONT_LOG("Initialization Completed successfully\n");
>
> @@ -314,12 +351,10 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>   {
>      char* err;
>      char path[512];
> -   int i;
> -   tpmif_tx_request_t* tx;
>      if(dev == NULL) {
>         return;
>      }
> -   TPMFRONT_LOG("Shutting down tpmfront\n");
> +   TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
I think the above line belongs in your second patch. for_reconfig is 
undefined, causing compilation to fail.
>      /* disconnect */
>      if(dev->state == XenbusStateConnected) {
>         dev->state = XenbusStateClosing;
> @@ -349,27 +384,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>         /* Wait for the backend to close and unmap shared pages, ignore any errors */
>         wait_for_backend_state_changed(dev, XenbusStateClosed);
>
> -      /* Cleanup any shared pages */
> -      if(dev->pages) {
> -        for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -           if(dev->pages[i]) {
> -              tx = &dev->tx->ring[i].req;
> -              if(tx->ref != 0) {
> -                 gnttab_end_access(tx->ref);
> -              }
> -              free_page(dev->pages[i]);
> -           }
> -        }
> -        free(dev->pages);
> -      }
> -
>         /* Close event channel and unmap shared page */
>         mask_evtchn(dev->evtchn);
>         unbind_evtchn(dev->evtchn);
>         gnttab_end_access(dev->ring_ref);
>
> -      free_page(dev->tx);
> -
> +      free_page(dev->page);
>      }
>
>      /* Cleanup memory usage */
> @@ -387,13 +407,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>
>   int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   {
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
>      int i;
> -   tpmif_tx_request_t* tx = NULL;
> +#endif
>      /* Error Checking */
>      if(dev == NULL || dev->state != XenbusStateConnected) {
>         TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
>         return -1;
>      }
> +   shr = dev->page;
>
>   #ifdef TPMFRONT_PRINT_DEBUG
>      TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
> @@ -407,19 +431,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   #endif
>
>      /* Copy to shared pages now */
> -   for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
> -      /* Share the page */
> -      tx = &dev->tx->ring[i].req;
> -      tx->unused = 0;
> -      tx->addr = virt_to_mach(dev->pages[i]);
> -      tx->ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->pages[i]), 0);
> -      /* Copy the bits to the page */
> -      tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
> -      memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
> -
> -      /* Update counters */
> -      length -= tx->size;
> +   offset = sizeof(*shr);
> +   if (length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Message too long for shared page\n");
> +      return -1;
>      }
I think it might be useful to #define a TPMIF_CAP_PROP_BUFFER_SIZE in 
tpmif.h so people know ahead of time the largest command they can send. 
Then they can create arrays on the stack with the correct length etc..
This brings up another issue. According to the TPM PC Client spec 
section 11.3.8, there is a capability TPM_CAP_PROP_BUFFER_SIZE. We 
should probably patch the emulator in vtpm-stubdom to make it return 
TPMIF_CAP_PROP_BUFFER_SIZE for this capability. You don't have to worry 
about this now if you don't want to. I can do it later once this stuff 
is in. If you do decide to tackle it, make it a separate patch.
> +   memcpy(offset + (uint8_t*)shr, msg, length);
> +   shr->length = length;
> +   barrier();
> +   shr->state = 1;
> +
>      dev->waiting = 1;
>      dev->resplen = 0;
>   #ifdef HAVE_LIBC
> @@ -434,44 +455,41 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
>   }
>   int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
>   {
> -   tpmif_tx_request_t* tx;
> -   int i;
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
> +int i;
> +#endif
>      if(dev == NULL || dev->state != XenbusStateConnected) {
>         TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
>         return -1;
>      }
>      /*Wait for the response */
>      wait_event(dev->waitq, (!dev->waiting));
> +   shr = dev->page;
> +   if (shr->state != 0)
> +      goto quit;
>
>      /* Initialize */
>      *msg = NULL;
> -   *length = 0;
> +   *length = shr->length;
> +   offset = sizeof(*shr);
>
> -   /* special case, just quit */
> -   tx = &dev->tx->ring[0].req;
> -   if(tx->size == 0 ) {
> -       goto quit;
> -   }
> -   /* Get the total size */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      *length += tx->size;
> +   if (*length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Reply too long for shared page\n");
> +      return -1;
>      }
> +
>      /* Alloc the buffer */
>      if(dev->respbuf) {
>         free(dev->respbuf);
>      }
>      *msg = dev->respbuf = malloc(*length);
>      dev->resplen = *length;
> +
>      /* Copy the bits */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
> -      gnttab_end_access(tx->ref);
> -      tx->ref = 0;
> -   }
> +   memcpy(*msg, offset + (uint8_t*)shr, *length);
> +
>   #ifdef TPMFRONT_PRINT_DEBUG
>      TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
>      for(i = 0; i < *length; ++i) {
> @@ -504,6 +522,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t*
>      return 0;
>   }
>
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
> +{
> +   if (!dev || !dev->page)
> +      return -1;
> +   dev->page->locality = locality;
> +   return 0;
> +}
> +
>   #ifdef HAVE_LIBC
>   #include <errno.h>
>   int tpmfront_open(struct tpmfront_dev* dev)
> diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h
> index 02ccdab..afc9181 100644
> --- a/xen/include/public/io/tpmif.h
> +++ b/xen/include/public/io/tpmif.h
> @@ -1,7 +1,7 @@
>   /******************************************************************************
>    * tpmif.h
>    *
> - * TPM I/O interface for Xen guest OSes.
> + * TPM I/O interface for Xen guest OSes, v2
>    *
>    * Permission is hereby granted, free of charge, to any person obtaining a copy
>    * of this software and associated documentation files (the "Software"), to
> @@ -21,48 +21,23 @@
>    * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>    * DEALINGS IN THE SOFTWARE.
>    *
> - * Copyright (c) 2005, IBM Corporation
> - *
> - * Author: Stefan Berger, stefanb@us.ibm.com
> - * Grant table support: Mahadevan Gomathisankaran
> - *
> - * This code has been derived from tools/libxc/xen/io/netif.h
> - *
> - * Copyright (c) 2003-2004, Keir Fraser
>    */
>
>   #ifndef __XEN_PUBLIC_IO_TPMIF_H__
>   #define __XEN_PUBLIC_IO_TPMIF_H__
>
> -#include "../grant_table.h"
> +struct vtpm_shared_page {
> +    uint16_t length;         /* request/response length in bytes */
>
> -struct tpmif_tx_request {
> -    unsigned long addr;   /* Machine address of packet.   */
> -    grant_ref_t ref;      /* grant table access reference */
> -    uint16_t unused;
> -    uint16_t size;        /* Packet size in bytes.        */
> -};
> -typedef struct tpmif_tx_request tpmif_tx_request_t;
> -
> -/*
> - * The TPMIF_TX_RING_SIZE defines the number of pages the
> - * front-end and backend can exchange (= size of array).
> - */
> -typedef uint32_t TPMIF_RING_IDX;
> -
> -#define TPMIF_TX_RING_SIZE 1
> -
> -/* This structure must fit in a memory page. */
> -
> -struct tpmif_ring {
> -    struct tpmif_tx_request req;
> -};
> -typedef struct tpmif_ring tpmif_ring_t;
> +    uint8_t state;           /* 0 - response ready / idle
> +                              * 1 - request ready / working */
> +    uint8_t locality;        /* for the current request */
> +    uint8_t padding[3];
>
> -struct tpmif_tx_interface {
> -    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
> +    uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
> +    uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
>   };
> -typedef struct tpmif_tx_interface tpmif_tx_interface_t;
> +typedef struct vtpm_shared_page vtpm_shared_page_t;
>
>   #endif
>
> --
> 1.7.11.7
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH] stubdom/vtpm: make state save operation atomic
  2012-11-27 22:16                       ` [PATCH] stubdom/vtpm: make state save operation atomic Daniel De Graaf
@ 2012-11-29 18:07                         ` Matthew Fioravante
  2012-11-29 20:24                           ` Daniel De Graaf
  0 siblings, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-29 18:07 UTC (permalink / raw)
  To: Daniel De Graaf
  Cc: samuel.thibault@ens-lyon.org, Ian.Campbell@citrix.com,
	xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 7176 bytes --]
On 11/27/2012 05:16 PM, Daniel De Graaf wrote:
> This changes the save format of the vtpm stubdom to include two copies
> of the saved data: one active, and one inactive. When saving the state,
> data is written to the inactive slot before updating the key and hash
> saved with the TPM Manager, which determines the active slot when the
> vTPM starts up.
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   stubdom/vtpm/vtpmblk.c | 66 +++++++++++++++++++++++++++++++++++++++++---------
>   1 file changed, 54 insertions(+), 12 deletions(-)
>
> diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c
> index b343bd8..f988606 100644
> --- a/stubdom/vtpm/vtpmblk.c
> +++ b/stubdom/vtpm/vtpmblk.c
> @@ -23,6 +23,8 @@
>   
>   /*Encryption key and block sizes */
>   #define BLKSZ 16
> +/* Maximum size of one saved-state slot */
> +#define SLOT_SIZE 32768
Instead of statically defining a slot size and stressing over whether or 
not it may be too small, why not make it half the size of the disk 
image? You can retrieve the disk size by doing fstat(blkfront_fd).
>   
>   static struct blkfront_dev* blkdev = NULL;
>   static int blkfront_fd = -1;
> @@ -59,15 +61,20 @@ void shutdown_vtpmblk(void)
>      blkdev = NULL;
>   }
>   
> -int write_vtpmblk_raw(uint8_t *data, size_t data_length)
> +static int write_vtpmblk_raw(uint8_t *data, size_t data_length, int slot)
>   {
>      int rc;
>      uint32_t lenbuf;
>      debug("Begin Write data=%p len=%u", data, data_length);
Should add which slot were writing to and possibly the disk offset as 
well to the debug print
>   
> +   if (data_length > SLOT_SIZE - 4) {
> +      error("write(data) cannot fit in data slot (%d). Increase SLOT_SIZE.", data_length);
> +      return -1;
> +   }
> +
>      lenbuf = cpu_to_be32((uint32_t)data_length);
>   
> -   lseek(blkfront_fd, 0, SEEK_SET);
> +   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
>      if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
>         error("write(length) failed! error was %s", strerror(errno));
>         return -1;
> @@ -82,12 +89,12 @@ int write_vtpmblk_raw(uint8_t *data, size_t data_length)
>      return 0;
>   }
>   
> -int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
> +static int read_vtpmblk_raw(uint8_t **data, size_t *data_length, int slot)
>   {
>      int rc;
>      uint32_t lenbuf;
>   
> -   lseek(blkfront_fd, 0, SEEK_SET);
> +   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
>      if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
>         error("read(length) failed! error was %s", strerror(errno));
>         return -1;
> @@ -97,6 +104,10 @@ int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
>         error("read 0 data_length for NVM");
>         return -1;
>      }
> +   if(*data_length > SLOT_SIZE - 4) {
> +      error("read invalid data_length for NVM");
> +      return -1;
> +   }
>   
>      *data = tpm_malloc(*data_length);
>      if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
> @@ -221,6 +232,8 @@ egress:
>      return rc;
>   }
>   
> +static int active_slot = -1;
I think we should initialize to 0 or 1 because -1 is an invalid state.
For a new vtpm, read_vtpmblk() will fail and I think this is what happens:
read_vtpmblk()
try_fetch_key_from_manager() -> fails
goto abort_egress
active_slot = -1 (you have this below)
Then later
write_vtpmblk()
active_slot = !active_slot (!-1 = 0)
The last line happens to work correctly but I don't think its very 
clear. I think we should initialize to 1 and set it to 1 if 
read_vtpmblk() fails.
Also a minor nitpick, the name is active_slot, but what it really is is 
the last_slot_written_to because everytime you write you change it first.
> +
>   int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
>      int rc;
>      uint8_t* cipher = NULL;
> @@ -228,12 +241,15 @@ int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_
>      uint8_t hashkey[HASHKEYSZ];
>      uint8_t* symkey = hashkey + HASHSZ;
>   
> +   /* Switch to the other slot */
> +   active_slot = !active_slot;
> +
>      /* 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))) {
> +   if((rc = write_vtpmblk_raw(cipher, cipher_len, active_slot))) {
>         goto abort_egress;
>      }
>      /* Get sha1 hash of data */
> @@ -256,7 +272,8 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>      size_t cipher_len = 0;
>      size_t keysize;
>      uint8_t* hashkey = NULL;
> -   uint8_t hash[HASHSZ];
> +   uint8_t hash0[HASHSZ];
> +   uint8_t hash1[HASHSZ];
>      uint8_t* symkey;
>   
>      /* Retreive the hash and the key from the manager */
> @@ -270,14 +287,32 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>      }
>      symkey = hashkey + HASHSZ;
>   
> -   /* Read from disk now */
> -   if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
> +   active_slot = 0;
> +   /* Read slot 0 from disk now */
> +   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 0))) {
> +      goto abort_egress;
> +   }
> +
> +   /* Compute the hash of the cipher text and compare */
> +   sha1(cipher, cipher_len, hash0);
> +   if(!memcmp(hash0, hashkey, HASHSZ))
> +      goto valid;
> +
> +   free(cipher);
> +   cipher = NULL;
> +
> +   active_slot = 1;
> +   /* Read slot 1 from disk now */
> +   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 1))) {
>         goto abort_egress;
>      }
>   
>      /* Compute the hash of the cipher text and compare */
> -   sha1(cipher, cipher_len, hash);
> -   if(memcmp(hash, hashkey, HASHSZ)) {
> +   sha1(cipher, cipher_len, hash1);
> +   if(!memcmp(hash1, hashkey, HASHSZ))
> +      goto valid;
> +
> +   {
>         int i;
>         error("NVM Storage Checksum failed!");
>         printf("Expected: ");
> @@ -285,14 +320,20 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>   	 printf("%02hhX ", hashkey[i]);
>         }
>         printf("\n");
> -      printf("Actual:   ");
> +      printf("Slot 0:   ");
> +      for(i = 0; i < HASHSZ; ++i) {
> +	 printf("%02hhX ", hash0[i]);
> +      }
> +      printf("\n");
> +      printf("Slot 1:   ");
>         for(i = 0; i < HASHSZ; ++i) {
> -	 printf("%02hhX ", hash[i]);
> +	 printf("%02hhX ", hash1[i]);
>         }
>         printf("\n");
>         rc = -1;
>         goto abort_egress;
>      }
> +valid:
>   
>      /* Decrypt the blob */
>      if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
> @@ -300,6 +341,7 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>      }
>      goto egress;
>   abort_egress:
> +   active_slot = -1;
See my comment above
>   egress:
>      free(cipher);
>      free(hashkey);
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  2012-11-27 15:14     ` [PATCH 2/4] stubdom/vtpm: Add reconfiguration support Daniel De Graaf
  2012-11-27 16:44       ` Samuel Thibault
@ 2012-11-29 18:53       ` Matthew Fioravante
  2012-11-29 19:28         ` Daniel De Graaf
  2012-11-30  9:59         ` Ian Campbell
  1 sibling, 2 replies; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-29 18:53 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 5692 bytes --]
The purpose of this is to allow 2 entities in the same vm to use tpm 
drivers, pv_grub and the linux guest. The Xenbus Reconfigure states are 
new to me. Is this intended behavior in line with the original purpose 
of the Reconfigure states or are we hijacking them to do something not 
in the original xen front/back driver spec?
It looks like pv-grub just shuts down blkfront and the others without 
any reconfigure magic. Given that vtpm-stubdom will no longer 
automatically shutdown with your later patch, is there any reason we 
cannot just do the same here?
On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
> Allow the vtpm device to be disconnected and reconnected so that a
> bootloader (like pv-grub) can submit measurements and return the vtpm
> device to its initial state before booting the target kernel.
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   extras/mini-os/include/tpmfront.h |  2 +-
>   extras/mini-os/lib/sys.c          |  2 +-
>   extras/mini-os/tpmback.c          |  5 +++++
>   extras/mini-os/tpmfront.c         | 15 +++++++++------
>   stubdom/vtpm/vtpm.c               |  2 +-
>   5 files changed, 17 insertions(+), 9 deletions(-)
>
> diff --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
> index a0c7c4d..913faa4 100644
> --- a/extras/mini-os/include/tpmfront.h
> +++ b/extras/mini-os/include/tpmfront.h
> @@ -61,7 +61,7 @@ struct tpmfront_dev {
>   /*Initialize frontend */
>   struct tpmfront_dev* init_tpmfront(const char* nodename);
>   /*Shutdown frontend */
> -void shutdown_tpmfront(struct tpmfront_dev* dev);
> +void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig);
>   
>   /* Send a tpm command to the backend and wait for the response
>    *
> diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
> index 3cc3340..03da4f0 100644
> --- a/extras/mini-os/lib/sys.c
> +++ b/extras/mini-os/lib/sys.c
> @@ -459,7 +459,7 @@ int close(int fd)
>   #endif
>   #ifdef CONFIG_TPMFRONT
>   	case FTYPE_TPMFRONT:
> -            shutdown_tpmfront(files[fd].tpmfront.dev);
> +            shutdown_tpmfront(files[fd].tpmfront.dev, 0);
>   	    files[fd].type = FTYPE_NONE;
>   	    return 0;
>   #endif
> diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
> index 2d31061..ea42235 100644
> --- a/extras/mini-os/tpmback.c
> +++ b/extras/mini-os/tpmback.c
> @@ -664,6 +664,7 @@ static int frontend_changed(tpmif_t* tpmif)
>      switch (state) {
>         case XenbusStateInitialising:
>         case XenbusStateInitialised:
> +      case XenbusStateReconfigured:
>   	 break;
>   
>         case XenbusStateConnected:
> @@ -678,6 +679,10 @@ static int frontend_changed(tpmif_t* tpmif)
>   	 tpmif_change_state(tpmif, XenbusStateClosing);
>   	 break;
>   
> +      case XenbusStateReconfiguring:
> +         disconnect_fe(tpmif);
> +	 break;
> +
>         case XenbusStateUnknown: /* keep it here */
>         case XenbusStateClosed:
>   	 free_tpmif(tpmif);
> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
> index c1cbab3..b725ba0 100644
> --- a/extras/mini-os/tpmfront.c
> +++ b/extras/mini-os/tpmfront.c
> @@ -344,10 +344,10 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>      return dev;
>   
>   error:
> -   shutdown_tpmfront(dev);
> +   shutdown_tpmfront(dev, 0);
>      return NULL;
>   }
> -void shutdown_tpmfront(struct tpmfront_dev* dev)
> +void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig)
It might be cleaner to create a new function like reconfigure_tpmfront() 
or something like that instead of adding an option to shutdown_tpmfront().
>   {
>      char* err;
>      char path[512];
> @@ -357,8 +357,7 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>      TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
>      /* disconnect */
>      if(dev->state == XenbusStateConnected) {
> -      dev->state = XenbusStateClosing;
> -      //FIXME: Transaction for this?
> +      dev->state = for_reconfig ? XenbusStateReconfiguring : XenbusStateClosing;
>         /* Tell backend we are closing */
>         if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
>   	 free(err);
> @@ -374,15 +373,19 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>   	 free(err);
>         }
>   
> +      if (for_reconfig)
> +         wait_for_backend_state_changed(dev, XenbusStateReconfigured);
> +
>         /* Tell backend we are closed */
> -      dev->state = XenbusStateClosed;
> +      dev->state = for_reconfig ? XenbusStateInitialising : XenbusStateClosed;
>         if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
>   	 TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
>   	 free(err);
>         }
>   
>         /* Wait for the backend to close and unmap shared pages, ignore any errors */
> -      wait_for_backend_state_changed(dev, XenbusStateClosed);
> +      if (!for_reconfig)
> +         wait_for_backend_state_changed(dev, XenbusStateClosed);
>   
>         /* Close event channel and unmap shared page */
>         mask_evtchn(dev->evtchn);
> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
> index 71aef78..c33e078 100644
> --- a/stubdom/vtpm/vtpm.c
> +++ b/stubdom/vtpm/vtpm.c
> @@ -394,7 +394,7 @@ abort_postvtpmblk:
>   abort_postrng:
>   
>      /* Close devices */
> -   shutdown_tpmfront(tpmfront_dev);
> +   shutdown_tpmfront(tpmfront_dev, 0);
>   abort_posttpmfront:
>      shutdown_tpmback();
>   
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-27 15:14     ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Daniel De Graaf
  2012-11-27 16:42       ` Samuel Thibault
  2012-11-27 18:19       ` Matthew Fioravante
@ 2012-11-29 19:09       ` Matthew Fioravante
  2012-11-29 19:20         ` Daniel De Graaf
  2 siblings, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-29 19:09 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 6005 bytes --]
Looks good. I'm actually kind of surprised that the emulator doesn't provide
an interface to set the requested locality.
Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
> The vTPM protocol now contains a field allowing the locality of a
> command to be specified; pass this to the TPM when processing a packet.
> This also enables a single vTPM to provide multiple tpmback interfaces
> so that several closely related domains can share a vTPM (for example, a
> qemu device stubdom and its target domain).
>
> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
>   stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>   stubdom/vtpm/vtpm.c        | 16 +++---------
>   2 files changed, 59 insertions(+), 18 deletions(-)
>
> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
> index b84eff1..31ace1a 100644
> --- a/stubdom/tpmemu-0.7.4.patch
> +++ b/stubdom/tpmemu-0.7.4.patch
> @@ -1,9 +1,60 @@
> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c	2012-04-27 10:55:46.581963398 -0400
> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c	2012-04-27 10:56:02.193034152 -0400
> -@@ -249,7 +249,7 @@
> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
> +index 60bbb90..f8f7f0f 100644
> +--- a/tpm/tpm_capability.c
> ++++ b/tpm/tpm_capability.c
> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
> +                              UINT32 setValueSize, BOOL ownerAuth,
> +                              BOOL deactivated, BOOL disabled)
> + {
> ++  if (tpmData.stany.flags.localityModifier != 8)
> ++    return TPM_BAD_PARAMETER;
> +   /* set the capability area with the specified data, on failure
> +      deactivate the TPM */
> +   switch (subCap) {
> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
> +index 288d1ce..9e1cfb4 100644
> +--- a/tpm/tpm_cmd_handler.c
> ++++ b/tpm/tpm_cmd_handler.c
> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
> +   tpm_extern_release();
> + }
> +
> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
> + {
> +   TPM_REQUEST req;
> +   TPM_RESPONSE rsp;
> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
> +   UINT32 len;
> +   BOOL free_out;
> +
> +-  debug("tpm_handle_command()");
> ++  debug("tpm_handle_command(%d)", locality);
> ++  if (locality != -1)
> ++    tpmData.stany.flags.localityModifier = locality;
> +
> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
> +index eed749e..4c228bd 100644
> +--- a/tpm/tpm_emulator.h
> ++++ b/tpm/tpm_emulator.h
> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
> +  * its usage. In case of an error, all internally allocated memory
> +  * is released and the the state of out and out_size is unspecified.
> +  */
> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
> +
> + #endif /* _TPM_EMULATOR_H_ */
> +
> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
> +index aabe6c3..440a01b 100644
> +--- a/tpm/tpm_emulator_extern.c
> ++++ b/tpm/tpm_emulator_extern.c
> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>    #else /* TPM_NO_EXTERN */
> -
> +
>    int (*tpm_extern_init)(void)                                      = NULL;
>   -int (*tpm_extern_release)(void)                                   = NULL;
>   +void (*tpm_extern_release)(void)                                   = NULL;
> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
> index c33e078..dcfc3b9 100644
> --- a/stubdom/vtpm/vtpm.c
> +++ b/stubdom/vtpm/vtpm.c
> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>   
>   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");
> @@ -162,15 +160,7 @@ static void main_loop(void) {
>         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);
> +   tpmcmd = tpmback_req_any();
>      while(tpmcmd) {
>         /* Handle the request */
>         if(tpmcmd->req_len) {
> @@ -183,7 +173,7 @@ static void main_loop(void) {
>            }
>            /* If not disabled, do the command */
>            else {
> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>                  error("tpm_handle_command() failed");
>                  create_error_response(tpmcmd, TPM_FAIL);
>               }
> @@ -194,7 +184,7 @@ static void main_loop(void) {
>         tpmback_resp(tpmcmd);
>   
>         /* Wait for the next request */
> -      tpmcmd = tpmback_req(domid, handle);
> +      tpmcmd = tpmback_req_any();
>   
>      }
>   
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality
  2012-11-29 19:09       ` Matthew Fioravante
@ 2012-11-29 19:20         ` Daniel De Graaf
  0 siblings, 0 replies; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-29 19:20 UTC (permalink / raw)
  To: Matthew Fioravante; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/29/2012 02:09 PM, Matthew Fioravante wrote:
> Looks good. I'm actually kind of surprised that the emulator doesn't provide
> an interface to set the requested locality.
It does; however, it's a rather bad interface: you can send a vendor-specific
command to change the entire STANY_FLAGS data structure, which contains the
locality field along with some others that really shouldn't be changed. This
patch restricts that vendor-specific command interface to locality 8, which
can itself be restricted or unavailable once locality restrictions are
implemented. The number 8 was chosen because it's not usable as a quoting
locality since (1<<8) won't fit in uint8_t.
 
> Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
> 
> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>> The vTPM protocol now contains a field allowing the locality of a
>> command to be specified; pass this to the TPM when processing a packet.
>> This also enables a single vTPM to provide multiple tpmback interfaces
>> so that several closely related domains can share a vTPM (for example, a
>> qemu device stubdom and its target domain).
>>
>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>> ---
>>   stubdom/tpmemu-0.7.4.patch | 61 ++++++++++++++++++++++++++++++++++++++++++----
>>   stubdom/vtpm/vtpm.c        | 16 +++---------
>>   2 files changed, 59 insertions(+), 18 deletions(-)
>>
>> diff --git a/stubdom/tpmemu-0.7.4.patch b/stubdom/tpmemu-0.7.4.patch
>> index b84eff1..31ace1a 100644
>> --- a/stubdom/tpmemu-0.7.4.patch
>> +++ b/stubdom/tpmemu-0.7.4.patch
>> @@ -1,9 +1,60 @@
>> -diff -Naur tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c tpm_emulator-x86_64/tpm/tpm_emulator_extern.c
>> ---- tpm_emulator-x86_64-back/tpm/tpm_emulator_extern.c    2012-04-27 10:55:46.581963398 -0400
>> -+++ tpm_emulator-x86_64/tpm/tpm_emulator_extern.c    2012-04-27 10:56:02.193034152 -0400
>> -@@ -249,7 +249,7 @@
>> +diff --git a/tpm/tpm_capability.c b/tpm/tpm_capability.c
>> +index 60bbb90..f8f7f0f 100644
>> +--- a/tpm/tpm_capability.c
>> ++++ b/tpm/tpm_capability.c
>> +@@ -949,6 +949,8 @@ static TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,
>> +                              UINT32 setValueSize, BOOL ownerAuth,
>> +                              BOOL deactivated, BOOL disabled)
>> + {
>> ++  if (tpmData.stany.flags.localityModifier != 8)
>> ++    return TPM_BAD_PARAMETER;
>> +   /* set the capability area with the specified data, on failure
>> +      deactivate the TPM */
>> +   switch (subCap) {
>> +diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
>> +index 288d1ce..9e1cfb4 100644
>> +--- a/tpm/tpm_cmd_handler.c
>> ++++ b/tpm/tpm_cmd_handler.c
>> +@@ -4132,7 +4132,7 @@ void tpm_emulator_shutdown()
>> +   tpm_extern_release();
>> + }
>> +
>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)
>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality)
>> + {
>> +   TPM_REQUEST req;
>> +   TPM_RESPONSE rsp;
>> +@@ -4140,7 +4140,9 @@ int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint3
>> +   UINT32 len;
>> +   BOOL free_out;
>> +
>> +-  debug("tpm_handle_command()");
>> ++  debug("tpm_handle_command(%d)", locality);
>> ++  if (locality != -1)
>> ++    tpmData.stany.flags.localityModifier = locality;
>> +
>> +   /* we need the whole packet at once, otherwise unmarshalling will fail */
>> +   if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {
>> +diff --git a/tpm/tpm_emulator.h b/tpm/tpm_emulator.h
>> +index eed749e..4c228bd 100644
>> +--- a/tpm/tpm_emulator.h
>> ++++ b/tpm/tpm_emulator.h
>> +@@ -59,7 +59,7 @@ void tpm_emulator_shutdown(void);
>> +  * its usage. In case of an error, all internally allocated memory
>> +  * is released and the the state of out and out_size is unspecified.
>> +  */
>> +-int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);
>> ++int tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size, int locality);
>> +
>> + #endif /* _TPM_EMULATOR_H_ */
>> +
>> +diff --git a/tpm/tpm_emulator_extern.c b/tpm/tpm_emulator_extern.c
>> +index aabe6c3..440a01b 100644
>> +--- a/tpm/tpm_emulator_extern.c
>> ++++ b/tpm/tpm_emulator_extern.c
>> +@@ -249,7 +249,7 @@ int (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_fr
>>    #else /* TPM_NO_EXTERN */
>> -
>> +
>>    int (*tpm_extern_init)(void)                                      = NULL;
>>   -int (*tpm_extern_release)(void)                                   = NULL;
>>   +void (*tpm_extern_release)(void)                                   = NULL;
>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>> index c33e078..dcfc3b9 100644
>> --- a/stubdom/vtpm/vtpm.c
>> +++ b/stubdom/vtpm/vtpm.c
>> @@ -141,8 +141,6 @@ int check_ordinal(tpmcmd_t* tpmcmd) {
>>     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");
>> @@ -162,15 +160,7 @@ static void main_loop(void) {
>>         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);
>> +   tpmcmd = tpmback_req_any();
>>      while(tpmcmd) {
>>         /* Handle the request */
>>         if(tpmcmd->req_len) {
>> @@ -183,7 +173,7 @@ static void main_loop(void) {
>>            }
>>            /* If not disabled, do the command */
>>            else {
>> -            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
>> +            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &tpmcmd->resp, &tpmcmd->resp_len, tpmcmd->locality)) != 0) {
>>                  error("tpm_handle_command() failed");
>>                  create_error_response(tpmcmd, TPM_FAIL);
>>               }
>> @@ -194,7 +184,7 @@ static void main_loop(void) {
>>         tpmback_resp(tpmcmd);
>>           /* Wait for the next request */
>> -      tpmcmd = tpmback_req(domid, handle);
>> +      tpmcmd = tpmback_req_any();
>>        }
>>   
> 
> 
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  2012-11-29 18:53       ` Matthew Fioravante
@ 2012-11-29 19:28         ` Daniel De Graaf
  2012-11-29 19:47           ` Matthew Fioravante
  2012-11-30  9:59         ` Ian Campbell
  1 sibling, 1 reply; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-29 19:28 UTC (permalink / raw)
  To: Matthew Fioravante; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
On 11/29/2012 01:53 PM, Matthew Fioravante wrote:
> The purpose of this is to allow 2 entities in the same vm to use tpm drivers, pv_grub and the linux guest. The Xenbus Reconfigure states are new to me. Is this intended behavior in line with the original purpose of the Reconfigure states or are we hijacking them to do something not in the original xen front/back driver spec?
> 
> It looks like pv-grub just shuts down blkfront and the others without any reconfigure magic. Given that vtpm-stubdom will no longer automatically shutdown with your later patch, is there any reason we cannot just do the same here?
The vtpm backend in mini-os cleans up after itself destructively when it is
closed: it removes xenstore entries and frees the data structures, and so
requires the xenstore directory to be re-created. I originally wanted to keep
the shutdown semantics the same (to preserve the vtpm auto-shutdown), although
that's not reflected in this patch queue.
I think the correct method here is to make the backend act like it does for the
reconfigure on close, and trigger free only when the xenstore entry vanishes.
 
> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>> Allow the vtpm device to be disconnected and reconnected so that a
>> bootloader (like pv-grub) can submit measurements and return the vtpm
>> device to its initial state before booting the target kernel.
>>
>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>> ---
>>   extras/mini-os/include/tpmfront.h |  2 +-
>>   extras/mini-os/lib/sys.c          |  2 +-
>>   extras/mini-os/tpmback.c          |  5 +++++
>>   extras/mini-os/tpmfront.c         | 15 +++++++++------
>>   stubdom/vtpm/vtpm.c               |  2 +-
>>   5 files changed, 17 insertions(+), 9 deletions(-)
>>
>> diff --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
>> index a0c7c4d..913faa4 100644
>> --- a/extras/mini-os/include/tpmfront.h
>> +++ b/extras/mini-os/include/tpmfront.h
>> @@ -61,7 +61,7 @@ struct tpmfront_dev {
>>   /*Initialize frontend */
>>   struct tpmfront_dev* init_tpmfront(const char* nodename);
>>   /*Shutdown frontend */
>> -void shutdown_tpmfront(struct tpmfront_dev* dev);
>> +void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig);
>>     /* Send a tpm command to the backend and wait for the response
>>    *
>> diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
>> index 3cc3340..03da4f0 100644
>> --- a/extras/mini-os/lib/sys.c
>> +++ b/extras/mini-os/lib/sys.c
>> @@ -459,7 +459,7 @@ int close(int fd)
>>   #endif
>>   #ifdef CONFIG_TPMFRONT
>>       case FTYPE_TPMFRONT:
>> -            shutdown_tpmfront(files[fd].tpmfront.dev);
>> +            shutdown_tpmfront(files[fd].tpmfront.dev, 0);
>>           files[fd].type = FTYPE_NONE;
>>           return 0;
>>   #endif
>> diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
>> index 2d31061..ea42235 100644
>> --- a/extras/mini-os/tpmback.c
>> +++ b/extras/mini-os/tpmback.c
>> @@ -664,6 +664,7 @@ static int frontend_changed(tpmif_t* tpmif)
>>      switch (state) {
>>         case XenbusStateInitialising:
>>         case XenbusStateInitialised:
>> +      case XenbusStateReconfigured:
>>        break;
>>           case XenbusStateConnected:
>> @@ -678,6 +679,10 @@ static int frontend_changed(tpmif_t* tpmif)
>>        tpmif_change_state(tpmif, XenbusStateClosing);
>>        break;
>>   +      case XenbusStateReconfiguring:
>> +         disconnect_fe(tpmif);
>> +     break;
>> +
>>         case XenbusStateUnknown: /* keep it here */
>>         case XenbusStateClosed:
>>        free_tpmif(tpmif);
>> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
>> index c1cbab3..b725ba0 100644
>> --- a/extras/mini-os/tpmfront.c
>> +++ b/extras/mini-os/tpmfront.c
>> @@ -344,10 +344,10 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>>      return dev;
>>     error:
>> -   shutdown_tpmfront(dev);
>> +   shutdown_tpmfront(dev, 0);
>>      return NULL;
>>   }
>> -void shutdown_tpmfront(struct tpmfront_dev* dev)
>> +void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig)
> It might be cleaner to create a new function like reconfigure_tpmfront() or something like that instead of adding an option to shutdown_tpmfront().
>>   {
>>      char* err;
>>      char path[512];
>> @@ -357,8 +357,7 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>>      TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
>>      /* disconnect */
>>      if(dev->state == XenbusStateConnected) {
>> -      dev->state = XenbusStateClosing;
>> -      //FIXME: Transaction for this?
>> +      dev->state = for_reconfig ? XenbusStateReconfiguring : XenbusStateClosing;
>>         /* Tell backend we are closing */
>>         if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
>>        free(err);
>> @@ -374,15 +373,19 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>>        free(err);
>>         }
>>   +      if (for_reconfig)
>> +         wait_for_backend_state_changed(dev, XenbusStateReconfigured);
>> +
>>         /* Tell backend we are closed */
>> -      dev->state = XenbusStateClosed;
>> +      dev->state = for_reconfig ? XenbusStateInitialising : XenbusStateClosed;
>>         if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
>>        TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
>>        free(err);
>>         }
>>           /* Wait for the backend to close and unmap shared pages, ignore any errors */
>> -      wait_for_backend_state_changed(dev, XenbusStateClosed);
>> +      if (!for_reconfig)
>> +         wait_for_backend_state_changed(dev, XenbusStateClosed);
>>           /* Close event channel and unmap shared page */
>>         mask_evtchn(dev->evtchn);
>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>> index 71aef78..c33e078 100644
>> --- a/stubdom/vtpm/vtpm.c
>> +++ b/stubdom/vtpm/vtpm.c
>> @@ -394,7 +394,7 @@ abort_postvtpmblk:
>>   abort_postrng:
>>        /* Close devices */
>> -   shutdown_tpmfront(tpmfront_dev);
>> +   shutdown_tpmfront(tpmfront_dev, 0);
>>   abort_posttpmfront:
>>      shutdown_tpmback();
>>   
> 
> 
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  2012-11-29 19:28         ` Daniel De Graaf
@ 2012-11-29 19:47           ` Matthew Fioravante
  2012-11-29 21:37             ` Samuel Thibault
  0 siblings, 1 reply; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-29 19:47 UTC (permalink / raw)
  To: Daniel De Graaf; +Cc: Ian.Campbell@citrix.com, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 6981 bytes --]
On 11/29/2012 02:28 PM, Daniel De Graaf wrote:
> On 11/29/2012 01:53 PM, Matthew Fioravante wrote:
>> The purpose of this is to allow 2 entities in the same vm to use tpm drivers, pv_grub and the linux guest. The Xenbus Reconfigure states are new to me. Is this intended behavior in line with the original purpose of the Reconfigure states or are we hijacking them to do something not in the original xen front/back driver spec?
>>
>> It looks like pv-grub just shuts down blkfront and the others without any reconfigure magic. Given that vtpm-stubdom will no longer automatically shutdown with your later patch, is there any reason we cannot just do the same here?
> The vtpm backend in mini-os cleans up after itself destructively when it is
> closed: it removes xenstore entries and frees the data structures, and so
> requires the xenstore directory to be re-created. I originally wanted to keep
> the shutdown semantics the same (to preserve the vtpm auto-shutdown), although
> that's not reflected in this patch queue.
>
> I think the correct method here is to make the backend act like it does for the
> reconfigure on close, and trigger free only when the xenstore entry vanishes.
A cursory look at blkback in linux and it looks like the backend driver 
doesn't tear down the xenstore entries at all. I think its supposed to 
be the job of libxl to do that no? So I think I agree with you that what 
we really want is to change the backend to leave xenstore alone and 
maintain enough state so that the device can reconnect later.
>   
>> On 11/27/2012 10:14 AM, Daniel De Graaf wrote:
>>> Allow the vtpm device to be disconnected and reconnected so that a
>>> bootloader (like pv-grub) can submit measurements and return the vtpm
>>> device to its initial state before booting the target kernel.
>>>
>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>> ---
>>>    extras/mini-os/include/tpmfront.h |  2 +-
>>>    extras/mini-os/lib/sys.c          |  2 +-
>>>    extras/mini-os/tpmback.c          |  5 +++++
>>>    extras/mini-os/tpmfront.c         | 15 +++++++++------
>>>    stubdom/vtpm/vtpm.c               |  2 +-
>>>    5 files changed, 17 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
>>> index a0c7c4d..913faa4 100644
>>> --- a/extras/mini-os/include/tpmfront.h
>>> +++ b/extras/mini-os/include/tpmfront.h
>>> @@ -61,7 +61,7 @@ struct tpmfront_dev {
>>>    /*Initialize frontend */
>>>    struct tpmfront_dev* init_tpmfront(const char* nodename);
>>>    /*Shutdown frontend */
>>> -void shutdown_tpmfront(struct tpmfront_dev* dev);
>>> +void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig);
>>>      /* Send a tpm command to the backend and wait for the response
>>>     *
>>> diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
>>> index 3cc3340..03da4f0 100644
>>> --- a/extras/mini-os/lib/sys.c
>>> +++ b/extras/mini-os/lib/sys.c
>>> @@ -459,7 +459,7 @@ int close(int fd)
>>>    #endif
>>>    #ifdef CONFIG_TPMFRONT
>>>        case FTYPE_TPMFRONT:
>>> -            shutdown_tpmfront(files[fd].tpmfront.dev);
>>> +            shutdown_tpmfront(files[fd].tpmfront.dev, 0);
>>>            files[fd].type = FTYPE_NONE;
>>>            return 0;
>>>    #endif
>>> diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
>>> index 2d31061..ea42235 100644
>>> --- a/extras/mini-os/tpmback.c
>>> +++ b/extras/mini-os/tpmback.c
>>> @@ -664,6 +664,7 @@ static int frontend_changed(tpmif_t* tpmif)
>>>       switch (state) {
>>>          case XenbusStateInitialising:
>>>          case XenbusStateInitialised:
>>> +      case XenbusStateReconfigured:
>>>         break;
>>>            case XenbusStateConnected:
>>> @@ -678,6 +679,10 @@ static int frontend_changed(tpmif_t* tpmif)
>>>         tpmif_change_state(tpmif, XenbusStateClosing);
>>>         break;
>>>    +      case XenbusStateReconfiguring:
>>> +         disconnect_fe(tpmif);
>>> +     break;
>>> +
>>>          case XenbusStateUnknown: /* keep it here */
>>>          case XenbusStateClosed:
>>>         free_tpmif(tpmif);
>>> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
>>> index c1cbab3..b725ba0 100644
>>> --- a/extras/mini-os/tpmfront.c
>>> +++ b/extras/mini-os/tpmfront.c
>>> @@ -344,10 +344,10 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>>>       return dev;
>>>      error:
>>> -   shutdown_tpmfront(dev);
>>> +   shutdown_tpmfront(dev, 0);
>>>       return NULL;
>>>    }
>>> -void shutdown_tpmfront(struct tpmfront_dev* dev)
>>> +void shutdown_tpmfront(struct tpmfront_dev* dev, int for_reconfig)
>> It might be cleaner to create a new function like reconfigure_tpmfront() or something like that instead of adding an option to shutdown_tpmfront().
>>>    {
>>>       char* err;
>>>       char path[512];
>>> @@ -357,8 +357,7 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>>>       TPMFRONT_LOG("Shutting down tpmfront%s\n", for_reconfig ? " for reconfigure" : "");
>>>       /* disconnect */
>>>       if(dev->state == XenbusStateConnected) {
>>> -      dev->state = XenbusStateClosing;
>>> -      //FIXME: Transaction for this?
>>> +      dev->state = for_reconfig ? XenbusStateReconfiguring : XenbusStateClosing;
>>>          /* Tell backend we are closing */
>>>          if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
>>>         free(err);
>>> @@ -374,15 +373,19 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>>>         free(err);
>>>          }
>>>    +      if (for_reconfig)
>>> +         wait_for_backend_state_changed(dev, XenbusStateReconfigured);
>>> +
>>>          /* Tell backend we are closed */
>>> -      dev->state = XenbusStateClosed;
>>> +      dev->state = for_reconfig ? XenbusStateInitialising : XenbusStateClosed;
>>>          if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
>>>         TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
>>>         free(err);
>>>          }
>>>            /* Wait for the backend to close and unmap shared pages, ignore any errors */
>>> -      wait_for_backend_state_changed(dev, XenbusStateClosed);
>>> +      if (!for_reconfig)
>>> +         wait_for_backend_state_changed(dev, XenbusStateClosed);
>>>            /* Close event channel and unmap shared page */
>>>          mask_evtchn(dev->evtchn);
>>> diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
>>> index 71aef78..c33e078 100644
>>> --- a/stubdom/vtpm/vtpm.c
>>> +++ b/stubdom/vtpm/vtpm.c
>>> @@ -394,7 +394,7 @@ abort_postvtpmblk:
>>>    abort_postrng:
>>>         /* Close devices */
>>> -   shutdown_tpmfront(tpmfront_dev);
>>> +   shutdown_tpmfront(tpmfront_dev, 0);
>>>    abort_posttpmfront:
>>>       shutdown_tpmback();
>>>    
>>
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH] stubdom/vtpm: make state save operation atomic
  2012-11-29 18:07                         ` Matthew Fioravante
@ 2012-11-29 20:24                           ` Daniel De Graaf
  2012-11-29 20:48                             ` Matthew Fioravante
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel De Graaf @ 2012-11-29 20:24 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: samuel.thibault@ens-lyon.org, Ian.Campbell@citrix.com,
	xen-devel@lists.xen.org
On 11/29/2012 01:07 PM, Matthew Fioravante wrote:
> On 11/27/2012 05:16 PM, Daniel De Graaf wrote:
>> This changes the save format of the vtpm stubdom to include two copies
>> of the saved data: one active, and one inactive. When saving the state,
>> data is written to the inactive slot before updating the key and hash
>> saved with the TPM Manager, which determines the active slot when the
>> vTPM starts up.
>>
>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>> ---
>>   stubdom/vtpm/vtpmblk.c | 66 +++++++++++++++++++++++++++++++++++++++++---------
>>   1 file changed, 54 insertions(+), 12 deletions(-)
>>
>> diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c
>> index b343bd8..f988606 100644
>> --- a/stubdom/vtpm/vtpmblk.c
>> +++ b/stubdom/vtpm/vtpmblk.c
>> @@ -23,6 +23,8 @@
>>     /*Encryption key and block sizes */
>>   #define BLKSZ 16
>> +/* Maximum size of one saved-state slot */
>> +#define SLOT_SIZE 32768
> Instead of statically defining a slot size and stressing over whether or not it may be too small, why not make it half the size of the disk image? You can retrieve the disk size by doing fstat(blkfront_fd).
Ah, I didn't see that information was available in mini-os. Actually, the blkinfo
structure in init_vtpmblk is more convenient, so I'll use that.
>>     static struct blkfront_dev* blkdev = NULL;
>>   static int blkfront_fd = -1;
>> @@ -59,15 +61,20 @@ void shutdown_vtpmblk(void)
>>      blkdev = NULL;
>>   }
>>   -int write_vtpmblk_raw(uint8_t *data, size_t data_length)
>> +static int write_vtpmblk_raw(uint8_t *data, size_t data_length, int slot)
>>   {
>>      int rc;
>>      uint32_t lenbuf;
>>      debug("Begin Write data=%p len=%u", data, data_length);
> Should add which slot were writing to and possibly the disk offset as well to the debug print
A number of debug outputs will be improved with slot info.
>>   +   if (data_length > SLOT_SIZE - 4) {
>> +      error("write(data) cannot fit in data slot (%d). Increase SLOT_SIZE.", data_length);
>> +      return -1;
>> +   }
>> +
>>      lenbuf = cpu_to_be32((uint32_t)data_length);
>>   -   lseek(blkfront_fd, 0, SEEK_SET);
>> +   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
>>      if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
>>         error("write(length) failed! error was %s", strerror(errno));
>>         return -1;
>> @@ -82,12 +89,12 @@ int write_vtpmblk_raw(uint8_t *data, size_t data_length)
>>      return 0;
>>   }
>>   -int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
>> +static int read_vtpmblk_raw(uint8_t **data, size_t *data_length, int slot)
>>   {
>>      int rc;
>>      uint32_t lenbuf;
>>   -   lseek(blkfront_fd, 0, SEEK_SET);
>> +   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
>>      if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
>>         error("read(length) failed! error was %s", strerror(errno));
>>         return -1;
>> @@ -97,6 +104,10 @@ int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
>>         error("read 0 data_length for NVM");
>>         return -1;
>>      }
>> +   if(*data_length > SLOT_SIZE - 4) {
>> +      error("read invalid data_length for NVM");
>> +      return -1;
>> +   }
>>        *data = tpm_malloc(*data_length);
>>      if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
>> @@ -221,6 +232,8 @@ egress:
>>      return rc;
>>   }
>>   +static int active_slot = -1;
> I think we should initialize to 0 or 1 because -1 is an invalid state.
> For a new vtpm, read_vtpmblk() will fail and I think this is what happens:
> read_vtpmblk()
> try_fetch_key_from_manager() -> fails
> goto abort_egress
> active_slot = -1 (you have this below)
Yes, that's intentional. That way, you can tell the difference between slot 1
being active and no slot being active.
 
> Then later
> write_vtpmblk()
> active_slot = !active_slot (!-1 = 0)
> 
> The last line happens to work correctly but I don't think its very clear. I think we should initialize to 1 and set it to 1 if read_vtpmblk() fails.
I think I'll just put a comment at the !active_slot to note that active_slot is
-1 => 0 if no active slots existed.
> Also a minor nitpick, the name is active_slot, but what it really is is the last_slot_written_to because everytime you write you change it first.
That still makes it the active slot: at the point when it's changed, the value is
the new active slot (and we're just working to commit that change to disk).
>> +
>>   int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
>>      int rc;
>>      uint8_t* cipher = NULL;
>> @@ -228,12 +241,15 @@ int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_
>>      uint8_t hashkey[HASHKEYSZ];
>>      uint8_t* symkey = hashkey + HASHSZ;
>>   +   /* Switch to the other slot */
>> +   active_slot = !active_slot;
>> +
>>      /* 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))) {
>> +   if((rc = write_vtpmblk_raw(cipher, cipher_len, active_slot))) {
>>         goto abort_egress;
>>      }
>>      /* Get sha1 hash of data */
>> @@ -256,7 +272,8 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>      size_t cipher_len = 0;
>>      size_t keysize;
>>      uint8_t* hashkey = NULL;
>> -   uint8_t hash[HASHSZ];
>> +   uint8_t hash0[HASHSZ];
>> +   uint8_t hash1[HASHSZ];
>>      uint8_t* symkey;
>>        /* Retreive the hash and the key from the manager */
>> @@ -270,14 +287,32 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>      }
>>      symkey = hashkey + HASHSZ;
>>   -   /* Read from disk now */
>> -   if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
>> +   active_slot = 0;
>> +   /* Read slot 0 from disk now */
>> +   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 0))) {
>> +      goto abort_egress;
>> +   }
>> +
>> +   /* Compute the hash of the cipher text and compare */
>> +   sha1(cipher, cipher_len, hash0);
>> +   if(!memcmp(hash0, hashkey, HASHSZ))
>> +      goto valid;
>> +
>> +   free(cipher);
>> +   cipher = NULL;
>> +
>> +   active_slot = 1;
>> +   /* Read slot 1 from disk now */
>> +   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 1))) {
>>         goto abort_egress;
>>      }
>>        /* Compute the hash of the cipher text and compare */
>> -   sha1(cipher, cipher_len, hash);
>> -   if(memcmp(hash, hashkey, HASHSZ)) {
>> +   sha1(cipher, cipher_len, hash1);
>> +   if(!memcmp(hash1, hashkey, HASHSZ))
>> +      goto valid;
>> +
>> +   {
>>         int i;
>>         error("NVM Storage Checksum failed!");
>>         printf("Expected: ");
>> @@ -285,14 +320,20 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>        printf("%02hhX ", hashkey[i]);
>>         }
>>         printf("\n");
>> -      printf("Actual:   ");
>> +      printf("Slot 0:   ");
>> +      for(i = 0; i < HASHSZ; ++i) {
>> +     printf("%02hhX ", hash0[i]);
>> +      }
>> +      printf("\n");
>> +      printf("Slot 1:   ");
>>         for(i = 0; i < HASHSZ; ++i) {
>> -     printf("%02hhX ", hash[i]);
>> +     printf("%02hhX ", hash1[i]);
>>         }
>>         printf("\n");
>>         rc = -1;
>>         goto abort_egress;
>>      }
>> +valid:
>>        /* Decrypt the blob */
>>      if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
>> @@ -300,6 +341,7 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>      }
>>      goto egress;
>>   abort_egress:
>> +   active_slot = -1;
> See my comment above
>>   egress:
>>      free(cipher);
>>      free(hashkey);
> 
> 
-- 
Daniel De Graaf
National Security Agency
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH] stubdom/vtpm: make state save operation atomic
  2012-11-29 20:24                           ` Daniel De Graaf
@ 2012-11-29 20:48                             ` Matthew Fioravante
  0 siblings, 0 replies; 53+ messages in thread
From: Matthew Fioravante @ 2012-11-29 20:48 UTC (permalink / raw)
  To: Daniel De Graaf
  Cc: samuel.thibault@ens-lyon.org, Ian.Campbell@citrix.com,
	xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 8929 bytes --]
On 11/29/2012 03:24 PM, Daniel De Graaf wrote:
> On 11/29/2012 01:07 PM, Matthew Fioravante wrote:
>> On 11/27/2012 05:16 PM, Daniel De Graaf wrote:
>>> This changes the save format of the vtpm stubdom to include two copies
>>> of the saved data: one active, and one inactive. When saving the state,
>>> data is written to the inactive slot before updating the key and hash
>>> saved with the TPM Manager, which determines the active slot when the
>>> vTPM starts up.
>>>
>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>> ---
>>>    stubdom/vtpm/vtpmblk.c | 66 +++++++++++++++++++++++++++++++++++++++++---------
>>>    1 file changed, 54 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c
>>> index b343bd8..f988606 100644
>>> --- a/stubdom/vtpm/vtpmblk.c
>>> +++ b/stubdom/vtpm/vtpmblk.c
>>> @@ -23,6 +23,8 @@
>>>      /*Encryption key and block sizes */
>>>    #define BLKSZ 16
>>> +/* Maximum size of one saved-state slot */
>>> +#define SLOT_SIZE 32768
>> Instead of statically defining a slot size and stressing over whether or not it may be too small, why not make it half the size of the disk image? You can retrieve the disk size by doing fstat(blkfront_fd).
> Ah, I didn't see that information was available in mini-os. Actually, the blkinfo
> structure in init_vtpmblk is more convenient, so I'll use that.
>
>>>      static struct blkfront_dev* blkdev = NULL;
>>>    static int blkfront_fd = -1;
>>> @@ -59,15 +61,20 @@ void shutdown_vtpmblk(void)
>>>       blkdev = NULL;
>>>    }
>>>    -int write_vtpmblk_raw(uint8_t *data, size_t data_length)
>>> +static int write_vtpmblk_raw(uint8_t *data, size_t data_length, int slot)
>>>    {
>>>       int rc;
>>>       uint32_t lenbuf;
>>>       debug("Begin Write data=%p len=%u", data, data_length);
>> Should add which slot were writing to and possibly the disk offset as well to the debug print
> A number of debug outputs will be improved with slot info.
>
>>>    +   if (data_length > SLOT_SIZE - 4) {
>>> +      error("write(data) cannot fit in data slot (%d). Increase SLOT_SIZE.", data_length);
>>> +      return -1;
>>> +   }
>>> +
>>>       lenbuf = cpu_to_be32((uint32_t)data_length);
>>>    -   lseek(blkfront_fd, 0, SEEK_SET);
>>> +   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
>>>       if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
>>>          error("write(length) failed! error was %s", strerror(errno));
>>>          return -1;
>>> @@ -82,12 +89,12 @@ int write_vtpmblk_raw(uint8_t *data, size_t data_length)
>>>       return 0;
>>>    }
>>>    -int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
>>> +static int read_vtpmblk_raw(uint8_t **data, size_t *data_length, int slot)
>>>    {
>>>       int rc;
>>>       uint32_t lenbuf;
>>>    -   lseek(blkfront_fd, 0, SEEK_SET);
>>> +   lseek(blkfront_fd, slot * SLOT_SIZE, SEEK_SET);
>>>       if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
>>>          error("read(length) failed! error was %s", strerror(errno));
>>>          return -1;
>>> @@ -97,6 +104,10 @@ int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
>>>          error("read 0 data_length for NVM");
>>>          return -1;
>>>       }
>>> +   if(*data_length > SLOT_SIZE - 4) {
>>> +      error("read invalid data_length for NVM");
>>> +      return -1;
>>> +   }
>>>         *data = tpm_malloc(*data_length);
>>>       if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
>>> @@ -221,6 +232,8 @@ egress:
>>>       return rc;
>>>    }
>>>    +static int active_slot = -1;
>> I think we should initialize to 0 or 1 because -1 is an invalid state.
>> For a new vtpm, read_vtpmblk() will fail and I think this is what happens:
>> read_vtpmblk()
>> try_fetch_key_from_manager() -> fails
>> goto abort_egress
>> active_slot = -1 (you have this below)
> Yes, that's intentional. That way, you can tell the difference between slot 1
> being active and no slot being active.
Other than possibly for debugging, do we really care if no slot is 
active? If there is no logical active slot then either slot 0 or 1 is 
valid for the next write.
>   
>> Then later
>> write_vtpmblk()
>> active_slot = !active_slot (!-1 = 0)
>>
>> The last line happens to work correctly but I don't think its very clear. I think we should initialize to 1 and set it to 1 if read_vtpmblk() fails.
> I think I'll just put a comment at the !active_slot to note that active_slot is
> -1 => 0 if no active slots existed.
If we keep the -1, then defiantly a comment is warranted. There should 
be a block comment at active_slot's definition to briefly explain all of 
this, what the valid states of active_slot are (-1, 0, 1), and what they 
mean because at first glance its not intuitive and looks like it could 
be a bug. Another self documenting option would be to use an enum or 
#define INVALID_SLOT -1 if you don't want to write as much comment text.
>
>> Also a minor nitpick, the name is active_slot, but what it really is is the last_slot_written_to because everytime you write you change it first.
> That still makes it the active slot: at the point when it's changed, the value is
> the new active slot (and we're just working to commit that change to disk).
>
>>> +
>>>    int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
>>>       int rc;
>>>       uint8_t* cipher = NULL;
>>> @@ -228,12 +241,15 @@ int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_
>>>       uint8_t hashkey[HASHKEYSZ];
>>>       uint8_t* symkey = hashkey + HASHSZ;
>>>    +   /* Switch to the other slot */
>>> +   active_slot = !active_slot;
>>> +
>>>       /* 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))) {
>>> +   if((rc = write_vtpmblk_raw(cipher, cipher_len, active_slot))) {
>>>          goto abort_egress;
>>>       }
>>>       /* Get sha1 hash of data */
>>> @@ -256,7 +272,8 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>>       size_t cipher_len = 0;
>>>       size_t keysize;
>>>       uint8_t* hashkey = NULL;
>>> -   uint8_t hash[HASHSZ];
>>> +   uint8_t hash0[HASHSZ];
>>> +   uint8_t hash1[HASHSZ];
>>>       uint8_t* symkey;
>>>         /* Retreive the hash and the key from the manager */
>>> @@ -270,14 +287,32 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>>       }
>>>       symkey = hashkey + HASHSZ;
>>>    -   /* Read from disk now */
>>> -   if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
>>> +   active_slot = 0;
>>> +   /* Read slot 0 from disk now */
>>> +   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 0))) {
>>> +      goto abort_egress;
>>> +   }
>>> +
>>> +   /* Compute the hash of the cipher text and compare */
>>> +   sha1(cipher, cipher_len, hash0);
>>> +   if(!memcmp(hash0, hashkey, HASHSZ))
>>> +      goto valid;
>>> +
>>> +   free(cipher);
>>> +   cipher = NULL;
>>> +
>>> +   active_slot = 1;
>>> +   /* Read slot 1 from disk now */
>>> +   if((rc = read_vtpmblk_raw(&cipher, &cipher_len, 1))) {
>>>          goto abort_egress;
>>>       }
>>>         /* Compute the hash of the cipher text and compare */
>>> -   sha1(cipher, cipher_len, hash);
>>> -   if(memcmp(hash, hashkey, HASHSZ)) {
>>> +   sha1(cipher, cipher_len, hash1);
>>> +   if(!memcmp(hash1, hashkey, HASHSZ))
>>> +      goto valid;
>>> +
>>> +   {
>>>          int i;
>>>          error("NVM Storage Checksum failed!");
>>>          printf("Expected: ");
>>> @@ -285,14 +320,20 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>>         printf("%02hhX ", hashkey[i]);
>>>          }
>>>          printf("\n");
>>> -      printf("Actual:   ");
>>> +      printf("Slot 0:   ");
>>> +      for(i = 0; i < HASHSZ; ++i) {
>>> +     printf("%02hhX ", hash0[i]);
>>> +      }
>>> +      printf("\n");
>>> +      printf("Slot 1:   ");
>>>          for(i = 0; i < HASHSZ; ++i) {
>>> -     printf("%02hhX ", hash[i]);
>>> +     printf("%02hhX ", hash1[i]);
>>>          }
>>>          printf("\n");
>>>          rc = -1;
>>>          goto abort_egress;
>>>       }
>>> +valid:
>>>         /* Decrypt the blob */
>>>       if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
>>> @@ -300,6 +341,7 @@ int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data
>>>       }
>>>       goto egress;
>>>    abort_egress:
>>> +   active_slot = -1;
>> See my comment above
>>>    egress:
>>>       free(cipher);
>>>       free(hashkey);
>>
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  2012-11-29 19:47           ` Matthew Fioravante
@ 2012-11-29 21:37             ` Samuel Thibault
  0 siblings, 0 replies; 53+ messages in thread
From: Samuel Thibault @ 2012-11-29 21:37 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Daniel De Graaf, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
Matthew Fioravante, le Thu 29 Nov 2012 14:47:17 -0500, a écrit :
> I think I agree with you that what we really want is to change the
> backend to leave xenstore alone and maintain enough state so that the
> device can reconnect later.
Yes, I believe that's much nicer.
Samuel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 2/4] stubdom/vtpm: Add reconfiguration support
  2012-11-29 18:53       ` Matthew Fioravante
  2012-11-29 19:28         ` Daniel De Graaf
@ 2012-11-30  9:59         ` Ian Campbell
  1 sibling, 0 replies; 53+ messages in thread
From: Ian Campbell @ 2012-11-30  9:59 UTC (permalink / raw)
  To: Matthew Fioravante; +Cc: Daniel De Graaf, xen-devel@lists.xen.org
(can you not top post please)
On Thu, 2012-11-29 at 18:53 +0000, Matthew Fioravante wrote:
> The purpose of this is to allow 2 entities in the same vm to use tpm 
> drivers, pv_grub and the linux guest. The Xenbus Reconfigure states are 
> new to me. Is this intended behavior in line with the original purpose 
> of the Reconfigure states or are we hijacking them to do something not 
> in the original xen front/back driver spec?
I'm not sure there was ever such a thing.
The reconfigure states were originally added by the pcifront/back
drivers which used them to implement device hotplug iirc.
It's looks to me like the use case here is more akin to the "online"
node which the block and net stuff has?
Ian.
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH RFC] stubdom: Change vTPM shared page ABI
  2012-11-28 22:22       ` Matthew Fioravante
  2012-11-29  7:53         ` Ian Campbell
@ 2012-11-30 16:11         ` Konrad Rzeszutek Wilk
  1 sibling, 0 replies; 53+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-11-30 16:11 UTC (permalink / raw)
  To: Matthew Fioravante; +Cc: Daniel De Graaf, Ian Campbell, xen-devel@lists.xen.org
On Wed, Nov 28, 2012 at 05:22:59PM -0500, Matthew Fioravante wrote:
> On 11/28/2012 03:46 PM, Konrad Rzeszutek Wilk wrote:
> >On Fri, Nov 23, 2012 at 11:04:06AM +0000, Ian Campbell wrote:
> >>On Tue, 2012-11-20 at 16:16 +0000, Fioravante, Matthew E. wrote:
> >>>This was something I've been wanting to do for a while so I'm very
> >>>happy you went ahead and fixed it yourself. Once you submit the linux
> >>>version I'll test it on my system.
> >>>
> >>>Acked by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
> >>Do we need to synchronise with anything else (Linux drivers?) or I can I
> >>just throw this into the tree once it is done?
> >>
> >>Are we hanging any existing users of the tpm stuff out to dry? Could we
> >>get a feature-protocol-v2 flag in xenstore so users at least get an
> >>error message from either the front or backend to give a hint why it
> >>isn't working?
> >We could cop out and just name this new driver differently. Then
> >we would not have to deal with the older ones.
> I've already done that with my patch on the linux mailing list. The
> old frontend driver name was tpm_xenu.ko, the new one is
> xen-tpmfront.ko.
I meant the XenBus directory name. It is 'vtpm' - if it was called
'vtpm2' we would avoid the "older" drivers from even seeing this one.
> >
> >>>  void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)  {
> >>>-   tpmif_tx_request_t* tx;
> >>>-   int offset;
> >>>-   int i;
> >>>-   uint32_t domid;
> >>>-   int tocopy;
> >>>+   vtpm_shared_page_t* shr;
> >>>+   unsigned int offset;
> >>>     int flags;
> >>>+#ifdef TPMBACK_PRINT_DEBUG
> >>>+int i;
> >>>+#endif
> >>Dodgy indentation? (I saw a bunch of these)
> >>
> >>>- * Copyright (c) 2005, IBM Corporation
> >>>- *
> >>>- * Author: Stefan Berger, stefanb@us.ibm.com
> >>>- * Grant table support: Mahadevan Gomathisankaran
> >>Did you really remove everything these guys wrote?
> >>
> >>>- * This code has been derived from tools/libxc/xen/io/netif.h
> >>>- *
> >>>- * Copyright (c) 2003-2004, Keir Fraser
> >>I guess I can buy this bit no longer being true given that you reworked
> >>the whole protocol.
> >>
> >>Ian
> >>
> >>
> >>_______________________________________________
> >>Xen-devel mailing list
> >>Xen-devel@lists.xen.org
> >>http://lists.xen.org/xen-devel
> >>
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 1/4] stubdom: Change vTPM shared page ABI
  2012-11-29 14:14       ` Matthew Fioravante
@ 2012-12-07 21:25         ` Konrad Rzeszutek Wilk
  2012-12-10  9:58           ` Ian Campbell
  0 siblings, 1 reply; 53+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-12-07 21:25 UTC (permalink / raw)
  To: Matthew Fioravante
  Cc: Daniel De Graaf, Ian.Campbell@citrix.com, xen-devel@lists.xen.org
> >+   snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
> >+   if ((err = xenbus_write(XBT_NIL, path, "1")))
> >+   {
> >+      /* if we got an error here we should carefully remove the interface and then return */
> >+      TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> >+      free(err);
> >+      remove_tpmif(tpmif);
> >+      goto error_post_irq;
> >+   }
> >+
> My preference is still to do away with the versioning stuff since
> tpm is just getting released. Its not even in linux yet so there is
> no confusion. We can even merge the linux patches together and
> resubmit as one if thats preferrable. Konrad, Ian, your final votes
> on that?
I am up for just removing the versioning stuff - and if one really
wants to be fool-proof - rename the 'backend/vtpm' to 'backend/vtpm2'
Perhaps?
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 1/4] stubdom: Change vTPM shared page ABI
  2012-12-07 21:25         ` Konrad Rzeszutek Wilk
@ 2012-12-10  9:58           ` Ian Campbell
  2012-12-10 15:03             ` Matthew Fioravante
  0 siblings, 1 reply; 53+ messages in thread
From: Ian Campbell @ 2012-12-10  9:58 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Matthew Fioravante, Daniel De Graaf, xen-devel@lists.xen.org
On Fri, 2012-12-07 at 21:25 +0000, Konrad Rzeszutek Wilk wrote:
> > >+   snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
> > >+   if ((err = xenbus_write(XBT_NIL, path, "1")))
> > >+   {
> > >+      /* if we got an error here we should carefully remove the interface and then return */
> > >+      TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> > >+      free(err);
> > >+      remove_tpmif(tpmif);
> > >+      goto error_post_irq;
> > >+   }
> > >+
> > My preference is still to do away with the versioning stuff since
> > tpm is just getting released.
It is present in the 2.6.18-xen tree and has made its way into distros,
at least SLES11.
>  Its not even in linux yet so there is
> > no confusion. We can even merge the linux patches together and
> > resubmit as one if thats preferrable. Konrad, Ian, your final votes
> > on that?
> 
> I am up for just removing the versioning stuff - and if one really
> wants to be fool-proof - rename the 'backend/vtpm' to 'backend/vtpm2'
> Perhaps?
> 
^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [PATCH 1/4] stubdom: Change vTPM shared page ABI
  2012-12-10  9:58           ` Ian Campbell
@ 2012-12-10 15:03             ` Matthew Fioravante
  0 siblings, 0 replies; 53+ messages in thread
From: Matthew Fioravante @ 2012-12-10 15:03 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Konrad Rzeszutek Wilk, Daniel De Graaf, xen-devel@lists.xen.org
[-- Attachment #1.1: Type: text/plain, Size: 1252 bytes --]
Ok why don't we go with backend/vtpm2. That seems to be the less 
intrusive approach.
On 12/10/2012 04:58 AM, Ian Campbell wrote:
> On Fri, 2012-12-07 at 21:25 +0000, Konrad Rzeszutek Wilk wrote:
>>>> +   snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
>>>> +   if ((err = xenbus_write(XBT_NIL, path, "1")))
>>>> +   {
>>>> +      /* if we got an error here we should carefully remove the interface and then return */
>>>> +      TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
>>>> +      free(err);
>>>> +      remove_tpmif(tpmif);
>>>> +      goto error_post_irq;
>>>> +   }
>>>> +
>>> My preference is still to do away with the versioning stuff since
>>> tpm is just getting released.
> It is present in the 2.6.18-xen tree and has made its way into distros,
> at least SLES11.
>
>>   Its not even in linux yet so there is
>>> no confusion. We can even merge the linux patches together and
>>> resubmit as one if thats preferrable. Konrad, Ian, your final votes
>>> on that?
>> I am up for just removing the versioning stuff - and if one really
>> wants to be fool-proof - rename the 'backend/vtpm' to 'backend/vtpm2'
>> Perhaps?
>>
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply	[flat|nested] 53+ messages in thread
end of thread, other threads:[~2012-12-10 15:03 UTC | newest]
Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-20 16:11 [PATCH RFC] stubdom: Change vTPM shared page ABI Daniel De Graaf
2012-11-20 16:16 ` Fioravante, Matthew E.
2012-11-20 18:24   ` [PATCH] drivers/tpm-xen: " Daniel De Graaf
2012-11-23 11:04   ` [PATCH RFC] stubdom: " Ian Campbell
2012-11-23 16:15     ` Daniel De Graaf
2012-11-23 16:30       ` Ian Campbell
2012-11-23 17:37         ` Samuel Thibault
2012-11-26 13:03       ` Fioravante, Matthew E.
2012-11-26 13:11         ` Fioravante, Matthew E.
2012-11-28 20:46     ` Konrad Rzeszutek Wilk
2012-11-28 22:22       ` Matthew Fioravante
2012-11-29  7:53         ` Ian Campbell
2012-11-30 16:11         ` Konrad Rzeszutek Wilk
2012-11-27 14:38 ` Matthew Fioravante
2012-11-27 15:14   ` [PATCH 0/4] stubdom/vtpm improvements Daniel De Graaf
2012-11-27 15:14     ` [PATCH 1/4] stubdom: Change vTPM shared page ABI Daniel De Graaf
2012-11-27 21:29       ` Matthew Fioravante
2012-11-27 22:08         ` Daniel De Graaf
2012-11-29 14:14       ` Matthew Fioravante
2012-12-07 21:25         ` Konrad Rzeszutek Wilk
2012-12-10  9:58           ` Ian Campbell
2012-12-10 15:03             ` Matthew Fioravante
2012-11-27 15:14     ` [PATCH 2/4] stubdom/vtpm: Add reconfiguration support Daniel De Graaf
2012-11-27 16:44       ` Samuel Thibault
2012-11-29 18:53       ` Matthew Fioravante
2012-11-29 19:28         ` Daniel De Graaf
2012-11-29 19:47           ` Matthew Fioravante
2012-11-29 21:37             ` Samuel Thibault
2012-11-30  9:59         ` Ian Campbell
2012-11-27 15:14     ` [PATCH 3/4] stubdom/grub: send kernel measurements to vTPM Daniel De Graaf
2012-11-27 16:41       ` Samuel Thibault
2012-11-27 18:08       ` Matthew Fioravante
2012-11-27 18:36         ` Samuel Thibault
2012-11-27 18:53         ` Daniel De Graaf
2012-11-27 15:14     ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Daniel De Graaf
2012-11-27 16:42       ` Samuel Thibault
2012-11-27 18:19       ` Matthew Fioravante
2012-11-27 19:02         ` Daniel De Graaf
2012-11-27 19:48           ` Matthew Fioravante
2012-11-27 20:04             ` Samuel Thibault
2012-11-27 20:11             ` Daniel De Graaf
2012-11-27 20:21               ` Matthew Fioravante
2012-11-27 20:30                 ` Daniel De Graaf
2012-11-27 20:34                   ` Matthew Fioravante
2012-11-27 20:40                     ` Daniel De Graaf
2012-11-27 22:16                       ` [PATCH] stubdom/vtpm: make state save operation atomic Daniel De Graaf
2012-11-29 18:07                         ` Matthew Fioravante
2012-11-29 20:24                           ` Daniel De Graaf
2012-11-29 20:48                             ` Matthew Fioravante
2012-11-28 21:58             ` [PATCH 4/4] stubdom/vtpm: Support multiple backends and locality Samuel Thibault
2012-11-29 19:09       ` Matthew Fioravante
2012-11-29 19:20         ` Daniel De Graaf
2012-11-27 16:46     ` [PATCH 0/4] stubdom/vtpm improvements Samuel Thibault
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).