Message ID | 4780481659602f92fffacac66e7dca41ad2787c4.camel@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | tpm: add backend for mssim | expand |
On 12/10/22 12:10, James Bottomley wrote: > The Microsoft Simulator (mssim) is the reference emulation platform > for the TCG TPM 2.0 specification. > > https://github.com/Microsoft/ms-tpm-20-ref.git > > It exports a fairly simple network socket baset protocol on two baset -> based. > sockets, one for command (default 2321) and one for control (default > 2322). This patch adds a simple backend that can speak the mssim > protocol over the network. It also allows the host, and two ports to > be specified on the qemu command line. The benefits are twofold: > firstly it gives us a backend that actually speaks a standard TPM > emulation protocol instead of the linux specific TPM driver format of > the current emulated TPM backend and secondly, using the microsoft > protocol, the end point of the emulator can be anywhere on the > network, facilitating the cloud use case where a central TPM service > can be used over a control network. > > The implementation does basic control commands like power off/on, but > doesn't implement cancellation or startup. The former because > cancellation is pretty much useless on a fast operating TPM emulator > and the latter because this emulator is designed to be used with OVMF > which itself does TPM startup and I wanted to validate that. How did you implement VM suspend/resume and snapshotting support? Stefan > > To run this, simply download an emulator based on the MS specification > (package ibmswtpm2 on openSUSE) and run it, then add these two lines > to the qemu command and it will use the emulator. > > -tpmdev mssim,id=tpm0 \ > -device tpm-crb,tpmdev=tpm0 \ > > to use a remote emulator replace the first line with > > -tpmdev mssim,it=tpm0,host=remote.host,port=4455,ctrl=4457 \ > > tpm-tis also works as the backend. > > Signed-off-by: James Bottomley <jejb@linux.ibm.com> > --- > backends/tpm/Kconfig | 5 + > backends/tpm/meson.build | 1 + > backends/tpm/tpm_mssim.c | 266 +++++++++++++++++++++++++++++++++++++++ > backends/tpm/tpm_mssim.h | 43 +++++++ > monitor/hmp-cmds.c | 6 + > qapi/tpm.json | 35 +++++- > 6 files changed, 353 insertions(+), 3 deletions(-) > create mode 100644 backends/tpm/tpm_mssim.c > create mode 100644 backends/tpm/tpm_mssim.h > > diff --git a/backends/tpm/Kconfig b/backends/tpm/Kconfig > index 5d91eb89c2..d6d6fa53e9 100644 > --- a/backends/tpm/Kconfig > +++ b/backends/tpm/Kconfig > @@ -12,3 +12,8 @@ config TPM_EMULATOR > bool > default y > depends on TPM_BACKEND > + > +config TPM_MSSIM > + bool > + default y > + depends on TPM_BACKEND > diff --git a/backends/tpm/meson.build b/backends/tpm/meson.build > index 7f2503f84e..c7c3c79125 100644 > --- a/backends/tpm/meson.build > +++ b/backends/tpm/meson.build > @@ -3,4 +3,5 @@ if have_tpm > softmmu_ss.add(files('tpm_util.c')) > softmmu_ss.add(when: 'CONFIG_TPM_PASSTHROUGH', if_true: files('tpm_passthrough.c')) > softmmu_ss.add(when: 'CONFIG_TPM_EMULATOR', if_true: files('tpm_emulator.c')) > + softmmu_ss.add(when: 'CONFIG_TPM_MSSIM', if_true: files('tpm_mssim.c')) > endif > diff --git a/backends/tpm/tpm_mssim.c b/backends/tpm/tpm_mssim.c > new file mode 100644 > index 0000000000..6864b1fbc0 > --- /dev/null > +++ b/backends/tpm/tpm_mssim.c > @@ -0,0 +1,266 @@ > +/* > + * Emulator TPM driver which connects over the mssim protocol > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * Copyright (c) 2022 > + * Author: James Bottomley <jejb@linux.ibm.com> > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/error-report.h" > +#include "qemu/sockets.h" > + > +#include "qapi/clone-visitor.h" > +#include "qapi/qapi-visit-tpm.h" > + > +#include "io/channel-socket.h" > + > +#include "sysemu/tpm_backend.h" > +#include "sysemu/tpm_util.h" > + > +#include "qom/object.h" > + > +#include "tpm_int.h" > +#include "tpm_mssim.h" > + > +#define ERROR_PREFIX "TPM mssim Emulator: " > + > +#define TYPE_TPM_MSSIM "tpm-mssim" > +OBJECT_DECLARE_SIMPLE_TYPE(TPMmssim, TPM_MSSIM) > + > +struct TPMmssim { > + TPMBackend parent; > + > + TPMmssimOptions opts; > + > + QIOChannel *cmd_qc, *ctrl_qc; > +}; > + > +static int tpm_send_ctrl(TPMmssim *t, uint32_t cmd, Error **errp) > +{ > + int ret; > + > + cmd = htonl(cmd); > + ret = qio_channel_write_all(t->ctrl_qc, (char *)&cmd, sizeof(cmd), errp); > + if (ret != 0) > + return ret; > + ret = qio_channel_read_all(t->ctrl_qc, (char *)&cmd, sizeof(cmd), errp); > + if (ret != 0) > + return ret; > + if (cmd != 0) { > + error_setg(errp, ERROR_PREFIX "Incorrect ACK recieved on control channel 0x%x\n", cmd); > + return -1; > + } > + return 0; > +} > + > +static void tpm_mssim_instance_init(Object *obj) > +{ > +} > + > +static void tpm_mssim_instance_finalize(Object *obj) > +{ > + TPMmssim *t = TPM_MSSIM(obj); > + > + tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, NULL); > + > + object_unref(OBJECT(t->ctrl_qc)); > + object_unref(OBJECT(t->cmd_qc)); > +} > + > +static void tpm_mssim_cancel_cmd(TPMBackend *tb) > +{ > + return; > +} > + > +static TPMVersion tpm_mssim_get_version(TPMBackend *tb) > +{ > + return TPM_VERSION_2_0; > +} > + > +static size_t tpm_mssim_get_buffer_size(TPMBackend *tb) > +{ > + /* TCG standard profile max buffer size */ > + return 4096; > +} > + > +static TpmTypeOptions *tpm_mssim_get_opts(TPMBackend *tb) > +{ > + TPMmssim *t = TPM_MSSIM(tb); > + TpmTypeOptions *opts = g_new0(TpmTypeOptions, 1); > + > + opts->type = TPM_TYPE_MSSIM; > + opts->u.mssim.data = QAPI_CLONE(TPMmssimOptions, &t->opts); > + > + return opts; > +} > + > +static void tpm_mssim_handle_request(TPMBackend *tb, TPMBackendCmd *cmd, > + Error **errp) > +{ > + TPMmssim *t = TPM_MSSIM(tb); > + uint32_t header, len; > + uint8_t locality = cmd->locty; > + struct iovec iov[4]; > + int ret; > + > + header = htonl(TPM_SEND_COMMAND); > + len = htonl(cmd->in_len); > + > + iov[0].iov_base = &header; > + iov[0].iov_len = sizeof(header); > + iov[1].iov_base = &locality; > + iov[1].iov_len = sizeof(locality); > + iov[2].iov_base = &len; > + iov[2].iov_len = sizeof(len); > + iov[3].iov_base = (void *)cmd->in; > + iov[3].iov_len = cmd->in_len; > + > + ret = qio_channel_writev_all(t->cmd_qc, iov, 4, errp); > + if (ret != 0) > + goto fail; > + > + ret = qio_channel_read_all(t->cmd_qc, (char *)&len, sizeof(len), errp); > + if (ret != 0) > + goto fail; > + len = ntohl(len); > + if (len > cmd->out_len) { > + error_setg(errp, "receive size is too large"); > + goto fail; > + } > + ret = qio_channel_read_all(t->cmd_qc, (char *)cmd->out, len, errp); > + if (ret != 0) > + goto fail; > + /* ACK packet */ > + ret = qio_channel_read_all(t->cmd_qc, (char *)&header, sizeof(header), errp); > + if (ret != 0) > + goto fail; > + if (header != 0) { > + error_setg(errp, "incorrect ACK received on command channel 0x%x", len); > + goto fail; > + } > + > + return; > + > + fail: > + error_prepend(errp, ERROR_PREFIX); > + tpm_util_write_fatal_error_response(cmd->out, cmd->out_len); > +} > + > +static TPMBackend *tpm_mssim_create(QemuOpts *opts) > +{ > + TPMBackend *be = TPM_BACKEND(object_new(TYPE_TPM_MSSIM)); > + TPMmssim *t = TPM_MSSIM(be); > + InetSocketAddress cmd_s, ctl_s; > + int sock; > + const char *host, *port, *ctrl; > + Error *errp = NULL; > + > + host = qemu_opt_get(opts, "host"); > + if (!host) > + host = "localhost"; > + t->opts.host = g_strdup(host); > + > + port = qemu_opt_get(opts, "port"); > + if (!port) > + port = "2321"; > + t->opts.port = g_strdup(port); > + > + ctrl = qemu_opt_get(opts, "ctrl"); > + if (!ctrl) > + ctrl = "2322"; > + t->opts.ctrl = g_strdup(ctrl); > + > + cmd_s.host = (char *)host; > + cmd_s.port = (char *)port; > + > + ctl_s.host = (char *)host; > + ctl_s.port = (char *)ctrl; > + > + sock = inet_connect_saddr(&cmd_s, &errp); > + if (sock < 0) > + goto fail; > + t->cmd_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, &errp)); > + if (errp) > + goto fail; > + sock = inet_connect_saddr(&ctl_s, &errp); > + if (sock < 0) > + goto fail_unref_cmd; > + t->ctrl_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, &errp)); > + if (errp) > + goto fail_unref_cmd; > + > + /* reset the TPM using a power cycle sequence, in case someone > + * has previously powered it up */ > + sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, &errp); > + if (sock != 0) > + goto fail_unref; > + sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_ON, &errp); > + if (sock != 0) > + goto fail_unref; > + sock = tpm_send_ctrl(t, TPM_SIGNAL_NV_ON, &errp); > + if (sock != 0) > + goto fail_unref; > + > + return be; > + fail_unref: > + object_unref(OBJECT(t->ctrl_qc)); > + fail_unref_cmd: > + object_unref(OBJECT(t->cmd_qc)); > + fail: > + error_prepend(&errp, ERROR_PREFIX); > + error_report_err(errp); > + object_unref(OBJECT(be)); > + > + return NULL; > +} > + > +static const QemuOptDesc tpm_mssim_cmdline_opts[] = { > + TPM_STANDARD_CMDLINE_OPTS, > + { > + .name = "host", > + .type = QEMU_OPT_STRING, > + .help = "name or IP address of host to connect to (deault localhost)", > + }, > + { > + .name = "port", > + .type = QEMU_OPT_STRING, > + .help = "port number for standard TPM commands (default 2321)", > + }, > + { > + .name = "ctrl", > + .type = QEMU_OPT_STRING, > + .help = "control port for TPM commands (default 2322)", > + }, > +}; > + > +static void tpm_mssim_class_init(ObjectClass *klass, void *data) > +{ > + TPMBackendClass *cl = TPM_BACKEND_CLASS(klass); > + > + cl->type = TPM_TYPE_MSSIM; > + cl->opts = tpm_mssim_cmdline_opts; > + cl->desc = "TPM mssim emulator backend driver"; > + cl->create = tpm_mssim_create; > + cl->cancel_cmd = tpm_mssim_cancel_cmd; > + cl->get_tpm_version = tpm_mssim_get_version; > + cl->get_buffer_size = tpm_mssim_get_buffer_size; > + cl->get_tpm_options = tpm_mssim_get_opts; > + cl->handle_request = tpm_mssim_handle_request; > +} > + > +static const TypeInfo tpm_mssim_info = { > + .name = TYPE_TPM_MSSIM, > + .parent = TYPE_TPM_BACKEND, > + .instance_size = sizeof(TPMmssim), > + .class_init = tpm_mssim_class_init, > + .instance_init = tpm_mssim_instance_init, > + .instance_finalize = tpm_mssim_instance_finalize, > +}; > + > +static void tpm_mssim_register(void) > +{ > + type_register_static(&tpm_mssim_info); > +} > + > +type_init(tpm_mssim_register) > diff --git a/backends/tpm/tpm_mssim.h b/backends/tpm/tpm_mssim.h > new file mode 100644 > index 0000000000..04a270338a > --- /dev/null > +++ b/backends/tpm/tpm_mssim.h > @@ -0,0 +1,43 @@ > +/* > + * SPDX-License-Identifier: BSD-2-Clause > + * > + * The code below is copied from the Microsoft/TCG Reference implementation > + * > + * https://github.com/Microsoft/ms-tpm-20-ref.git > + * > + * In file TPMCmd/Simulator/include/TpmTcpProtocol.h > + */ > + > +#define TPM_SIGNAL_POWER_ON 1 > +#define TPM_SIGNAL_POWER_OFF 2 > +#define TPM_SIGNAL_PHYS_PRES_ON 3 > +#define TPM_SIGNAL_PHYS_PRES_OFF 4 > +#define TPM_SIGNAL_HASH_START 5 > +#define TPM_SIGNAL_HASH_DATA 6 > + // {uint32_t BufferSize, uint8_t[BufferSize] Buffer} > +#define TPM_SIGNAL_HASH_END 7 > +#define TPM_SEND_COMMAND 8 > + // {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} -> > + // {uint32_t OutBufferSize, uint8_t[OutBufferSize] OutBuffer} > + > +#define TPM_SIGNAL_CANCEL_ON 9 > +#define TPM_SIGNAL_CANCEL_OFF 10 > +#define TPM_SIGNAL_NV_ON 11 > +#define TPM_SIGNAL_NV_OFF 12 > +#define TPM_SIGNAL_KEY_CACHE_ON 13 > +#define TPM_SIGNAL_KEY_CACHE_OFF 14 > + > +#define TPM_REMOTE_HANDSHAKE 15 > +#define TPM_SET_ALTERNATIVE_RESULT 16 > + > +#define TPM_SIGNAL_RESET 17 > +#define TPM_SIGNAL_RESTART 18 > + > +#define TPM_SESSION_END 20 > +#define TPM_STOP 21 > + > +#define TPM_GET_COMMAND_RESPONSE_SIZES 25 > + > +#define TPM_ACT_GET_SIGNALED 26 > + > +#define TPM_TEST_FAILURE_MODE 30 > diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c > index 01b789a79e..f4cd030eab 100644 > --- a/monitor/hmp-cmds.c > +++ b/monitor/hmp-cmds.c > @@ -841,6 +841,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) > unsigned int c = 0; > TPMPassthroughOptions *tpo; > TPMEmulatorOptions *teo; > + TPMmssimOptions *tmo; > > info_list = qmp_query_tpm(&err); > if (err) { > @@ -874,6 +875,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) > teo = ti->options->u.emulator.data; > monitor_printf(mon, ",chardev=%s", teo->chardev); > break; > + case TPM_TYPE_MSSIM: > + tmo = ti->options->u.mssim.data; > + monitor_printf(mon, ",host=%s,port=%s,ctl=%s", tmo->host, > + tmo->port, tmo->host); > + break; > case TPM_TYPE__MAX: > break; > } > diff --git a/qapi/tpm.json b/qapi/tpm.json > index 4e2ea9756a..d92065043e 100644 > --- a/qapi/tpm.json > +++ b/qapi/tpm.json > @@ -49,7 +49,7 @@ > # > # Since: 1.5 > ## > -{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ], > +{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator', 'mssim' ], > 'if': 'CONFIG_TPM' } > > ## > @@ -64,7 +64,7 @@ > # Example: > # > # -> { "execute": "query-tpm-types" } > -# <- { "return": [ "passthrough", "emulator" ] } > +# <- { "return": [ "passthrough", "emulator", "mssim" ] } > # > ## > { 'command': 'query-tpm-types', 'returns': ['TpmType'], > @@ -99,6 +99,24 @@ > { 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' }, > 'if': 'CONFIG_TPM' } > > +## > +# @TPMmssimOptions: > +# > +# Information for the mssim emulator connection > +# > +# @host: host name or IP address to connect to > +# @port: port for the standard TPM commands > +# @ctrl: control port for TPM state changes > +# > +# Since: 7.2.0 > +## > +{ 'struct': 'TPMmssimOptions', > + 'data': { > + 'host': 'str', > + 'port': 'str', > + 'ctrl': 'str' }, > + 'if': 'CONFIG_TPM' } > + > ## > # @TPMPassthroughOptionsWrapper: > # > @@ -117,6 +135,15 @@ > 'data': { 'data': 'TPMEmulatorOptions' }, > 'if': 'CONFIG_TPM' } > > +## > +# @TPMmssimOptionsWrapper: > +# > +# Since: 7.2.0 > +## > +{ 'struct': 'TPMmssimOptionsWrapper', > + 'data' : { 'data': 'TPMmssimOptions' }, > + 'if': 'CONFIG_TPM' } > + > ## > # @TpmTypeOptions: > # > @@ -124,6 +151,7 @@ > # > # @type: - 'passthrough' The configuration options for the TPM passthrough type > # - 'emulator' The configuration options for TPM emulator backend type > +# - 'mssim' The configuration options for TPM emulator mssim type > # > # Since: 1.5 > ## > @@ -131,7 +159,8 @@ > 'base': { 'type': 'TpmType' }, > 'discriminator': 'type', > 'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper', > - 'emulator': 'TPMEmulatorOptionsWrapper' }, > + 'emulator': 'TPMEmulatorOptionsWrapper', > + 'mssim': 'TPMmssimOptionsWrapper' }, > 'if': 'CONFIG_TPM' } > > ##
On Mon, 2022-12-12 at 08:43 -0500, Stefan Berger wrote: > > > On 12/10/22 12:10, James Bottomley wrote: > > The Microsoft Simulator (mssim) is the reference emulation platform > > for the TCG TPM 2.0 specification. > > > > https://github.com/Microsoft/ms-tpm-20-ref.git > > > > It exports a fairly simple network socket baset protocol on two > > baset -> based. > > > sockets, one for command (default 2321) and one for control > > (default 2322). This patch adds a simple backend that can speak > > the mssim protocol over the network. It also allows the host, and > > two ports to be specified on the qemu command line. The benefits > > are twofold: firstly it gives us a backend that actually speaks a > > standard TPM emulation protocol instead of the linux specific TPM > > driver format of the current emulated TPM backend and secondly, > > using the microsoft protocol, the end point of the emulator can be > > anywhere on the network, facilitating the cloud use case where a > > central TPM ervice can be used over a control network. > > > > The implementation does basic control commands like power off/on, > > but doesn't implement cancellation or startup. The former because > > cancellation is pretty much useless on a fast operating TPM > > emulator and the latter because this emulator is designed to be > > used with OVMF which itself does TPM startup and I wanted to > > validate that. > > How did you implement VM suspend/resume and snapshotting support? TPM2 doesn't need to. The mssim follows the reference model which obeys the TPM2_Shutdown protocol, so the software does a power off with TPM2_Shutdown(TPM_SU_STATE) This allows poweroff to preserve the PCR state, provided the startup does TPM2_Startup(TPM_SU_STATE). the edk2 SecurityPackage does this in OVMF on S3 Resume, so using this backend allows us to check the OVMF startup for correctness. Now getting QEMU to go through S3 suspend is another issue, but when it does, the TPM should just work. James
On 12/12/22 08:59, James Bottomley wrote: > On Mon, 2022-12-12 at 08:43 -0500, Stefan Berger wrote: >> >> >> On 12/10/22 12:10, James Bottomley wrote: >>> The Microsoft Simulator (mssim) is the reference emulation platform >>> for the TCG TPM 2.0 specification. >>> >>> https://github.com/Microsoft/ms-tpm-20-ref.git >>> >>> It exports a fairly simple network socket baset protocol on two >> >> baset -> based. >> >>> sockets, one for command (default 2321) and one for control >>> (default 2322). This patch adds a simple backend that can speak >>> the mssim protocol over the network. It also allows the host, and >>> two ports to be specified on the qemu command line. The benefits >>> are twofold: firstly it gives us a backend that actually speaks a >>> standard TPM emulation protocol instead of the linux specific TPM >>> driver format of the current emulated TPM backend and secondly, >>> using the microsoft protocol, the end point of the emulator can be >>> anywhere on the network, facilitating the cloud use case where a >>> central TPM ervice can be used over a control network. >>> >>> The implementation does basic control commands like power off/on, >>> but doesn't implement cancellation or startup. The former because >>> cancellation is pretty much useless on a fast operating TPM >>> emulator and the latter because this emulator is designed to be >>> used with OVMF which itself does TPM startup and I wanted to >>> validate that. >> >> How did you implement VM suspend/resume and snapshotting support? > > TPM2 doesn't need to. The mssim follows the reference model which You mean TPM2 doesn't need to resume at the point where the VM resumes (I am not talking about ACPI resume but virsh save/restore) after for example a host reboot? What does this have to do with the mssim reference model and TPM2_Shutdown protocol? > obeys the TPM2_Shutdown protocol, so the software does a power off with > > TPM2_Shutdown(TPM_SU_STATE) > > This allows poweroff to preserve the PCR state, provided the startup > does > > TPM2_Startup(TPM_SU_STATE). > > the edk2 SecurityPackage does this in OVMF on S3 Resume, so using this > backend allows us to check the OVMF startup for correctness. > > Now getting QEMU to go through S3 suspend is another issue, but when it > does, the TPM should just work. > > James >
On Mon, 2022-12-12 at 09:27 -0500, Stefan Berger wrote: > > > On 12/12/22 08:59, James Bottomley wrote: > > On Mon, 2022-12-12 at 08:43 -0500, Stefan Berger wrote: > > > > > > > > > On 12/10/22 12:10, James Bottomley wrote: > > > > The Microsoft Simulator (mssim) is the reference emulation > > > > platform > > > > for the TCG TPM 2.0 specification. > > > > > > > > https://github.com/Microsoft/ms-tpm-20-ref.git > > > > > > > > It exports a fairly simple network socket baset protocol on two > > > > > > baset -> based. > > > > > > > sockets, one for command (default 2321) and one for control > > > > (default 2322). This patch adds a simple backend that can > > > > speak the mssim protocol over the network. It also allows the > > > > host, and two ports to be specified on the qemu command line. > > > > The benefits are twofold: firstly it gives us a backend that > > > > actually speaks a standard TPM emulation protocol instead of > > > > the linux specific TPM driver format of the current emulated > > > > TPM backend and secondly, using the microsoft protocol, the end > > > > point of the emulator can be anywhere on the network, > > > > facilitating the cloud use case where a central TPM ervice can > > > > be used over a control network. > > > > > > > > The implementation does basic control commands like power > > > > off/on, but doesn't implement cancellation or startup. The > > > > former because cancellation is pretty much useless on a fast > > > > operating TPM emulator and the latter because this emulator is > > > > designed to be used with OVMF which itself does TPM startup and > > > > I wanted to validate that. > > > > > > How did you implement VM suspend/resume and snapshotting support? > > > > TPM2 doesn't need to. The mssim follows the reference model which > > > You mean TPM2 doesn't need to resume at the point where the VM > resumes (I am not talking about ACPI resume but virsh save/restore) > after for example a host reboot? > What does this have to do with the mssim reference model and > TPM2_Shutdown protocol? Running S3 suspend/resume before doing VM save/restore could fix a lot of issue with passthrough PCI and when QEMU gets around to doing that a TPM following the standard model should just work. It's useful to have a driver supporting this work. James
On 12/12/22 09:32, James Bottomley wrote: > On Mon, 2022-12-12 at 09:27 -0500, Stefan Berger wrote: >> >> >> On 12/12/22 08:59, James Bottomley wrote: >>> On Mon, 2022-12-12 at 08:43 -0500, Stefan Berger wrote: >>>> >>>> >>>> On 12/10/22 12:10, James Bottomley wrote: >>>>> The Microsoft Simulator (mssim) is the reference emulation >>>>> platform >>>>> for the TCG TPM 2.0 specification. >>>>> >>>>> https://github.com/Microsoft/ms-tpm-20-ref.git >>>>> >>>>> It exports a fairly simple network socket baset protocol on two >>>> >>>> baset -> based. >>>> >>>>> sockets, one for command (default 2321) and one for control >>>>> (default 2322). This patch adds a simple backend that can >>>>> speak the mssim protocol over the network. It also allows the >>>>> host, and two ports to be specified on the qemu command line. >>>>> The benefits are twofold: firstly it gives us a backend that >>>>> actually speaks a standard TPM emulation protocol instead of >>>>> the linux specific TPM driver format of the current emulated >>>>> TPM backend and secondly, using the microsoft protocol, the end >>>>> point of the emulator can be anywhere on the network, >>>>> facilitating the cloud use case where a central TPM ervice can >>>>> be used over a control network. >>>>> >>>>> The implementation does basic control commands like power >>>>> off/on, but doesn't implement cancellation or startup. The >>>>> former because cancellation is pretty much useless on a fast >>>>> operating TPM emulator and the latter because this emulator is >>>>> designed to be used with OVMF which itself does TPM startup and >>>>> I wanted to validate that. >>>> >>>> How did you implement VM suspend/resume and snapshotting support? >>> >>> TPM2 doesn't need to. The mssim follows the reference model which >> >> >> You mean TPM2 doesn't need to resume at the point where the VM >> resumes (I am not talking about ACPI resume but virsh save/restore) >> after for example a host reboot? >> What does this have to do with the mssim reference model and >> TPM2_Shutdown protocol? > > Running S3 suspend/resume before doing VM save/restore could fix a lot > of issue with passthrough PCI and when QEMU gets around to doing that a > TPM following the standard model should just work. It's useful to have > a driver supporting this work. Did you test it with virsh save / restore with the mssim TPM? Does it work? Does it work if you reboot the host in between? Stefan > > James >
On Mon, 2022-12-12 at 09:44 -0500, Stefan Berger wrote: > > > On 12/12/22 09:32, James Bottomley wrote: > > On Mon, 2022-12-12 at 09:27 -0500, Stefan Berger wrote: > > > > > > > > > On 12/12/22 08:59, James Bottomley wrote: > > > > On Mon, 2022-12-12 at 08:43 -0500, Stefan Berger wrote: > > > > > > > > > > > > > > > On 12/10/22 12:10, James Bottomley wrote: > > > > > > The Microsoft Simulator (mssim) is the reference emulation > > > > > > platform > > > > > > for the TCG TPM 2.0 specification. > > > > > > > > > > > > https://github.com/Microsoft/ms-tpm-20-ref.git > > > > > > > > > > > > It exports a fairly simple network socket baset protocol on > > > > > > two > > > > > > > > > > baset -> based. > > > > > > > > > > > sockets, one for command (default 2321) and one for control > > > > > > (default 2322). This patch adds a simple backend that can > > > > > > speak the mssim protocol over the network. It also allows > > > > > > the > > > > > > host, and two ports to be specified on the qemu command > > > > > > line. > > > > > > The benefits are twofold: firstly it gives us a backend > > > > > > that > > > > > > actually speaks a standard TPM emulation protocol instead > > > > > > of > > > > > > the linux specific TPM driver format of the current > > > > > > emulated > > > > > > TPM backend and secondly, using the microsoft protocol, the > > > > > > end > > > > > > point of the emulator can be anywhere on the network, > > > > > > facilitating the cloud use case where a central TPM ervice > > > > > > can > > > > > > be used over a control network. > > > > > > > > > > > > The implementation does basic control commands like power > > > > > > off/on, but doesn't implement cancellation or startup. The > > > > > > former because cancellation is pretty much useless on a > > > > > > fast > > > > > > operating TPM emulator and the latter because this emulator > > > > > > is > > > > > > designed to be used with OVMF which itself does TPM startup > > > > > > and > > > > > > I wanted to validate that. > > > > > > > > > > How did you implement VM suspend/resume and snapshotting > > > > > support? > > > > > > > > TPM2 doesn't need to. The mssim follows the reference model > > > > which > > > > > > > > > You mean TPM2 doesn't need to resume at the point where the VM > > > resumes (I am not talking about ACPI resume but virsh > > > save/restore) > > > after for example a host reboot? > > > What does this have to do with the mssim reference model and > > > TPM2_Shutdown protocol? > > > > Running S3 suspend/resume before doing VM save/restore could fix a > > lot of issue with passthrough PCI and when QEMU gets around to > > doing that a TPM following the standard model should just work. > > It's useful to have a driver supporting this work. > Did you test it with virsh save / restore with the mssim TPM? Does it > work? Does it work if you reboot the host in between? I don't actually use virsh in my harness. I'm mostly interested in the running the kernel TPM selftests against the reference model. But I anticipate it wouldn't currently work because I don't believe virsh triggers a S3 event which is why snapshot and migration doesn't always work with PCI passthrough. James
On 12/12/22 09:47, James Bottomley wrote: > On Mon, 2022-12-12 at 09:44 -0500, Stefan Berger wrote: >> >> >> On 12/12/22 09:32, James Bottomley wrote: >>> On Mon, 2022-12-12 at 09:27 -0500, Stefan Berger wrote: >>>> >>>> >>>> On 12/12/22 08:59, James Bottomley wrote: >>>>> On Mon, 2022-12-12 at 08:43 -0500, Stefan Berger wrote: >>>>>> >>>>>> >>>>>> On 12/10/22 12:10, James Bottomley wrote: >>>>>>> The Microsoft Simulator (mssim) is the reference emulation >>>>>>> platform >>>>>>> for the TCG TPM 2.0 specification. >>>>>>> >>>>>>> https://github.com/Microsoft/ms-tpm-20-ref.git >>>>>>> >>>>>>> It exports a fairly simple network socket baset protocol on >>>>>>> two >>>>>> >>>>>> baset -> based. >>>>>> >>>>>>> sockets, one for command (default 2321) and one for control >>>>>>> (default 2322). This patch adds a simple backend that can >>>>>>> speak the mssim protocol over the network. It also allows >>>>>>> the >>>>>>> host, and two ports to be specified on the qemu command >>>>>>> line. >>>>>>> The benefits are twofold: firstly it gives us a backend >>>>>>> that >>>>>>> actually speaks a standard TPM emulation protocol instead >>>>>>> of >>>>>>> the linux specific TPM driver format of the current >>>>>>> emulated >>>>>>> TPM backend and secondly, using the microsoft protocol, the >>>>>>> end >>>>>>> point of the emulator can be anywhere on the network, >>>>>>> facilitating the cloud use case where a central TPM ervice >>>>>>> can >>>>>>> be used over a control network. >>>>>>> >>>>>>> The implementation does basic control commands like power >>>>>>> off/on, but doesn't implement cancellation or startup. The >>>>>>> former because cancellation is pretty much useless on a >>>>>>> fast >>>>>>> operating TPM emulator and the latter because this emulator >>>>>>> is >>>>>>> designed to be used with OVMF which itself does TPM startup >>>>>>> and >>>>>>> I wanted to validate that. >>>>>> >>>>>> How did you implement VM suspend/resume and snapshotting >>>>>> support? >>>>> >>>>> TPM2 doesn't need to. The mssim follows the reference model >>>>> which >>>> >>>> >>>> You mean TPM2 doesn't need to resume at the point where the VM >>>> resumes (I am not talking about ACPI resume but virsh >>>> save/restore) >>>> after for example a host reboot? >>>> What does this have to do with the mssim reference model and >>>> TPM2_Shutdown protocol? >>> >>> Running S3 suspend/resume before doing VM save/restore could fix a >>> lot of issue with passthrough PCI and when QEMU gets around to >>> doing that a TPM following the standard model should just work. >>> It's useful to have a driver supporting this work. >> Did you test it with virsh save / restore with the mssim TPM? Does it >> work? Does it work if you reboot the host in between? > > I don't actually use virsh in my harness. I'm mostly interested in the > running the kernel TPM selftests against the reference model. But I > anticipate it wouldn't currently work because I don't believe virsh > triggers a S3 event which is why snapshot and migration doesn't always > work with PCI passthrough. Then I think you should at least add a blocker to your model so that suspend/resume/snapshotting/migration are all disabled because the mssim reference implementation doesn't support permanent & volatile state suspend/resume (and upgrading!) without significant work on it as can be seen in libtpms. Why would we support another model for the backend that provides no advantages over what is there right now? Stefan > > James > > > >
On Mon, 2022-12-12 at 10:20 -0500, Stefan Berger wrote: > On 12/12/22 09:47, James Bottomley wrote: [...] > > I don't actually use virsh in my harness. I'm mostly interested in > > the running the kernel TPM selftests against the reference model. > > But I anticipate it wouldn't currently work because I don't believe > > virsh triggers a S3 event which is why snapshot and migration > > doesn't always work with PCI passthrough. > > Then I think you should at least add a blocker to your model so that > suspend/resume/snapshotting/migration are all disabled because the > mssim reference implementation doesn't support permanent & volatile > state suspend/resume (and upgrading!) without significant work on it > as can be seen in libtpms. Actually, I would think adding support, if that's what people wanted, would be pretty simple. Since the network end point is the identifier, the protocol would be not to power down the TPM on suspend/resume and simply to send TPM_STOP to close down the sockets gracefully. Then the next connection picks up the state where the previous one left off. > Why would we support another model for the backend that provides no > advantages over what is there right now? The advantages were what was stated: ability to connect to the MS reference model directly and no dependence on the Linux VTPM_PROXY protocol. James
On 12/12/22 10:28, James Bottomley wrote: > On Mon, 2022-12-12 at 10:20 -0500, Stefan Berger wrote: >> On 12/12/22 09:47, James Bottomley wrote: > [...] >>> I don't actually use virsh in my harness. I'm mostly interested in >>> the running the kernel TPM selftests against the reference model. >>> But I anticipate it wouldn't currently work because I don't believe >>> virsh triggers a S3 event which is why snapshot and migration >>> doesn't always work with PCI passthrough. >> >> Then I think you should at least add a blocker to your model so that >> suspend/resume/snapshotting/migration are all disabled because the >> mssim reference implementation doesn't support permanent & volatile >> state suspend/resume (and upgrading!) without significant work on it >> as can be seen in libtpms. > > Actually, I would think adding support, if that's what people wanted, > would be pretty simple. Since the network end point is the identifier, There's VM snapshotting as well where things are not as simple. Host reboot is a bit of a challenge when your TPM 2 emulator doesn't support permanent AND volatile state marshalling and unmarshalling. Upgrading the reference model has also been a challenge in the past where it couldn't read old state anymore when new pieces were added to the state. These were areas where efforts went into libtpms for example. This is not to say that everything is perfect with libtpms and swptm since they have thier own challenges but they have at least resolved some of the issues. > the protocol would be not to power down the TPM on suspend/resume and > simply to send TPM_STOP to close down the sockets gracefully. Then the > next connection picks up the state where the previous one left off. > >> Why would we support another model for the backend that provides no >> advantages over what is there right now? > > The advantages were what was stated: ability to connect to the MS > reference model directly and no dependence on the Linux VTPM_PROXY > protocol. We already have a working TPM 2 emulator that does support VM suspend/resume/snapshotting and migration. If you want to become maintainer of your backend model and everything associated with it, please add yourself to the MAINTAINERS list. > > James >
Copy'ing Markus for QAPI design feedback. On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: > The Microsoft Simulator (mssim) is the reference emulation platform > for the TCG TPM 2.0 specification. > > https://github.com/Microsoft/ms-tpm-20-ref.git > > It exports a fairly simple network socket baset protocol on two > sockets, one for command (default 2321) and one for control (default > 2322). This patch adds a simple backend that can speak the mssim > protocol over the network. It also allows the host, and two ports to > be specified on the qemu command line. The benefits are twofold: > firstly it gives us a backend that actually speaks a standard TPM > emulation protocol instead of the linux specific TPM driver format of > the current emulated TPM backend and secondly, using the microsoft > protocol, the end point of the emulator can be anywhere on the > network, facilitating the cloud use case where a central TPM service > can be used over a control network. What's the story with security for this ? The patch isn't using TLS, so talking to any emulator over anything other than localhost looks insecure, unless I'm missing something. > diff --git a/backends/tpm/tpm_mssim.c b/backends/tpm/tpm_mssim.c > new file mode 100644 > index 0000000000..6864b1fbc0 > --- /dev/null > +++ b/backends/tpm/tpm_mssim.c > @@ -0,0 +1,266 @@ > +/* > + * Emulator TPM driver which connects over the mssim protocol > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * Copyright (c) 2022 Copyright by whom ? Presumably this line should have "IBM" present if we're going to have it at all. > + * Author: James Bottomley <jejb@linux.ibm.com> > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/error-report.h" > +#include "qemu/sockets.h" > + > +#include "qapi/clone-visitor.h" > +#include "qapi/qapi-visit-tpm.h" > + > +#include "io/channel-socket.h" > + > +#include "sysemu/tpm_backend.h" > +#include "sysemu/tpm_util.h" > + > +#include "qom/object.h" > + > +#include "tpm_int.h" > +#include "tpm_mssim.h" > + > +static TPMBackend *tpm_mssim_create(QemuOpts *opts) > +{ > + TPMBackend *be = TPM_BACKEND(object_new(TYPE_TPM_MSSIM)); > + TPMmssim *t = TPM_MSSIM(be); > + InetSocketAddress cmd_s, ctl_s; > + int sock; > + const char *host, *port, *ctrl; > + Error *errp = NULL; > + > + host = qemu_opt_get(opts, "host"); > + if (!host) > + host = "localhost"; > + t->opts.host = g_strdup(host); > + > + port = qemu_opt_get(opts, "port"); > + if (!port) > + port = "2321"; > + t->opts.port = g_strdup(port); > + > + ctrl = qemu_opt_get(opts, "ctrl"); > + if (!ctrl) > + ctrl = "2322"; > + t->opts.ctrl = g_strdup(ctrl); > + > + cmd_s.host = (char *)host; > + cmd_s.port = (char *)port; > + > + ctl_s.host = (char *)host; > + ctl_s.port = (char *)ctrl; > + > + sock = inet_connect_saddr(&cmd_s, &errp); > + if (sock < 0) > + goto fail; > + t->cmd_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, &errp)); > + if (errp) > + goto fail; > + sock = inet_connect_saddr(&ctl_s, &errp); > + if (sock < 0) > + goto fail_unref_cmd; > + t->ctrl_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, &errp)); > + if (errp) > + goto fail_unref_cmd; We don't want to be using inet_connect_saddr, that's a legacy API. All new code should be using the qio_channel_socket_connect* family of APIs. This is trivial if the QAPI design uses SocketAddress structs directly. > + > + /* reset the TPM using a power cycle sequence, in case someone > + * has previously powered it up */ > + sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, &errp); > + if (sock != 0) > + goto fail_unref; > + sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_ON, &errp); > + if (sock != 0) > + goto fail_unref; > + sock = tpm_send_ctrl(t, TPM_SIGNAL_NV_ON, &errp); > + if (sock != 0) > + goto fail_unref; > + > + return be; > + fail_unref: > + object_unref(OBJECT(t->ctrl_qc)); > + fail_unref_cmd: > + object_unref(OBJECT(t->cmd_qc)); > + fail: > + error_prepend(&errp, ERROR_PREFIX); > + error_report_err(errp); > + object_unref(OBJECT(be)); > + > + return NULL; > +} > + > +static const QemuOptDesc tpm_mssim_cmdline_opts[] = { > + TPM_STANDARD_CMDLINE_OPTS, > + { > + .name = "host", > + .type = QEMU_OPT_STRING, > + .help = "name or IP address of host to connect to (deault localhost)", > + }, > + { > + .name = "port", > + .type = QEMU_OPT_STRING, > + .help = "port number for standard TPM commands (default 2321)", > + }, > + { > + .name = "ctrl", > + .type = QEMU_OPT_STRING, > + .help = "control port for TPM commands (default 2322)", > + }, > +}; > + > +static void tpm_mssim_class_init(ObjectClass *klass, void *data) > +{ > + TPMBackendClass *cl = TPM_BACKEND_CLASS(klass); > + > + cl->type = TPM_TYPE_MSSIM; > + cl->opts = tpm_mssim_cmdline_opts; > + cl->desc = "TPM mssim emulator backend driver"; > + cl->create = tpm_mssim_create; > + cl->cancel_cmd = tpm_mssim_cancel_cmd; > + cl->get_tpm_version = tpm_mssim_get_version; > + cl->get_buffer_size = tpm_mssim_get_buffer_size; > + cl->get_tpm_options = tpm_mssim_get_opts; > + cl->handle_request = tpm_mssim_handle_request; > +} > > +## > +# @TPMmssimOptions: > +# > +# Information for the mssim emulator connection > +# > +# @host: host name or IP address to connect to > +# @port: port for the standard TPM commands > +# @ctrl: control port for TPM state changes > +# > +# Since: 7.2.0 > +## > +{ 'struct': 'TPMmssimOptions', > + 'data': { > + 'host': 'str', > + 'port': 'str', > + 'ctrl': 'str' }, > + 'if': 'CONFIG_TPM' } We don't want to be adding new code using plain host/port combos, as that misses extra functionality for controlling IPv4 vs IPv6 usage. The existing 'emulator' backend references a chardev, but I'm not especially in favour of using the chardev indirection either, when all we should really need is a SocketAddress IOW, from a QAPI design POV, IMHO the best practice would be { 'struct': 'TPMmssimOptions', 'data': { 'command': 'SocketAddress', 'control': 'SocketAddress' }, 'if': 'CONFIG_TPM' } The main wrinkle with this is that exprssing nested struct fields with QemuOpts is a disaster zone, and -tpmdev doesn't yet support JSON syntax. IMHO we should just fix the latter problem, as I don't think it ought to be too hard. Probably a cut+paste / search/replace job on the chanmge we did for -device in: commit 5dacda5167560b3af8eadbce5814f60ba44b467e Author: Kevin Wolf <kwolf@redhat.com> Date: Fri Oct 8 15:34:42 2021 +0200 vl: Enable JSON syntax for -device This would mean we could use plain -tpmdev for a local instance -tpmdev mssim,id=tpm0 \ -device tpm-crb,tpmdev=tpm0 \ but to use a remote emulator we would use -tpmdev "{'backend': 'mssim', 'id': 'tpm0', 'command': { 'type': 'inet', 'host': 'remote', 'port': '4455' }, 'control': { 'type': 'inet', 'host': 'remote', 'port': '4456' }}" (without the whitepace/newlines, which i just used for sake of clarity) With regards, Daniel
On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: > Copy'ing Markus for QAPI design feedback. > > On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: > > The Microsoft Simulator (mssim) is the reference emulation platform > > for the TCG TPM 2.0 specification. > > > > https://github.com/Microsoft/ms-tpm-20-ref.git > > > > It exports a fairly simple network socket baset protocol on two > > sockets, one for command (default 2321) and one for control > > (default 2322). This patch adds a simple backend that can speak > > the mssim protocol over the network. It also allows the host, and > > two ports to be specified on the qemu command line. The benefits > > are twofold: firstly it gives us a backend that actually speaks a > > standard TPM emulation protocol instead of the linux specific TPM > > driver format of the current emulated TPM backend and secondly, > > using the microsoft protocol, the end point of the emulator can be > > anywhere on the network, facilitating the cloud use case where a > > central TPM service can be used over a control network. > > What's the story with security for this ? The patch isn't using > TLS, so talking to any emulator over anything other than localhost > looks insecure, unless I'm missing something. Pretty much every TPM application fears interposers and should thus be using the TPM transport security anyway. *If* this is the case, then the transport is secure. Note that this currently isn't the case for the kernel use of the TPM, but I'm trying to fix that. The standard mssim server is too simplistic to do transport layer security, but like everything that does this (or rather doesn't do this), you can front it with stunnel4. > > diff --git a/backends/tpm/tpm_mssim.c b/backends/tpm/tpm_mssim.c > > new file mode 100644 > > index 0000000000..6864b1fbc0 > > --- /dev/null > > +++ b/backends/tpm/tpm_mssim.c > > @@ -0,0 +1,266 @@ > > +/* > > + * Emulator TPM driver which connects over the mssim protocol > > + * SPDX-License-Identifier: GPL-2.0-or-later > > + * > > + * Copyright (c) 2022 > > Copyright by whom ? Presumably this line should have "IBM" present > if we're going to have it at all. It can either be me or IBM, we're joint owners, that's why I thought just author. > > + * Author: James Bottomley <jejb@linux.ibm.com> > > + */ > > + > > +#include "qemu/osdep.h" > > +#include "qemu/error-report.h" > > +#include "qemu/sockets.h" > > + > > +#include "qapi/clone-visitor.h" > > +#include "qapi/qapi-visit-tpm.h" > > + > > +#include "io/channel-socket.h" > > + > > +#include "sysemu/tpm_backend.h" > > +#include "sysemu/tpm_util.h" > > + > > +#include "qom/object.h" > > + > > +#include "tpm_int.h" > > +#include "tpm_mssim.h" > > + > > > +static TPMBackend *tpm_mssim_create(QemuOpts *opts) > > +{ > > + TPMBackend *be = TPM_BACKEND(object_new(TYPE_TPM_MSSIM)); > > + TPMmssim *t = TPM_MSSIM(be); > > + InetSocketAddress cmd_s, ctl_s; > > + int sock; > > + const char *host, *port, *ctrl; > > + Error *errp = NULL; > > + > > + host = qemu_opt_get(opts, "host"); > > + if (!host) > > + host = "localhost"; > > + t->opts.host = g_strdup(host); > > + > > + port = qemu_opt_get(opts, "port"); > > + if (!port) > > + port = "2321"; > > + t->opts.port = g_strdup(port); > > + > > + ctrl = qemu_opt_get(opts, "ctrl"); > > + if (!ctrl) > > + ctrl = "2322"; > > + t->opts.ctrl = g_strdup(ctrl); > > + > > + cmd_s.host = (char *)host; > > + cmd_s.port = (char *)port; > > + > > + ctl_s.host = (char *)host; > > + ctl_s.port = (char *)ctrl; > > + > > + sock = inet_connect_saddr(&cmd_s, &errp); > > + if (sock < 0) > > + goto fail; > > + t->cmd_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, > > &errp)); > > + if (errp) > > + goto fail; > > + sock = inet_connect_saddr(&ctl_s, &errp); > > + if (sock < 0) > > + goto fail_unref_cmd; > > + t->ctrl_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, > > &errp)); > > + if (errp) > > + goto fail_unref_cmd; > > We don't want to be using inet_connect_saddr, that's a legacy > API. All new code should be using the qio_channel_socket_connect* > family of APIs. This is trivial if the QAPI design uses SocketAddress > structs directly. Heh, well I just copied this from the ssh block backend ... I can easily find something more modern to update it. [...] > > > > +## > > +# @TPMmssimOptions: > > +# > > +# Information for the mssim emulator connection > > +# > > +# @host: host name or IP address to connect to > > +# @port: port for the standard TPM commands > > +# @ctrl: control port for TPM state changes > > +# > > +# Since: 7.2.0 > > +## > > +{ 'struct': 'TPMmssimOptions', > > + 'data': { > > + 'host': 'str', > > + 'port': 'str', > > + 'ctrl': 'str' }, > > + 'if': 'CONFIG_TPM' } > > We don't want to be adding new code using plain host/port combos, > as that misses extra functionality for controlling IPv4 vs IPv6 > usage. > > The existing 'emulator' backend references a chardev, but I'm > not especially in favour of using the chardev indirection either, > when all we should really need is a SocketAddress Unfortunately chardev isn't a socket, it really is a character device that fronts to the vtpm kernel proxy, so even if I convert mssim usage to socket, you'll still have to keep chardev for the emulator backend. > > IOW, from a QAPI design POV, IMHO the best practice would be > > { 'struct': 'TPMmssimOptions', > 'data': { > 'command': 'SocketAddress', > 'control': 'SocketAddress' }, > 'if': 'CONFIG_TPM' } > > > The main wrinkle with this is that exprssing nested struct fields > with QemuOpts is a disaster zone, and -tpmdev doesn't yet support > JSON syntax. > > IMHO we should just fix the latter problem, as I don't think it > ought to be too hard. Probably a cut+paste / search/replace job > on the chanmge we did for -device in: > > commit 5dacda5167560b3af8eadbce5814f60ba44b467e > Author: Kevin Wolf <kwolf@redhat.com> > Date: Fri Oct 8 15:34:42 2021 +0200 > > vl: Enable JSON syntax for -device > > This would mean we could use plain -tpmdev for a local instance > > -tpmdev mssim,id=tpm0 \ > -device tpm-crb,tpmdev=tpm0 \ > > but to use a remote emulator we would use > > -tpmdev "{'backend': 'mssim', 'id': 'tpm0', > 'command': { > 'type': 'inet', > 'host': 'remote', > 'port': '4455' > }, > 'control': { > 'type': 'inet', > 'host': 'remote', > 'port': '4456' > }}" > > (without the whitepace/newlines, which i just used for sake of > clarity) OK, I'll look into doing this. Regards, James
On 12/12/22 11:38, James Bottomley wrote: > On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: >> Copy'ing Markus for QAPI design feedback. >> >> On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: >>> The Microsoft Simulator (mssim) is the reference emulation platform >>> for the TCG TPM 2.0 specification. >>> >>> https://github.com/Microsoft/ms-tpm-20-ref.git >>> >>> It exports a fairly simple network socket baset protocol on two >>> sockets, one for command (default 2321) and one for control >>> (default 2322). This patch adds a simple backend that can speak >>> the mssim protocol over the network. It also allows the host, and >>> two ports to be specified on the qemu command line. The benefits >>> are twofold: firstly it gives us a backend that actually speaks a >>> standard TPM emulation protocol instead of the linux specific TPM >>> driver format of the current emulated TPM backend and secondly, >>> using the microsoft protocol, the end point of the emulator can be >>> anywhere on the network, facilitating the cloud use case where a >>> central TPM service can be used over a control network. >> >> What's the story with security for this ? The patch isn't using >> TLS, so talking to any emulator over anything other than localhost >> looks insecure, unless I'm missing something. > > Pretty much every TPM application fears interposers and should thus be > using the TPM transport security anyway. *If* this is the case, then > the transport is secure. Note that this currently isn't the case for What about all the older kernels that are out there? > the kernel use of the TPM, but I'm trying to fix that. The standard > mssim server is too simplistic to do transport layer security, but like > everything that does this (or rather doesn't do this), you can front it > with stunnel4. And who or what is going to set this up? Stefan
On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: > > > On 12/12/22 11:38, James Bottomley wrote: > > On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: > > > Copy'ing Markus for QAPI design feedback. > > > > > > On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: > > > > The Microsoft Simulator (mssim) is the reference emulation > > > > platform for the TCG TPM 2.0 specification. > > > > > > > > https://github.com/Microsoft/ms-tpm-20-ref.git > > > > > > > > It exports a fairly simple network socket baset protocol on two > > > > sockets, one for command (default 2321) and one for control > > > > (default 2322). This patch adds a simple backend that can > > > > speak the mssim protocol over the network. It also allows the > > > > host, and two ports to be specified on the qemu command line. > > > > The benefits are twofold: firstly it gives us a backend that > > > > actually speaks a standard TPM emulation protocol instead of > > > > the linux specific TPM driver format of the current emulated > > > > TPM backend and secondly, using the microsoft protocol, the end > > > > point of the emulator can be anywhere on the network, > > > > facilitating the cloud use case where a central TPM service can > > > > be used over a control network. > > > > > > What's the story with security for this ? The patch isn't using > > > TLS, so talking to any emulator over anything other than > > > localhost looks insecure, unless I'm missing something. > > > > Pretty much every TPM application fears interposers and should thus > > be using the TPM transport security anyway. *If* this is the case, > > then the transport is secure. Note that this currently isn't the > > case for > > What about all the older kernels that are out there? No current kernel uses transport security. In the event the patch eventually gets upstream, the kernel be secure against interposer attacks going forwards. I would imagine there might be pressure to backport the patch given the current level of worry about interposers. > > the kernel use of the TPM, but I'm trying to fix that. The > > standard mssim server is too simplistic to do transport layer > > security, but like everything that does this (or rather doesn't do > > this), you can front it with stunnel4. > > And who or what is going to set this up? I'm not sure I understand the question. Stunnel4 is mostly used to convert unencrypted proxies like imap on 143 or smtp on 25 to the secure version. Most people who run servers are fairly familiar with using it. It's what IBM used for encrypted migration initially. You can run stunnel on both ends, or the qemu side could be built in using the qemu tls-creds way of doing things but anything running the standard MS server would have to front it with stunnel still. James
On 12/12/22 13:48, James Bottomley wrote: > On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: >> >> >> On 12/12/22 11:38, James Bottomley wrote: >>> On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: >>>> Copy'ing Markus for QAPI design feedback. >>>> >>>> On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: >>>>> The Microsoft Simulator (mssim) is the reference emulation >>>>> platform for the TCG TPM 2.0 specification. >>>>> >>>>> https://github.com/Microsoft/ms-tpm-20-ref.git >>>>> >>>>> It exports a fairly simple network socket baset protocol on two >>>>> sockets, one for command (default 2321) and one for control >>>>> (default 2322). This patch adds a simple backend that can >>>>> speak the mssim protocol over the network. It also allows the >>>>> host, and two ports to be specified on the qemu command line. >>>>> The benefits are twofold: firstly it gives us a backend that >>>>> actually speaks a standard TPM emulation protocol instead of >>>>> the linux specific TPM driver format of the current emulated >>>>> TPM backend and secondly, using the microsoft protocol, the end >>>>> point of the emulator can be anywhere on the network, >>>>> facilitating the cloud use case where a central TPM service can >>>>> be used over a control network. >>>> >>>> What's the story with security for this ? The patch isn't using >>>> TLS, so talking to any emulator over anything other than >>>> localhost looks insecure, unless I'm missing something. >>> >>> Pretty much every TPM application fears interposers and should thus >>> be using the TPM transport security anyway. *If* this is the case, >>> then the transport is secure. Note that this currently isn't the >>> case for >> >> What about all the older kernels that are out there? > > No current kernel uses transport security. In the event the patch > eventually gets upstream, the kernel be secure against interposer > attacks going forwards. I would imagine there might be pressure to > backport the patch given the current level of worry about interposers. > >>> the kernel use of the TPM, but I'm trying to fix that. The >>> standard mssim server is too simplistic to do transport layer >>> security, but like everything that does this (or rather doesn't do >>> this), you can front it with stunnel4. >> >> And who or what is going to set this up? > > I'm not sure I understand the question. Stunnel4 is mostly used to > convert unencrypted proxies like imap on 143 or smtp on 25 to the > secure version. Most people who run servers are fairly familiar with > using it. It's what IBM used for encrypted migration initially. You > can run stunnel on both ends, or the qemu side could be built in using > the qemu tls-creds way of doing things but anything running the > standard MS server would have to front it with stunnel still. So it's up to libvirt to setup stunnel to support a completely different setup than what it has for swtpm already? Stefan > > James >
On Mon, 2022-12-12 at 13:58 -0500, Stefan Berger wrote: > On 12/12/22 13:48, James Bottomley wrote: > > On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: > > > On 12/12/22 11:38, James Bottomley wrote: [...] > > > > the kernel use of the TPM, but I'm trying to fix that. The > > > > standard mssim server is too simplistic to do transport layer > > > > security, but like everything that does this (or rather doesn't > > > > do this), you can front it with stunnel4. > > > > > > And who or what is going to set this up? > > > > I'm not sure I understand the question. Stunnel4 is mostly used to > > convert unencrypted proxies like imap on 143 or smtp on 25 to the > > secure version. Most people who run servers are fairly familiar > > with using it. It's what IBM used for encrypted migration > > initially. You can run stunnel on both ends, or the qemu side > > could be built in using the qemu tls-creds way of doing things but > > anything running the standard MS server would have to front it with > > stunnel still. > > So it's up to libvirt to setup stunnel to support a completely > different setup than what it has for swtpm already? I don't think so, no. Libvirt doesn't usually help with server setup (witness the complexity of setting up a server side vtpm proxy) so in the case tls-creds were built in, it would just work if the object is specified. The complexity is all on the server side to front it with stunnel. James
On 12/12/22 14:12, James Bottomley wrote: > On Mon, 2022-12-12 at 13:58 -0500, Stefan Berger wrote: >> On 12/12/22 13:48, James Bottomley wrote: >>> On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: >>>> On 12/12/22 11:38, James Bottomley wrote: > [...] >>>>> the kernel use of the TPM, but I'm trying to fix that. The >>>>> standard mssim server is too simplistic to do transport layer >>>>> security, but like everything that does this (or rather doesn't >>>>> do this), you can front it with stunnel4. >>>> >>>> And who or what is going to set this up? >>> >>> I'm not sure I understand the question. Stunnel4 is mostly used to >>> convert unencrypted proxies like imap on 143 or smtp on 25 to the >>> secure version. Most people who run servers are fairly familiar >>> with using it. It's what IBM used for encrypted migration >>> initially. You can run stunnel on both ends, or the qemu side >>> could be built in using the qemu tls-creds way of doing things but >>> anything running the standard MS server would have to front it with >>> stunnel still. >> >> So it's up to libvirt to setup stunnel to support a completely >> different setup than what it has for swtpm already? > > I don't think so, no. Libvirt doesn't usually help with server setup > (witness the complexity of setting up a server side vtpm proxy) so in > the case tls-creds were built in, it would just work if the object is I see, so you are extending the TPM emulator with TLS on the client side so you don't need another tool to setup a TLS connection from the QEMU/client side. Is the server side across the network or on the same host? Either way, what is the latency that this introduces because I would expect that this slows down IMA since the PCR extensions & TPM 2 response now go back and forth across the network? Stefan > specified. The complexity is all on the server side to front it with > stunnel. > > James >
On 12/12/22 14:32, Stefan Berger wrote: > > > On 12/12/22 14:12, James Bottomley wrote: >> On Mon, 2022-12-12 at 13:58 -0500, Stefan Berger wrote: >>> On 12/12/22 13:48, James Bottomley wrote: >>>> On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: >>>>> On 12/12/22 11:38, James Bottomley wrote: >> [...] >>>>>> the kernel use of the TPM, but I'm trying to fix that. The >>>>>> standard mssim server is too simplistic to do transport layer >>>>>> security, but like everything that does this (or rather doesn't >>>>>> do this), you can front it with stunnel4. >>>>> >>>>> And who or what is going to set this up? >>>> >>>> I'm not sure I understand the question. Stunnel4 is mostly used to >>>> convert unencrypted proxies like imap on 143 or smtp on 25 to the >>>> secure version. Most people who run servers are fairly familiar >>>> with using it. It's what IBM used for encrypted migration >>>> initially. You can run stunnel on both ends, or the qemu side >>>> could be built in using the qemu tls-creds way of doing things but >>>> anything running the standard MS server would have to front it with >>>> stunnel still. >>> >>> So it's up to libvirt to setup stunnel to support a completely >>> different setup than what it has for swtpm already? >> >> I don't think so, no. Libvirt doesn't usually help with server setup >> (witness the complexity of setting up a server side vtpm proxy) so in >> the case tls-creds were built in, it would just work if the object is > > I see, so you are extending the TPM emulator with TLS on the client side so you don't need another tool to setup a TLS connection from the QEMU/client side. s/TPM emulator/TPM backend/ > > Is the server side across the network or on the same host? Either way, what is the latency that this introduces because I would expect that this slows down IMA since the PCR extensions & TPM 2 response now go back and forth across the network? > > Stefan > >> specified. The complexity is all on the server side to front it with >> stunnel. >> >> James >> >
On Mon, 2022-12-12 at 14:32 -0500, Stefan Berger wrote: > > > On 12/12/22 14:12, James Bottomley wrote: > > On Mon, 2022-12-12 at 13:58 -0500, Stefan Berger wrote: > > > On 12/12/22 13:48, James Bottomley wrote: > > > > On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: > > > > > On 12/12/22 11:38, James Bottomley wrote: > > [...] > > > > > > the kernel use of the TPM, but I'm trying to fix that. The > > > > > > standard mssim server is too simplistic to do transport > > > > > > layer > > > > > > security, but like everything that does this (or rather > > > > > > doesn't > > > > > > do this), you can front it with stunnel4. > > > > > > > > > > And who or what is going to set this up? > > > > > > > > I'm not sure I understand the question. Stunnel4 is mostly > > > > used to > > > > convert unencrypted proxies like imap on 143 or smtp on 25 to > > > > the > > > > secure version. Most people who run servers are fairly > > > > familiar > > > > with using it. It's what IBM used for encrypted migration > > > > initially. You can run stunnel on both ends, or the qemu side > > > > could be built in using the qemu tls-creds way of doing things > > > > but > > > > anything running the standard MS server would have to front it > > > > with > > > > stunnel still. > > > > > > So it's up to libvirt to setup stunnel to support a completely > > > different setup than what it has for swtpm already? > > > > I don't think so, no. Libvirt doesn't usually help with server > > setup (witness the complexity of setting up a server side vtpm > > proxy) so in the case tls-creds were built in, it would just work > > if the object is > > I see, so you are extending the TPM emulator with TLS on the client > side so you don't need another tool to setup a TLS connection from > the QEMU/client side. I didn't say I would do this, just that it's an easy possibility with the current qemu framework. I actually need to fiddle with the TPM externally to do some of my testing (like platform reset injection) so I won't use TLS anyway. > Is the server side across the network or on the same host? It can be either. > Either way, what is the latency that this introduces because I would > expect that this slows down IMA since the PCR extensions & TPM 2 > response now go back and forth across the network? Most data centre protocols are now encrypted and networked (NVMeoF would probably be the poster child) with no real ill effects. In terms of a TPM, the competition is an underpowered discrete chip over a slow serial bus, so I think we'll actually improve the latency not diminish it. James
On 12/12/22 16:36, James Bottomley wrote: > On Mon, 2022-12-12 at 14:32 -0500, Stefan Berger wrote: >> >> >> On 12/12/22 14:12, James Bottomley wrote: >>> On Mon, 2022-12-12 at 13:58 -0500, Stefan Berger wrote: >>>> On 12/12/22 13:48, James Bottomley wrote: >>>>> On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: >>>>>> On 12/12/22 11:38, James Bottomley wrote: >>> [...] >>>>>>> the kernel use of the TPM, but I'm trying to fix that. The >>>>>>> standard mssim server is too simplistic to do transport >>>>>>> layer >>>>>>> security, but like everything that does this (or rather >>>>>>> doesn't >>>>>>> do this), you can front it with stunnel4. >>>>>> >>>>>> And who or what is going to set this up? >>>>> >>>>> I'm not sure I understand the question. Stunnel4 is mostly >>>>> used to >>>>> convert unencrypted proxies like imap on 143 or smtp on 25 to >>>>> the >>>>> secure version. Most people who run servers are fairly >>>>> familiar >>>>> with using it. It's what IBM used for encrypted migration >>>>> initially. You can run stunnel on both ends, or the qemu side >>>>> could be built in using the qemu tls-creds way of doing things >>>>> but >>>>> anything running the standard MS server would have to front it >>>>> with >>>>> stunnel still. >>>> >>>> So it's up to libvirt to setup stunnel to support a completely >>>> different setup than what it has for swtpm already? >>> >>> I don't think so, no. Libvirt doesn't usually help with server >>> setup (witness the complexity of setting up a server side vtpm >>> proxy) so in the case tls-creds were built in, it would just work >>> if the object is >> >> I see, so you are extending the TPM emulator with TLS on the client >> side so you don't need another tool to setup a TLS connection from >> the QEMU/client side. > > I didn't say I would do this, just that it's an easy possibility with > the current qemu framework. I actually need to fiddle with the TPM > externally to do some of my testing (like platform reset injection) so > I won't use TLS anyway. > >> Is the server side across the network or on the same host? > > It can be either. For the remote TPM you'll need some sort of management stack (who is building this?) that does the port assignments (allocations and freeing, starting of TPM instances etc) for the possibly many TPMs you would run on a remote machine and then create the libvirt XML or QEMU command line with the port assignments. I am not sure I see the advantage of this versus what we have at the moment with a single management stack . Also, if you did this you'd have a single point of failure for many VMs whose TPM is presumably running on some dedicated machine(s). > >> Either way, what is the latency that this introduces because I would >> expect that this slows down IMA since the PCR extensions & TPM 2 >> response now go back and forth across the network? > > Most data centre protocols are now encrypted and networked (NVMeoF > would probably be the poster child) with no real ill effects. In terms > of a TPM, the competition is an underpowered discrete chip over a slow > serial bus, so I think we'll actually improve the latency not diminish > it. Compared to QEMU and swtpm talking over a local socket you probably have a decent amount of slow-down if this is over the network. I still fail to see the advantage over what we have at the moment. Also I don't see what advantage the mssim protocol brings over what swtpm provides. If you are willing to do a 'dnf -y install swtpm_setup' and start the VM via libvirt it really doesn't matter what protocol the TPM is running underneath since it's all transparent. Stefan > > James >
On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: > Copy'ing Markus for QAPI design feedback. > > On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: [...] > > +## > > +# @TPMmssimOptions: > > +# > > +# Information for the mssim emulator connection > > +# > > +# @host: host name or IP address to connect to > > +# @port: port for the standard TPM commands > > +# @ctrl: control port for TPM state changes > > +# > > +# Since: 7.2.0 > > +## > > +{ 'struct': 'TPMmssimOptions', > > + 'data': { > > + 'host': 'str', > > + 'port': 'str', > > + 'ctrl': 'str' }, > > + 'if': 'CONFIG_TPM' } > > We don't want to be adding new code using plain host/port combos, > as that misses extra functionality for controlling IPv4 vs IPv6 > usage. > > The existing 'emulator' backend references a chardev, but I'm > not especially in favour of using the chardev indirection either, > when all we should really need is a SocketAddress > > IOW, from a QAPI design POV, IMHO the best practice would be > > { 'struct': 'TPMmssimOptions', > 'data': { > 'command': 'SocketAddress', > 'control': 'SocketAddress' }, > 'if': 'CONFIG_TPM' } > > > The main wrinkle with this is that exprssing nested struct fields > with QemuOpts is a disaster zone, and -tpmdev doesn't yet support > JSON syntax. > > IMHO we should just fix the latter problem, as I don't think it > ought to be too hard. Probably a cut+paste / search/replace job > on the chanmge we did for -device in: > > commit 5dacda5167560b3af8eadbce5814f60ba44b467e > Author: Kevin Wolf <kwolf@redhat.com> > Date: Fri Oct 8 15:34:42 2021 +0200 > > vl: Enable JSON syntax for -device > > This would mean we could use plain -tpmdev for a local instance > > -tpmdev mssim,id=tpm0 \ > -device tpm-crb,tpmdev=tpm0 \ > > but to use a remote emulator we would use > > -tpmdev "{'backend': 'mssim', 'id': 'tpm0', > 'command': { > 'type': 'inet', > 'host': 'remote', > 'port': '4455' > }, > 'control': { > 'type': 'inet', > 'host': 'remote', > 'port': '4456' > }}" > > (without the whitepace/newlines, which i just used for sake of > clarity) Just on this, might it not be easier for the commandline to do what gluster does? just use the '.' as a separator and subqdict extraction, so you'd specify -tpmdev mssim,id=tpm0,command.type=inet,command.host=remote,command.port=4455,control.type=inet,control.host=remote,control.port=4456 With the added bonus that X.type could be defaulted to inet and control.host could follow command.host and so on? James
On Mon, 2022-12-12 at 17:02 -0500, Stefan Berger wrote: > > > On 12/12/22 16:36, James Bottomley wrote: > > On Mon, 2022-12-12 at 14:32 -0500, Stefan Berger wrote: [...] > > > Either way, what is the latency that this introduces because I > > > would expect that this slows down IMA since the PCR extensions & > > > TPM 2 response now go back and forth across the network? > > > > Most data centre protocols are now encrypted and networked (NVMeoF > > would probably be the poster child) with no real ill effects. In > > terms of a TPM, the competition is an underpowered discrete chip > > over a slow serial bus, so I think we'll actually improve the > > latency not diminish it. > > Compared to QEMU and swtpm talking over a local socket you probably > have a decent amount of slow-down if this is over the network. I can only repeat that doesn't happen with other much more volume and latency bound networked protocols. > I still fail to see the advantage over what we have at the moment. > Also I don't see what advantage the mssim protocol brings over what > swtpm provides. I think I've said a couple of times now: The primary advantage is that it talks to the reference implementation over its native protocol. > If you are willing to do a 'dnf -y install swtpm_setup' and start > the VM via libvirt it really doesn't matter what protocol the TPM is > running underneath since it's all transparent. Swtpm currently isn't building for Leap: https://build.opensuse.org/package/show/security/swtpm And, as I said, this is primarily for testing, so I need the reference implementation ... swtpm has started deviating from it. James
On 12/12/22 17:27, James Bottomley wrote: . > > Swtpm currently isn't building for Leap: > > https://build.opensuse.org/package/show/security/swtpm Someone could have notified me...
On Mon, Dec 12, 2022 at 05:06:05PM -0500, James Bottomley wrote: > On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: > > Copy'ing Markus for QAPI design feedback. > > > > On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: > [...] > > > +## > > > +# @TPMmssimOptions: > > > +# > > > +# Information for the mssim emulator connection > > > +# > > > +# @host: host name or IP address to connect to > > > +# @port: port for the standard TPM commands > > > +# @ctrl: control port for TPM state changes > > > +# > > > +# Since: 7.2.0 > > > +## > > > +{ 'struct': 'TPMmssimOptions', > > > + 'data': { > > > + 'host': 'str', > > > + 'port': 'str', > > > + 'ctrl': 'str' }, > > > + 'if': 'CONFIG_TPM' } > > > > We don't want to be adding new code using plain host/port combos, > > as that misses extra functionality for controlling IPv4 vs IPv6 > > usage. > > > > The existing 'emulator' backend references a chardev, but I'm > > not especially in favour of using the chardev indirection either, > > when all we should really need is a SocketAddress > > > > IOW, from a QAPI design POV, IMHO the best practice would be > > > > { 'struct': 'TPMmssimOptions', > > 'data': { > > 'command': 'SocketAddress', > > 'control': 'SocketAddress' }, > > 'if': 'CONFIG_TPM' } > > > > > > The main wrinkle with this is that exprssing nested struct fields > > with QemuOpts is a disaster zone, and -tpmdev doesn't yet support > > JSON syntax. > > > > IMHO we should just fix the latter problem, as I don't think it > > ought to be too hard. Probably a cut+paste / search/replace job > > on the chanmge we did for -device in: > > > > commit 5dacda5167560b3af8eadbce5814f60ba44b467e > > Author: Kevin Wolf <kwolf@redhat.com> > > Date: Fri Oct 8 15:34:42 2021 +0200 > > > > vl: Enable JSON syntax for -device > > > > This would mean we could use plain -tpmdev for a local instance > > > > -tpmdev mssim,id=tpm0 \ > > -device tpm-crb,tpmdev=tpm0 \ > > > > but to use a remote emulator we would use > > > > -tpmdev "{'backend': 'mssim', 'id': 'tpm0', > > 'command': { > > 'type': 'inet', > > 'host': 'remote', > > 'port': '4455' > > }, > > 'control': { > > 'type': 'inet', > > 'host': 'remote', > > 'port': '4456' > > }}" > > > > (without the whitepace/newlines, which i just used for sake of > > clarity) > > Just on this, might it not be easier for the commandline to do what > gluster does? just use the '.' as a separator and subqdict extraction, > so you'd specify > > -tpmdev mssim,id=tpm0,command.type=inet,command.host=remote,command.port=4455,control.type=inet,control.host=remote,control.port=4456 > > With the added bonus that X.type could be defaulted to inet and > control.host could follow command.host and so on? These days, we have a policy of not tyring to map nested data onto the flat QemuOpts. This has been done in several areas and we've ended up with a mess of ever so slightly different impls each with their own flaws. This is why our preferred approach these days is to add support for JSON syntax to enable non-flat config. With regards, Daniel
On Mon, Dec 12, 2022 at 05:02:43PM -0500, Stefan Berger wrote: > > > On 12/12/22 16:36, James Bottomley wrote: > > On Mon, 2022-12-12 at 14:32 -0500, Stefan Berger wrote: > > > > > > > > > On 12/12/22 14:12, James Bottomley wrote: > > > > On Mon, 2022-12-12 at 13:58 -0500, Stefan Berger wrote: > > > > > On 12/12/22 13:48, James Bottomley wrote: > > > > > > On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: > > > > > > > On 12/12/22 11:38, James Bottomley wrote: > > > > [...] > > > > > > > > the kernel use of the TPM, but I'm trying to fix that. The > > > > > > > > standard mssim server is too simplistic to do transport > > > > > > > > layer > > > > > > > > security, but like everything that does this (or rather > > > > > > > > doesn't > > > > > > > > do this), you can front it with stunnel4. > > > > > > > > > > > > > > And who or what is going to set this up? > > > > > > > > > > > > I'm not sure I understand the question. Stunnel4 is mostly > > > > > > used to > > > > > > convert unencrypted proxies like imap on 143 or smtp on 25 to > > > > > > the > > > > > > secure version. Most people who run servers are fairly > > > > > > familiar > > > > > > with using it. It's what IBM used for encrypted migration > > > > > > initially. You can run stunnel on both ends, or the qemu side > > > > > > could be built in using the qemu tls-creds way of doing things > > > > > > but > > > > > > anything running the standard MS server would have to front it > > > > > > with > > > > > > stunnel still. > > > > > > > > > > So it's up to libvirt to setup stunnel to support a completely > > > > > different setup than what it has for swtpm already? > > > > > > > > I don't think so, no. Libvirt doesn't usually help with server > > > > setup (witness the complexity of setting up a server side vtpm > > > > proxy) so in the case tls-creds were built in, it would just work > > > > if the object is > > > > > > I see, so you are extending the TPM emulator with TLS on the client > > > side so you don't need another tool to setup a TLS connection from > > > the QEMU/client side. > > > > I didn't say I would do this, just that it's an easy possibility with > > the current qemu framework. I actually need to fiddle with the TPM > > externally to do some of my testing (like platform reset injection) so > > I won't use TLS anyway. > > > > > Is the server side across the network or on the same host? > > > > It can be either. > > For the remote TPM you'll need some sort of management stack (who > is building this?) that does the port assignments (allocations and > freeing, starting of TPM instances etc) for the possibly many TPMs > you would run on a remote machine and then create the libvirt XML > or QEMU command line with the port assignments. I am not sure I > see the advantage of this versus what we have at the moment with a > single management stack . Also, if you did this you'd have a single > point of failure for many VMs whose TPM is presumably running on > some dedicated machine(s). IMHO this is largely tangential. Remote access is technically possible, but local access is likely the common case. It isn't neccessary to solve the full remote mgmt solution as a pre-condition for this proposed patch. All that matters is whether it is valuable to have the mssim backend in QEMU. I think the benefit is weak when considering a full virt mgmt stack like OpenStack/KubeVirt, as swtpm basically solves everything people need to commonly do AFAICT. None the less, I can understand why it is desirable to have the option be able to run against the TPM reference implementation, for the sake of testing behavioural compliance. It is a shame there isn't a standardized protocol for software TPM communication, as that'd avoid the need for multiple backends. With regards, Daniel
On Mon, Dec 12, 2022 at 01:58:29PM -0500, Stefan Berger wrote: > > > On 12/12/22 13:48, James Bottomley wrote: > > On Mon, 2022-12-12 at 11:59 -0500, Stefan Berger wrote: > > > > > > > > > On 12/12/22 11:38, James Bottomley wrote: > > > > On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: > > > > > Copy'ing Markus for QAPI design feedback. > > > > > > > > > > On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: > > > > > > The Microsoft Simulator (mssim) is the reference emulation > > > > > > platform for the TCG TPM 2.0 specification. > > > > > > > > > > > > https://github.com/Microsoft/ms-tpm-20-ref.git > > > > > > > > > > > > It exports a fairly simple network socket baset protocol on two > > > > > > sockets, one for command (default 2321) and one for control > > > > > > (default 2322). This patch adds a simple backend that can > > > > > > speak the mssim protocol over the network. It also allows the > > > > > > host, and two ports to be specified on the qemu command line. > > > > > > The benefits are twofold: firstly it gives us a backend that > > > > > > actually speaks a standard TPM emulation protocol instead of > > > > > > the linux specific TPM driver format of the current emulated > > > > > > TPM backend and secondly, using the microsoft protocol, the end > > > > > > point of the emulator can be anywhere on the network, > > > > > > facilitating the cloud use case where a central TPM service can > > > > > > be used over a control network. > > > > > > > > > > What's the story with security for this ? The patch isn't using > > > > > TLS, so talking to any emulator over anything other than > > > > > localhost looks insecure, unless I'm missing something. > > > > > > > > Pretty much every TPM application fears interposers and should thus > > > > be using the TPM transport security anyway. *If* this is the case, > > > > then the transport is secure. Note that this currently isn't the > > > > case for > > > > > > What about all the older kernels that are out there? > > > > No current kernel uses transport security. In the event the patch > > eventually gets upstream, the kernel be secure against interposer > > attacks going forwards. I would imagine there might be pressure to > > backport the patch given the current level of worry about interposers. > > > > > > the kernel use of the TPM, but I'm trying to fix that. The > > > > standard mssim server is too simplistic to do transport layer > > > > security, but like everything that does this (or rather doesn't do > > > > this), you can front it with stunnel4. > > > > > > And who or what is going to set this up? > > > > I'm not sure I understand the question. Stunnel4 is mostly used to > > convert unencrypted proxies like imap on 143 or smtp on 25 to the > > secure version. Most people who run servers are fairly familiar with > > using it. It's what IBM used for encrypted migration initially. You > > can run stunnel on both ends, or the qemu side could be built in using > > the qemu tls-creds way of doing things but anything running the > > standard MS server would have to front it with stunnel still. > > > So it's up to libvirt to setup stunnel to support a completely > different setup than what it has for swtpm already? Well technically libvirt doesn't have todo anything. We are free to decide to only support locally hosted mssim deployments, and declare that off node access is unsupported and warn it is potentially insecure . With regards, Daniel
On Wed, 2022-12-14 at 11:52 +0000, Daniel P. Berrangé wrote: > It is a shame there isn't a standardized protocol for software TPM > communication, as that'd avoid the need for multiple backends. Technically the mssim protocol is the standard, being part of the reference implementation, but practically it's terrible: Using two ports per vTPM is hardly scalable in a cloud situation and, as you say, it has no security. Ideally someone with TCG connections would try to standardize a more scalable network server protocol, something nicely rest based that identified the vTPM by say its EK name. James
On Wed, 2022-12-14 at 11:31 +0000, Daniel P. Berrangé wrote: > On Mon, Dec 12, 2022 at 05:06:05PM -0500, James Bottomley wrote: > > On Mon, 2022-12-12 at 15:47 +0000, Daniel P. Berrangé wrote: > > > Copy'ing Markus for QAPI design feedback. > > > > > > On Sat, Dec 10, 2022 at 12:10:18PM -0500, James Bottomley wrote: > > [...] > > > > +## > > > > +# @TPMmssimOptions: > > > > +# > > > > +# Information for the mssim emulator connection > > > > +# > > > > +# @host: host name or IP address to connect to > > > > +# @port: port for the standard TPM commands > > > > +# @ctrl: control port for TPM state changes > > > > +# > > > > +# Since: 7.2.0 > > > > +## > > > > +{ 'struct': 'TPMmssimOptions', > > > > + 'data': { > > > > + 'host': 'str', > > > > + 'port': 'str', > > > > + 'ctrl': 'str' }, > > > > + 'if': 'CONFIG_TPM' } > > > > > > We don't want to be adding new code using plain host/port combos, > > > as that misses extra functionality for controlling IPv4 vs IPv6 > > > usage. > > > > > > The existing 'emulator' backend references a chardev, but I'm > > > not especially in favour of using the chardev indirection either, > > > when all we should really need is a SocketAddress > > > > > > IOW, from a QAPI design POV, IMHO the best practice would be > > > > > > { 'struct': 'TPMmssimOptions', > > > 'data': { > > > 'command': 'SocketAddress', > > > 'control': 'SocketAddress' }, > > > 'if': 'CONFIG_TPM' } > > > > > > > > > The main wrinkle with this is that exprssing nested struct fields > > > with QemuOpts is a disaster zone, and -tpmdev doesn't yet support > > > JSON syntax. > > > > > > IMHO we should just fix the latter problem, as I don't think it > > > ought to be too hard. Probably a cut+paste / search/replace job > > > on the chanmge we did for -device in: > > > > > > commit 5dacda5167560b3af8eadbce5814f60ba44b467e > > > Author: Kevin Wolf <kwolf@redhat.com> > > > Date: Fri Oct 8 15:34:42 2021 +0200 > > > > > > vl: Enable JSON syntax for -device > > > > > > This would mean we could use plain -tpmdev for a local instance > > > > > > -tpmdev mssim,id=tpm0 \ > > > -device tpm-crb,tpmdev=tpm0 \ > > > > > > but to use a remote emulator we would use > > > > > > -tpmdev "{'backend': 'mssim', 'id': 'tpm0', > > > 'command': { > > > 'type': 'inet', > > > 'host': 'remote', > > > 'port': '4455' > > > }, > > > 'control': { > > > 'type': 'inet', > > > 'host': 'remote', > > > 'port': '4456' > > > }}" > > > > > > (without the whitepace/newlines, which i just used for sake of > > > clarity) > > > > Just on this, might it not be easier for the commandline to do what > > gluster does? just use the '.' as a separator and subqdict > > extraction, so you'd specify > > > > -tpmdev > > mssim,id=tpm0,command.type=inet,command.host=remote,command.port=44 > > 55,control.type=inet,control.host=remote,control.port=4456 > > > > With the added bonus that X.type could be defaulted to inet and > > control.host could follow command.host and so on? > > These days, we have a policy of not tyring to map nested data onto > the flat QemuOpts. This has been done in several areas and we've > ended up with a mess of ever so slightly different impls each with > their own flaws. This is why our preferred approach these days is to > add support for JSON syntax to enable non-flat config. Well, OK, but I've got to say on behalf of shell script writers everywhere that using json for command line arguments is a textbook definition of cruel and unusual punishment. James
James Bottomley <jejb@linux.ibm.com> writes: > On Wed, 2022-12-14 at 11:31 +0000, Daniel P. Berrangé wrote: [...] >> These days, we have a policy of not tyring to map nested data onto >> the flat QemuOpts. This has been done in several areas and we've >> ended up with a mess of ever so slightly different impls each with >> their own flaws. This is why our preferred approach these days is to >> add support for JSON syntax to enable non-flat config. > > Well, OK, but I've got to say on behalf of shell script writers > everywhere that using json for command line arguments is a textbook > definition of cruel and unusual punishment. For new code, use qobject_input_visitor_new_str(). Parses both JSON and dotted keys. Example: case QEMU_OPTION_blockdev in qemu_init(). Dotted keys can fall apart for corner cases. See util/keyval.c if you're curious. Sometimes we bend over backwards for backward compatibility, and do something like if (optarg[0] == '{') { QObject *obj = qobject_from_json(optarg, &error_fatal); v = qobject_input_visitor_new(obj); qobject_unref(obj); } else { ... old parser ... } This parses both JSON and whatever old crap. Example: object_option_parse(). Questions?
On 12/14/22 07:43, James Bottomley wrote: > On Wed, 2022-12-14 at 11:52 +0000, Daniel P. Berrangé wrote: >> It is a shame there isn't a standardized protocol for software TPM >> communication, as that'd avoid the need for multiple backends. > > Technically the mssim protocol is the standard, being part of the > reference implementation, but practically it's terrible: Using two ... and it's missing functionality related to state migration > ports per vTPM is hardly scalable in a cloud situation and, as you say, > it has no security. Ideally someone with TCG connections would try to > standardize a more scalable network server protocol, something nicely > rest based that identified the vTPM by say its EK name. > > James >
diff --git a/backends/tpm/Kconfig b/backends/tpm/Kconfig index 5d91eb89c2..d6d6fa53e9 100644 --- a/backends/tpm/Kconfig +++ b/backends/tpm/Kconfig @@ -12,3 +12,8 @@ config TPM_EMULATOR bool default y depends on TPM_BACKEND + +config TPM_MSSIM + bool + default y + depends on TPM_BACKEND diff --git a/backends/tpm/meson.build b/backends/tpm/meson.build index 7f2503f84e..c7c3c79125 100644 --- a/backends/tpm/meson.build +++ b/backends/tpm/meson.build @@ -3,4 +3,5 @@ if have_tpm softmmu_ss.add(files('tpm_util.c')) softmmu_ss.add(when: 'CONFIG_TPM_PASSTHROUGH', if_true: files('tpm_passthrough.c')) softmmu_ss.add(when: 'CONFIG_TPM_EMULATOR', if_true: files('tpm_emulator.c')) + softmmu_ss.add(when: 'CONFIG_TPM_MSSIM', if_true: files('tpm_mssim.c')) endif diff --git a/backends/tpm/tpm_mssim.c b/backends/tpm/tpm_mssim.c new file mode 100644 index 0000000000..6864b1fbc0 --- /dev/null +++ b/backends/tpm/tpm_mssim.c @@ -0,0 +1,266 @@ +/* + * Emulator TPM driver which connects over the mssim protocol + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2022 + * Author: James Bottomley <jejb@linux.ibm.com> + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/sockets.h" + +#include "qapi/clone-visitor.h" +#include "qapi/qapi-visit-tpm.h" + +#include "io/channel-socket.h" + +#include "sysemu/tpm_backend.h" +#include "sysemu/tpm_util.h" + +#include "qom/object.h" + +#include "tpm_int.h" +#include "tpm_mssim.h" + +#define ERROR_PREFIX "TPM mssim Emulator: " + +#define TYPE_TPM_MSSIM "tpm-mssim" +OBJECT_DECLARE_SIMPLE_TYPE(TPMmssim, TPM_MSSIM) + +struct TPMmssim { + TPMBackend parent; + + TPMmssimOptions opts; + + QIOChannel *cmd_qc, *ctrl_qc; +}; + +static int tpm_send_ctrl(TPMmssim *t, uint32_t cmd, Error **errp) +{ + int ret; + + cmd = htonl(cmd); + ret = qio_channel_write_all(t->ctrl_qc, (char *)&cmd, sizeof(cmd), errp); + if (ret != 0) + return ret; + ret = qio_channel_read_all(t->ctrl_qc, (char *)&cmd, sizeof(cmd), errp); + if (ret != 0) + return ret; + if (cmd != 0) { + error_setg(errp, ERROR_PREFIX "Incorrect ACK recieved on control channel 0x%x\n", cmd); + return -1; + } + return 0; +} + +static void tpm_mssim_instance_init(Object *obj) +{ +} + +static void tpm_mssim_instance_finalize(Object *obj) +{ + TPMmssim *t = TPM_MSSIM(obj); + + tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, NULL); + + object_unref(OBJECT(t->ctrl_qc)); + object_unref(OBJECT(t->cmd_qc)); +} + +static void tpm_mssim_cancel_cmd(TPMBackend *tb) +{ + return; +} + +static TPMVersion tpm_mssim_get_version(TPMBackend *tb) +{ + return TPM_VERSION_2_0; +} + +static size_t tpm_mssim_get_buffer_size(TPMBackend *tb) +{ + /* TCG standard profile max buffer size */ + return 4096; +} + +static TpmTypeOptions *tpm_mssim_get_opts(TPMBackend *tb) +{ + TPMmssim *t = TPM_MSSIM(tb); + TpmTypeOptions *opts = g_new0(TpmTypeOptions, 1); + + opts->type = TPM_TYPE_MSSIM; + opts->u.mssim.data = QAPI_CLONE(TPMmssimOptions, &t->opts); + + return opts; +} + +static void tpm_mssim_handle_request(TPMBackend *tb, TPMBackendCmd *cmd, + Error **errp) +{ + TPMmssim *t = TPM_MSSIM(tb); + uint32_t header, len; + uint8_t locality = cmd->locty; + struct iovec iov[4]; + int ret; + + header = htonl(TPM_SEND_COMMAND); + len = htonl(cmd->in_len); + + iov[0].iov_base = &header; + iov[0].iov_len = sizeof(header); + iov[1].iov_base = &locality; + iov[1].iov_len = sizeof(locality); + iov[2].iov_base = &len; + iov[2].iov_len = sizeof(len); + iov[3].iov_base = (void *)cmd->in; + iov[3].iov_len = cmd->in_len; + + ret = qio_channel_writev_all(t->cmd_qc, iov, 4, errp); + if (ret != 0) + goto fail; + + ret = qio_channel_read_all(t->cmd_qc, (char *)&len, sizeof(len), errp); + if (ret != 0) + goto fail; + len = ntohl(len); + if (len > cmd->out_len) { + error_setg(errp, "receive size is too large"); + goto fail; + } + ret = qio_channel_read_all(t->cmd_qc, (char *)cmd->out, len, errp); + if (ret != 0) + goto fail; + /* ACK packet */ + ret = qio_channel_read_all(t->cmd_qc, (char *)&header, sizeof(header), errp); + if (ret != 0) + goto fail; + if (header != 0) { + error_setg(errp, "incorrect ACK received on command channel 0x%x", len); + goto fail; + } + + return; + + fail: + error_prepend(errp, ERROR_PREFIX); + tpm_util_write_fatal_error_response(cmd->out, cmd->out_len); +} + +static TPMBackend *tpm_mssim_create(QemuOpts *opts) +{ + TPMBackend *be = TPM_BACKEND(object_new(TYPE_TPM_MSSIM)); + TPMmssim *t = TPM_MSSIM(be); + InetSocketAddress cmd_s, ctl_s; + int sock; + const char *host, *port, *ctrl; + Error *errp = NULL; + + host = qemu_opt_get(opts, "host"); + if (!host) + host = "localhost"; + t->opts.host = g_strdup(host); + + port = qemu_opt_get(opts, "port"); + if (!port) + port = "2321"; + t->opts.port = g_strdup(port); + + ctrl = qemu_opt_get(opts, "ctrl"); + if (!ctrl) + ctrl = "2322"; + t->opts.ctrl = g_strdup(ctrl); + + cmd_s.host = (char *)host; + cmd_s.port = (char *)port; + + ctl_s.host = (char *)host; + ctl_s.port = (char *)ctrl; + + sock = inet_connect_saddr(&cmd_s, &errp); + if (sock < 0) + goto fail; + t->cmd_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, &errp)); + if (errp) + goto fail; + sock = inet_connect_saddr(&ctl_s, &errp); + if (sock < 0) + goto fail_unref_cmd; + t->ctrl_qc = QIO_CHANNEL(qio_channel_socket_new_fd(sock, &errp)); + if (errp) + goto fail_unref_cmd; + + /* reset the TPM using a power cycle sequence, in case someone + * has previously powered it up */ + sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, &errp); + if (sock != 0) + goto fail_unref; + sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_ON, &errp); + if (sock != 0) + goto fail_unref; + sock = tpm_send_ctrl(t, TPM_SIGNAL_NV_ON, &errp); + if (sock != 0) + goto fail_unref; + + return be; + fail_unref: + object_unref(OBJECT(t->ctrl_qc)); + fail_unref_cmd: + object_unref(OBJECT(t->cmd_qc)); + fail: + error_prepend(&errp, ERROR_PREFIX); + error_report_err(errp); + object_unref(OBJECT(be)); + + return NULL; +} + +static const QemuOptDesc tpm_mssim_cmdline_opts[] = { + TPM_STANDARD_CMDLINE_OPTS, + { + .name = "host", + .type = QEMU_OPT_STRING, + .help = "name or IP address of host to connect to (deault localhost)", + }, + { + .name = "port", + .type = QEMU_OPT_STRING, + .help = "port number for standard TPM commands (default 2321)", + }, + { + .name = "ctrl", + .type = QEMU_OPT_STRING, + .help = "control port for TPM commands (default 2322)", + }, +}; + +static void tpm_mssim_class_init(ObjectClass *klass, void *data) +{ + TPMBackendClass *cl = TPM_BACKEND_CLASS(klass); + + cl->type = TPM_TYPE_MSSIM; + cl->opts = tpm_mssim_cmdline_opts; + cl->desc = "TPM mssim emulator backend driver"; + cl->create = tpm_mssim_create; + cl->cancel_cmd = tpm_mssim_cancel_cmd; + cl->get_tpm_version = tpm_mssim_get_version; + cl->get_buffer_size = tpm_mssim_get_buffer_size; + cl->get_tpm_options = tpm_mssim_get_opts; + cl->handle_request = tpm_mssim_handle_request; +} + +static const TypeInfo tpm_mssim_info = { + .name = TYPE_TPM_MSSIM, + .parent = TYPE_TPM_BACKEND, + .instance_size = sizeof(TPMmssim), + .class_init = tpm_mssim_class_init, + .instance_init = tpm_mssim_instance_init, + .instance_finalize = tpm_mssim_instance_finalize, +}; + +static void tpm_mssim_register(void) +{ + type_register_static(&tpm_mssim_info); +} + +type_init(tpm_mssim_register) diff --git a/backends/tpm/tpm_mssim.h b/backends/tpm/tpm_mssim.h new file mode 100644 index 0000000000..04a270338a --- /dev/null +++ b/backends/tpm/tpm_mssim.h @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * The code below is copied from the Microsoft/TCG Reference implementation + * + * https://github.com/Microsoft/ms-tpm-20-ref.git + * + * In file TPMCmd/Simulator/include/TpmTcpProtocol.h + */ + +#define TPM_SIGNAL_POWER_ON 1 +#define TPM_SIGNAL_POWER_OFF 2 +#define TPM_SIGNAL_PHYS_PRES_ON 3 +#define TPM_SIGNAL_PHYS_PRES_OFF 4 +#define TPM_SIGNAL_HASH_START 5 +#define TPM_SIGNAL_HASH_DATA 6 + // {uint32_t BufferSize, uint8_t[BufferSize] Buffer} +#define TPM_SIGNAL_HASH_END 7 +#define TPM_SEND_COMMAND 8 + // {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} -> + // {uint32_t OutBufferSize, uint8_t[OutBufferSize] OutBuffer} + +#define TPM_SIGNAL_CANCEL_ON 9 +#define TPM_SIGNAL_CANCEL_OFF 10 +#define TPM_SIGNAL_NV_ON 11 +#define TPM_SIGNAL_NV_OFF 12 +#define TPM_SIGNAL_KEY_CACHE_ON 13 +#define TPM_SIGNAL_KEY_CACHE_OFF 14 + +#define TPM_REMOTE_HANDSHAKE 15 +#define TPM_SET_ALTERNATIVE_RESULT 16 + +#define TPM_SIGNAL_RESET 17 +#define TPM_SIGNAL_RESTART 18 + +#define TPM_SESSION_END 20 +#define TPM_STOP 21 + +#define TPM_GET_COMMAND_RESPONSE_SIZES 25 + +#define TPM_ACT_GET_SIGNALED 26 + +#define TPM_TEST_FAILURE_MODE 30 diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 01b789a79e..f4cd030eab 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -841,6 +841,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) unsigned int c = 0; TPMPassthroughOptions *tpo; TPMEmulatorOptions *teo; + TPMmssimOptions *tmo; info_list = qmp_query_tpm(&err); if (err) { @@ -874,6 +875,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) teo = ti->options->u.emulator.data; monitor_printf(mon, ",chardev=%s", teo->chardev); break; + case TPM_TYPE_MSSIM: + tmo = ti->options->u.mssim.data; + monitor_printf(mon, ",host=%s,port=%s,ctl=%s", tmo->host, + tmo->port, tmo->host); + break; case TPM_TYPE__MAX: break; } diff --git a/qapi/tpm.json b/qapi/tpm.json index 4e2ea9756a..d92065043e 100644 --- a/qapi/tpm.json +++ b/qapi/tpm.json @@ -49,7 +49,7 @@ # # Since: 1.5 ## -{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ], +{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator', 'mssim' ], 'if': 'CONFIG_TPM' } ## @@ -64,7 +64,7 @@ # Example: # # -> { "execute": "query-tpm-types" } -# <- { "return": [ "passthrough", "emulator" ] } +# <- { "return": [ "passthrough", "emulator", "mssim" ] } # ## { 'command': 'query-tpm-types', 'returns': ['TpmType'], @@ -99,6 +99,24 @@ { 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' }, 'if': 'CONFIG_TPM' } +## +# @TPMmssimOptions: +# +# Information for the mssim emulator connection +# +# @host: host name or IP address to connect to +# @port: port for the standard TPM commands +# @ctrl: control port for TPM state changes +# +# Since: 7.2.0 +## +{ 'struct': 'TPMmssimOptions', + 'data': { + 'host': 'str', + 'port': 'str', + 'ctrl': 'str' }, + 'if': 'CONFIG_TPM' } + ## # @TPMPassthroughOptionsWrapper: # @@ -117,6 +135,15 @@ 'data': { 'data': 'TPMEmulatorOptions' }, 'if': 'CONFIG_TPM' } +## +# @TPMmssimOptionsWrapper: +# +# Since: 7.2.0 +## +{ 'struct': 'TPMmssimOptionsWrapper', + 'data' : { 'data': 'TPMmssimOptions' }, + 'if': 'CONFIG_TPM' } + ## # @TpmTypeOptions: # @@ -124,6 +151,7 @@ # # @type: - 'passthrough' The configuration options for the TPM passthrough type # - 'emulator' The configuration options for TPM emulator backend type +# - 'mssim' The configuration options for TPM emulator mssim type # # Since: 1.5 ## @@ -131,7 +159,8 @@ 'base': { 'type': 'TpmType' }, 'discriminator': 'type', 'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper', - 'emulator': 'TPMEmulatorOptionsWrapper' }, + 'emulator': 'TPMEmulatorOptionsWrapper', + 'mssim': 'TPMmssimOptionsWrapper' }, 'if': 'CONFIG_TPM' } ##
The Microsoft Simulator (mssim) is the reference emulation platform for the TCG TPM 2.0 specification. https://github.com/Microsoft/ms-tpm-20-ref.git It exports a fairly simple network socket baset protocol on two sockets, one for command (default 2321) and one for control (default 2322). This patch adds a simple backend that can speak the mssim protocol over the network. It also allows the host, and two ports to be specified on the qemu command line. The benefits are twofold: firstly it gives us a backend that actually speaks a standard TPM emulation protocol instead of the linux specific TPM driver format of the current emulated TPM backend and secondly, using the microsoft protocol, the end point of the emulator can be anywhere on the network, facilitating the cloud use case where a central TPM service can be used over a control network. The implementation does basic control commands like power off/on, but doesn't implement cancellation or startup. The former because cancellation is pretty much useless on a fast operating TPM emulator and the latter because this emulator is designed to be used with OVMF which itself does TPM startup and I wanted to validate that. To run this, simply download an emulator based on the MS specification (package ibmswtpm2 on openSUSE) and run it, then add these two lines to the qemu command and it will use the emulator. -tpmdev mssim,id=tpm0 \ -device tpm-crb,tpmdev=tpm0 \ to use a remote emulator replace the first line with -tpmdev mssim,it=tpm0,host=remote.host,port=4455,ctrl=4457 \ tpm-tis also works as the backend. Signed-off-by: James Bottomley <jejb@linux.ibm.com> --- backends/tpm/Kconfig | 5 + backends/tpm/meson.build | 1 + backends/tpm/tpm_mssim.c | 266 +++++++++++++++++++++++++++++++++++++++ backends/tpm/tpm_mssim.h | 43 +++++++ monitor/hmp-cmds.c | 6 + qapi/tpm.json | 35 +++++- 6 files changed, 353 insertions(+), 3 deletions(-) create mode 100644 backends/tpm/tpm_mssim.c create mode 100644 backends/tpm/tpm_mssim.h