qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH V13 5/7] Add a TPM Passthrough backend driver im


From: Anthony Liguori
Subject: Re: [Qemu-devel] [PATCH V13 5/7] Add a TPM Passthrough backend driver implementation
Date: Mon, 12 Dec 2011 17:27:34 -0600
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.21) Gecko/20110831 Lightning/1.0b2 Thunderbird/3.1.13

On 12/12/2011 01:12 PM, Stefan Berger wrote:
 From Andreas Niederl's original posting with adaptations where necessary:

This patch is based of off version 9 of Stefan Berger's patch series
   "Qemu Trusted Platform Module (TPM) integration"
and adds a new backend driver for it.

This patch adds a passthrough backend driver for passing commands sent to the
emulated TPM device directly to a TPM device opened on the host machine.

Thus it is possible to use a hardware TPM device in a system running on QEMU,
providing the ability to access a TPM in a special state (e.g. after a Trusted
Boot).

This functionality is being used in the acTvSM Trusted Virtualization Platform
which is available on [1].

Usage example:
   qemu-system-x86_64 -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \
                      -device tpm-tis,tpmdev=tpm0 \
                      -cdrom test.iso -boot d

Some notes about the host TPM:
The TPM needs to be enabled and activated. If that's not the case one
has to go through the BIOS/UEFI and enable and activate that TPM for TPM
commands to work as expected.
It may be necessary to boot the kernel using tpm_tis.force=1 in the boot
command line or 'modprobe tpm_tis force=1' in case of using it as a module.

Regards,
Andreas Niederl, Stefan Berger

[1] http://trustedjava.sourceforge.net/

Signed-off-by: Andreas Niederl<address@hidden>
Signed-off-by: Stefan Berger<address@hidden>

---

Changes for v12:
  - check size indicator in response from TPM to match that of the received
    packet

Changes for v10:
  - clarified documentation
  - using /dev/tpm0 as default device if path option is not given
  - refactored code handling 'device' option into its own function
  - fixed name of structure to TPMPassthruThreadParams
  - only add tpm_passthrough_driver to collection of backends if
    it is compiled on the host

Changes for v9:
  - prefixing of all functions and variables with tpm_passthrough_
  - cleanup of all variables into a structure that is now accessed
    using TPMBackend (tb->s.tpm_pt)
  - build it on Linux machines
  - added function to test whether given device is a TPM and refuse
    startup if it is not
---
  Makefile.target      |    1 +
  configure            |    3 +
  hw/tpm_passthrough.c |  477 ++++++++++++++++++++++++++++++++++++++++++++++++++
  qemu-options.hx      |   33 ++++
  tpm.c                |   23 +++
  tpm.h                |   34 ++++
  6 files changed, 571 insertions(+), 0 deletions(-)
  create mode 100644 hw/tpm_passthrough.c

diff --git a/Makefile.target b/Makefile.target
index 37d5d10..4fc96e6 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -206,6 +206,7 @@ obj-$(CONFIG_KVM) += kvm.o kvm-all.o
  obj-$(CONFIG_NO_KVM) += kvm-stub.o
  obj-y += memory.o
  obj-$(CONFIG_TPM) += tpm.o tpm_tis.o
+obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
  LIBS+=-lz

  QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/configure b/configure
index 385feb4..25995bc 100755
--- a/configure
+++ b/configure
@@ -3721,6 +3721,9 @@ fi

  if test "$tpm" = "yes"; then
    if test "$target_softmmu" = "yes" ; then
+    if test "$linux" = "yes" ; then
+      echo "CONFIG_TPM_PASSTHROUGH=y">>  $config_target_mak
+    fi
      echo "CONFIG_TPM=y">>  $config_host_mak
    fi
  fi
diff --git a/hw/tpm_passthrough.c b/hw/tpm_passthrough.c
new file mode 100644
index 0000000..f9cfe3d
--- /dev/null
+++ b/hw/tpm_passthrough.c
@@ -0,0 +1,477 @@
+/*
+ *  passthrough TPM driver
+ *
+ *  Copyright (c) 2010, 2011 IBM Corporation
+ *  Authors:
+ *    Stefan Berger<address@hidden>
+ *
+ *  Copyright (C) 2011 IAIK, Graz University of Technology
+ *    Author: Andreas Niederl
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see<http://www.gnu.org/licenses/>
+ */
+
+#include "qemu-common.h"
+#include "qemu-error.h"
+#include "tpm.h"
+#include "hw/hw.h"
+#include "hw/tpm_tis.h"
+#include "hw/pc.h"
+
+/* #define DEBUG_TPM */
+
+/* data structures */
+
+typedef struct TPMPassthruThreadParams {
+    TPMState *tpm_state;
+
+    TPMRecvDataCB *recv_data_callback;
+    TPMBackend *tb;
+} TPMPassthruThreadParams;
+
+struct TPMPassthruState {
+    QemuThread thread;
+    bool thread_terminate;
+    bool thread_running;
+
+    TPMPassthruThreadParams tpm_thread_params;
+
+    char tpm_dev[64];
+    int tpm_fd;
+    bool had_startup_error;
+};
+
+#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
+
+/* borrowed from qemu-char.c */
+static int tpm_passthrough_unix_write(int fd, const uint8_t *buf, uint32_t len)
+{
+    int ret, len1;
+
+    len1 = len;
+    while (len1>  0) {
+        ret = write(fd, buf, len1);
+        if (ret<  0) {
+            if (errno != EINTR&&  errno != EAGAIN) {
+                return -1;
+            }
+        } else if (ret == 0) {
+            break;
+        } else {
+            buf  += ret;
+            len1 -= ret;
+        }
+    }
+    return len - len1;
+}
+
+static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
+{
+    int ret, len1;
+    uint8_t *buf1;
+
+    len1 = len;
+    buf1 = buf;
+    while ((len1>  0)&&  (ret = read(fd, buf1, len1)) != 0) {
+        if (ret<  0) {
+            if (errno != EINTR&&  errno != EAGAIN) {
+                return -1;
+            }
+        } else {
+            buf1 += ret;
+            len1 -= ret;
+        }
+    }
+    return len - len1;
+}
+
+static void *tpm_passthrough_main_loop(void *d)
+{
+    TPMPassthruThreadParams *thr_parms = d;
+    TPMPassthruState *tpm_pt = thr_parms->tb->s.tpm_pt;
+    uint32_t in_len, out_len;
+    uint8_t *in, *out;
+    uint8_t locty;
+    TPMLocality *cmd_locty;
+    int ret;

This is rather scary. I'd rather see us make use of a GThreadPool in order to submit read/write requests asynchronously to the /dev/tpm device. I don't think the code should be structured expecting synchronous command execution.

Regards,

Anthony Liguori



reply via email to

[Prev in Thread] Current Thread [Next in Thread]