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<andreas.nied...@iaik.tugraz.at>
Signed-off-by: Stefan Berger<stef...@linux.vnet.ibm.com>
---
Makefile.target | 3 +-
configure | 3 +
hw/tpm_backend.c | 58 +++++++
hw/tpm_backend.h | 43 +++++
hw/tpm_passthrough.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-options.hx | 37 +++++-
tpm.c | 17 ++
tpm.h | 33 ++++
8 files changed, 611 insertions(+), 2 deletions(-)
create mode 100644 hw/tpm_backend.c
create mode 100644 hw/tpm_backend.h
create mode 100644 hw/tpm_passthrough.c
diff --git a/Makefile.target b/Makefile.target
index 7cb4588..7af3593 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -221,7 +221,8 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-$(CONFIG_VGA) += vga.o
obj-y += memory.o savevm.o
obj-y += tpm.o
-obj-$(CONFIG_TPM) += tpm_tis.o
+obj-$(CONFIG_TPM) += tpm_tis.o tpm_backend.o
+obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
LIBS+=-lz
obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/configure b/configure
index c728b89..6395f06 100755
--- a/configure
+++ b/configure
@@ -3847,6 +3847,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_backend.c b/hw/tpm_backend.c
new file mode 100644
index 0000000..4cf0809
--- /dev/null
+++ b/hw/tpm_backend.c
@@ -0,0 +1,58 @@
+/*
+ * common TPM backend driver functions
+ *
+ * Copyright (c) 2012 IBM Corporation
+ * Authors:
+ * Stefan Berger<stef...@us.ibm.com>
+ *
+ * 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 "tpm.h"
+#include "qemu-thread.h"
+#include "hw/tpm_backend.h"
+
+void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
+{
+ g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL);
+}
+
+void tpm_backend_thread_create(TPMBackendThread *tbt,
+ GFunc func, gpointer user_data)
+{
+ if (!tbt->pool) {
+ tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
+ g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
+ }
+}
+
+void tpm_backend_thread_end(TPMBackendThread *tbt)
+{
+ if (tbt->pool) {
+ g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
+ g_thread_pool_free(tbt->pool, FALSE, TRUE);
+ tbt->pool = NULL;
+ }
+}
+
+void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt,
+ GFunc func, gpointer user_data)
+{
+ if (!tbt->pool) {
+ tpm_backend_thread_create(tbt, func, user_data);
+ } else {
+ g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_TPM_RESET,
+ NULL);
+ }
+}
diff --git a/hw/tpm_backend.h b/hw/tpm_backend.h
new file mode 100644
index 0000000..f5fe198
--- /dev/null
+++ b/hw/tpm_backend.h
@@ -0,0 +1,43 @@
+/*
+ * common TPM backend driver functions
+ *
+ * Copyright (c) 2012 IBM Corporation
+ * Authors:
+ * Stefan Berger<stef...@us.ibm.com>
+ *
+ * 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/>
+ */
+
+#ifndef HW_TPM_BACKEND_H
+#define HW_TPM_BACKEND_H
+
+typedef struct TPMBackendThread {
+ GThreadPool *pool;
+} TPMBackendThread;
+
+void tpm_backend_thread_deliver_request(TPMBackendThread *tbt);
+void tpm_backend_thread_create(TPMBackendThread *tbt,
+ GFunc func, gpointer user_data);
+void tpm_backend_thread_end(TPMBackendThread *tbt);
+void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt,
+ GFunc func, gpointer user_data);
+
+typedef enum TPMBackendCmd {
+ TPM_BACKEND_CMD_INIT = 1,
+ TPM_BACKEND_CMD_PROCESS_CMD,
+ TPM_BACKEND_CMD_END,
+ TPM_BACKEND_CMD_TPM_RESET,
+} TPMBackendCmd;
+
+#endif /* HW_TPM_BACKEND_H */
diff --git a/hw/tpm_passthrough.c b/hw/tpm_passthrough.c
new file mode 100644
index 0000000..dee7418
--- /dev/null
+++ b/hw/tpm_passthrough.c
@@ -0,0 +1,419 @@
+/*
+ * passthrough TPM driver
+ *
+ * Copyright (c) 2010, 2011 IBM Corporation
+ * Authors:
+ * Stefan Berger<stef...@us.ibm.com>
+ *
+ * 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/tpm_backend.h"
+#include "hw/pc.h"
+
+/* #define DEBUG_TPM */
+
+#ifdef DEBUG_TPM
+#define dprintf(fmt, ...) \
+ do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+ do { } while (0)
+#endif
+
+/* data structures */
+
+typedef struct TPMPassthruThreadParams {
+ TPMState *tpm_state;
+
+ TPMRecvDataCB *recv_data_callback;
+ TPMBackend *tb;
+} TPMPassthruThreadParams;
+
+struct TPMPassthruState {
+ QemuThread thread;
+ TPMBackendThread tbt;
+
+ TPMPassthruThreadParams tpm_thread_params;
+
+ char *tpm_dev;
+ int tpm_fd;
+ bool had_startup_error;
+};
+
+#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
+
+/* borrowed from qemu-char.c */