* [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1
@ 2017-11-15 12:31 Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 1/4] specs: Extend TPM spec with TPM emulator description Stefan Berger
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Stefan Berger @ 2017-11-15 12:31 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, marcandre.lureau, Stefan Berger
This pull request is for 2.11 and extends documentation as well as fixes
bugs related to concurrency and failure mode.
The following changes since commit 4ffa88c99c54d2a30f79e3dbecec50b023eff1c8:
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-11-08-1' into staging (2017-11-10 16:01:35 +0000)
are available in the git repository at:
git://github.com/stefanberger/qemu-tpm.git tags/pull-tpm-2017-11-15-1
for you to fetch changes up to 6cd65969da57eaa9bdff07b80ecca2becce0597a:
tpm_tis: Return 0 for every register in case of failure mode (2017-11-15 06:47:35 -0500)
----------------------------------------------------------------
Merge tpm 2017/11/15 v1
----------------------------------------------------------------
Marc-André Lureau (1):
tpm-emulator: protect concurrent ctrl_chr access
Stefan Berger (3):
specs: Extend TPM spec with TPM emulator description
tpm_tis: Return TPM_VERSION_UNSPEC in case of BE failure
tpm_tis: Return 0 for every register in case of failure mode
docs/specs/tpm.txt | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
hw/tpm/tpm_emulator.c | 44 +++++++++++++++++-----------
hw/tpm/tpm_tis.c | 6 +++-
3 files changed, 112 insertions(+), 17 deletions(-)
--
2.5.5
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-devel] [PULL 1/4] specs: Extend TPM spec with TPM emulator description
2017-11-15 12:31 [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Stefan Berger
@ 2017-11-15 12:31 ` Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 2/4] tpm-emulator: protect concurrent ctrl_chr access Stefan Berger
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Stefan Berger @ 2017-11-15 12:31 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, marcandre.lureau, Stefan Berger
Following the recent extension of QEMU with a TPM emulator device,
update the specs describing for how to interact with the device.
The results of commands run inside a Linux VM are expected to be
similar to those when the TPM passthrough device is used, so we
just reuse that.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
docs/specs/tpm.txt | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt
index 914daac..d1d7157 100644
--- a/docs/specs/tpm.txt
+++ b/docs/specs/tpm.txt
@@ -121,3 +121,82 @@ crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0
PCR-00: 35 4E 3B CE 23 9F 38 59 ...
...
PCR-23: 00 00 00 00 00 00 00 00 ...
+
+
+== The QEMU TPM emulator device ==
+
+The TPM emulator device uses an external TPM emulator called 'swtpm' for
+sending TPM commands to and receiving responses from. The swtpm program
+must have been started before trying to access it through the TPM emulator
+with QEMU.
+
+The TPM emulator implements a command channel for transferring TPM commands
+and responses as well as a control channel over which control commands can
+be sent. The specification for the control channel can be found here:
+
+https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod
+
+
+The control channel serves the purpose of resetting, initializing, and
+migrating the TPM state, among other things.
+
+The swtpm program behaves like a hardware TPM and therefore needs to be
+initialized by the firmware running inside the QEMU virtual machine.
+One necessary step for initializing the device is to send the TPM_Startup
+command to it. SeaBIOS, for example, has been instrumented to initialize
+a TPM 1.2 or TPM 2 device using this command.
+
+
+QEMU files related to the TPM emulator device:
+ - hw/tpm/tpm_emulator.c
+ - hw/tpm/tpm_util.c
+ - hw/tpm/tpm_util.h
+
+
+The following commands start the swtpm with a UnixIO control channel over
+a socket interface. They do not need to be run as root.
+
+mkdir /tmp/mytpm1
+swtpm socket --tpmstate dir=/tmp/mytpm1 \
+ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
+ --log level=20
+
+Command line to start QEMU with the TPM emulator device communicating with
+the swtpm:
+
+qemu-system-x86_64 -display sdl -enable-kvm \
+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
+ -tpmdev emulator,id=tpm0,chardev=chrtpm \
+ -device tpm-tis,tpmdev=tpm0 test.img
+
+
+In case SeaBIOS is used as firmware, it should show the TPM menu item
+after entering the menu with 'ESC'.
+
+Select boot device:
+1. DVD/CD [ata1-0: QEMU DVD-ROM ATAPI-4 DVD/CD]
+[...]
+5. Legacy option rom
+
+t. TPM Configuration
+
+
+The following commands should result in similar output inside the VM with a
+Linux kernel that either has the TPM TIS driver built-in or available as a
+module:
+
+#> dmesg | grep -i tpm
+[ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1)
+
+#> dmesg | grep TCPA
+[ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \
+ BXPCTCPA 0000001 BXPC 00000001)
+
+#> ls -l /dev/tpm*
+crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0
+
+#> find /sys/devices/ | grep pcrs$ | xargs cat
+PCR-00: 35 4E 3B CE 23 9F 38 59 ...
+...
+PCR-23: 00 00 00 00 00 00 00 00 ...
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PULL 2/4] tpm-emulator: protect concurrent ctrl_chr access
2017-11-15 12:31 [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 1/4] specs: Extend TPM spec with TPM emulator description Stefan Berger
@ 2017-11-15 12:31 ` Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 3/4] tpm_tis: Return TPM_VERSION_UNSPEC in case of BE failure Stefan Berger
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Stefan Berger @ 2017-11-15 12:31 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, marcandre.lureau, Marc-André Lureau,
Stefan Berger
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The control chardev is being used from the data thread to set the
locality of the next request. Altough the chr has a write mutex, we
may potentially read the reply from another thread request.
Add a mutex to protect from concurrent control commands.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
hw/tpm/tpm_emulator.c | 44 ++++++++++++++++++++++++++++----------------
1 file changed, 28 insertions(+), 16 deletions(-)
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
index 9aaec8e..e1a6810 100644
--- a/hw/tpm/tpm_emulator.c
+++ b/hw/tpm/tpm_emulator.c
@@ -71,15 +71,21 @@ typedef struct TPMEmulator {
ptm_cap caps; /* capabilities of the TPM */
uint8_t cur_locty_number; /* last set locality */
Error *migration_blocker;
+
+ QemuMutex mutex;
} TPMEmulator;
-static int tpm_emulator_ctrlcmd(CharBackend *dev, unsigned long cmd, void *msg,
+static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
size_t msg_len_in, size_t msg_len_out)
{
+ CharBackend *dev = &tpm->ctrl_chr;
uint32_t cmd_no = cpu_to_be32(cmd);
ssize_t n = sizeof(uint32_t) + msg_len_in;
uint8_t *buf = NULL;
+ int ret = -1;
+
+ qemu_mutex_lock(&tpm->mutex);
buf = g_alloca(n);
memcpy(buf, &cmd_no, sizeof(cmd_no));
@@ -87,17 +93,21 @@ static int tpm_emulator_ctrlcmd(CharBackend *dev, unsigned long cmd, void *msg,
n = qemu_chr_fe_write_all(dev, buf, n);
if (n <= 0) {
- return -1;
+ goto end;
}
if (msg_len_out != 0) {
n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
if (n <= 0) {
- return -1;
+ goto end;
}
}
- return 0;
+ ret = 0;
+
+end:
+ qemu_mutex_unlock(&tpm->mutex);
+ return ret;
}
static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
@@ -154,7 +164,7 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
DPRINTF("setting locality : 0x%x", locty_number);
loc.u.req.loc = locty_number;
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SET_LOCALITY, &loc,
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
sizeof(loc), sizeof(loc)) < 0) {
error_setg(errp, "tpm-emulator: could not set locality : %s",
strerror(errno));
@@ -202,8 +212,8 @@ error:
static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
{
DPRINTF("%s", __func__);
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_GET_CAPABILITY,
- &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
+ &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
error_report("tpm-emulator: probing failed : %s", strerror(errno));
return -1;
}
@@ -254,8 +264,8 @@ static int tpm_emulator_startup_tpm(TPMBackend *tb)
ptm_res res;
DPRINTF("%s", __func__);
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_INIT, &init, sizeof(init),
- sizeof(init)) < 0) {
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init),
+ sizeof(init)) < 0) {
error_report("tpm-emulator: could not send INIT: %s",
strerror(errno));
goto err_exit;
@@ -278,7 +288,7 @@ static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
ptm_est est;
DPRINTF("%s", __func__);
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_GET_TPMESTABLISHED, &est,
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est,
0, sizeof(est)) < 0) {
error_report("tpm-emulator: Could not get the TPM established flag: %s",
strerror(errno));
@@ -302,7 +312,7 @@ static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
}
reset_est.u.req.loc = tpm_emu->cur_locty_number;
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_RESET_TPMESTABLISHED,
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_RESET_TPMESTABLISHED,
&reset_est, sizeof(reset_est),
sizeof(reset_est)) < 0) {
error_report("tpm-emulator: Could not reset the establishment bit: %s",
@@ -330,7 +340,7 @@ static void tpm_emulator_cancel_cmd(TPMBackend *tb)
return;
}
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_CANCEL_TPM_CMD, &res, 0,
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_CANCEL_TPM_CMD, &res, 0,
sizeof(res)) < 0) {
error_report("tpm-emulator: Could not cancel command: %s",
strerror(errno));
@@ -378,8 +388,8 @@ static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SET_DATAFD, &res, 0,
- sizeof(res)) || res != 0) {
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0,
+ sizeof(res)) < 0 || res != 0) {
error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
strerror(errno));
goto err_exit;
@@ -501,6 +511,7 @@ static void tpm_emulator_inst_init(Object *obj)
DPRINTF("%s", __func__);
tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
tpm_emu->cur_locty_number = ~0;
+ qemu_mutex_init(&tpm_emu->mutex);
}
/*
@@ -510,8 +521,7 @@ static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
{
ptm_res res;
- if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SHUTDOWN, &res, 0,
- sizeof(res)) < 0) {
+ if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) {
error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
strerror(errno));
} else if (res != 0) {
@@ -536,6 +546,8 @@ static void tpm_emulator_inst_finalize(Object *obj)
migrate_del_blocker(tpm_emu->migration_blocker);
error_free(tpm_emu->migration_blocker);
}
+
+ qemu_mutex_destroy(&tpm_emu->mutex);
}
static void tpm_emulator_class_init(ObjectClass *klass, void *data)
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PULL 3/4] tpm_tis: Return TPM_VERSION_UNSPEC in case of BE failure
2017-11-15 12:31 [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 1/4] specs: Extend TPM spec with TPM emulator description Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 2/4] tpm-emulator: protect concurrent ctrl_chr access Stefan Berger
@ 2017-11-15 12:31 ` Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 4/4] tpm_tis: Return 0 for every register in case of failure mode Stefan Berger
2017-11-16 12:45 ` [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Peter Maydell
4 siblings, 0 replies; 6+ messages in thread
From: Stefan Berger @ 2017-11-15 12:31 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, marcandre.lureau, Stefan Berger
In case the backend has a failure, such as the tpm_emulator's CMD_INIT
failing, the TIS goes into failure mode and does not respond to reads
or writes to MMIO registers. In this case we need to prevent the ACPI
table from being added and the straight-forward way is to indicate that
there's no known TPM version being used.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/tpm/tpm_tis.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index 7402528..fec2fc6 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -1008,6 +1008,10 @@ TPMVersion tpm_tis_get_tpm_version(Object *obj)
{
TPMState *s = TPM(obj);
+ if (tpm_backend_had_startup_error(s->be_driver)) {
+ return TPM_VERSION_UNSPEC;
+ }
+
return tpm_backend_get_tpm_version(s->be_driver);
}
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PULL 4/4] tpm_tis: Return 0 for every register in case of failure mode
2017-11-15 12:31 [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Stefan Berger
` (2 preceding siblings ...)
2017-11-15 12:31 ` [Qemu-devel] [PULL 3/4] tpm_tis: Return TPM_VERSION_UNSPEC in case of BE failure Stefan Berger
@ 2017-11-15 12:31 ` Stefan Berger
2017-11-16 12:45 ` [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Peter Maydell
4 siblings, 0 replies; 6+ messages in thread
From: Stefan Berger @ 2017-11-15 12:31 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, marcandre.lureau, Stefan Berger
Rather than returning ~0, return 0 for every register in case of failure
mode. The '0' is better to indicate that there's no device there. It avoids
SeaBIOS detecting a device and getting stuck on it trying to read and write
its registers.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/tpm/tpm_tis.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index fec2fc6..42d647d 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -545,7 +545,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
uint8_t v;
if (tpm_backend_had_startup_error(s->be_driver)) {
- return val;
+ return 0;
}
switch (offset) {
--
2.5.5
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1
2017-11-15 12:31 [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Stefan Berger
` (3 preceding siblings ...)
2017-11-15 12:31 ` [Qemu-devel] [PULL 4/4] tpm_tis: Return 0 for every register in case of failure mode Stefan Berger
@ 2017-11-16 12:45 ` Peter Maydell
4 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2017-11-16 12:45 UTC (permalink / raw)
To: Stefan Berger; +Cc: QEMU Developers, Marc-André Lureau
On 15 November 2017 at 12:31, Stefan Berger <stefanb@linux.vnet.ibm.com> wrote:
> This pull request is for 2.11 and extends documentation as well as fixes
> bugs related to concurrency and failure mode.
>
> The following changes since commit 4ffa88c99c54d2a30f79e3dbecec50b023eff1c8:
>
> Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-11-08-1' into staging (2017-11-10 16:01:35 +0000)
>
> are available in the git repository at:
>
> git://github.com/stefanberger/qemu-tpm.git tags/pull-tpm-2017-11-15-1
>
> for you to fetch changes up to 6cd65969da57eaa9bdff07b80ecca2becce0597a:
>
> tpm_tis: Return 0 for every register in case of failure mode (2017-11-15 06:47:35 -0500)
>
> ----------------------------------------------------------------
> Merge tpm 2017/11/15 v1
>
> ----------------------------------------------------------------
> Marc-André Lureau (1):
> tpm-emulator: protect concurrent ctrl_chr access
>
> Stefan Berger (3):
> specs: Extend TPM spec with TPM emulator description
> tpm_tis: Return TPM_VERSION_UNSPEC in case of BE failure
> tpm_tis: Return 0 for every register in case of failure mode
>
> docs/specs/tpm.txt | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++
> hw/tpm/tpm_emulator.c | 44 +++++++++++++++++-----------
> hw/tpm/tpm_tis.c | 6 +++-
> 3 files changed, 112 insertions(+), 17 deletions(-)
Applied, thanks.
-- PMM
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-11-16 12:45 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-11-15 12:31 [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 1/4] specs: Extend TPM spec with TPM emulator description Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 2/4] tpm-emulator: protect concurrent ctrl_chr access Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 3/4] tpm_tis: Return TPM_VERSION_UNSPEC in case of BE failure Stefan Berger
2017-11-15 12:31 ` [Qemu-devel] [PULL 4/4] tpm_tis: Return 0 for every register in case of failure mode Stefan Berger
2017-11-16 12:45 ` [Qemu-devel] [PULL 0/4] Merge tpm 2017/11/15 v1 Peter Maydell
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).