Page MenuHomeFreeBSD

D46373.id142285.diff
No OneTemporary

D46373.id142285.diff

diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -60,6 +60,7 @@
sockstream.c \
tpm_device.c \
tpm_emul_passthru.c \
+ tpm_emul_swtpm.c \
tpm_intf_crb.c \
tpm_ppi_qemu.c \
uart_backend.c \
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -435,7 +435,7 @@
.It Cm lpc
LPC PCI-ISA bridge with COM1, COM2, COM3, and COM4 16550 serial ports,
a boot ROM, and,
-optionally, a fwcfg type, and the debug/test device.
+optionally, a TPM module, a fwcfg type, and the debug/test device.
The LPC bridge emulation can only be configured on bus 0.
.It Cm fbuf
Raw framebuffer device attached to VNC server.
@@ -629,17 +629,25 @@
.Sm on
.El
.Pp
-Emulate a TPM device. The argument
-.Ar path
-needs to point to a valid TPM device path, i.e.
-.Pa /dev/tpm0 .
-.El
-.Pp
+Emulate a TPM device.
Supported options for
.Ar type :
.Bl -tag -width 10n
.It Cm passthru
-pass a physical TPM device through to the guest
+Use a physical TPM device.
+The argument
+.Ar path
+needs to point to a valid TPM device path, i.e.
+.Pa /dev/tpm0 .
+.It Cm swtpm
+Connect to a running
+.Cm swtpm
+instance.
+The argument
+.Ar path
+needs to point to a UNIX domain socket that a
+.Cm swtpm
+process is listening on.
.El
.Pp
The
@@ -649,7 +657,8 @@
.It Cm version= Ns Ar version
Version of the TPM device according to the TCG specification.
Defaults to
-.Cm 2.0
+.Cm 2.0 ,
+which is the only version currently supported.
.El
.Ss Boot ROM device backends
.Sm off
diff --git a/usr.sbin/bhyve/bhyve_config.5 b/usr.sbin/bhyve/bhyve_config.5
--- a/usr.sbin/bhyve/bhyve_config.5
+++ b/usr.sbin/bhyve/bhyve_config.5
@@ -146,15 +146,6 @@
This value only works when loaded with UEFI mode for VNC, and
used a VNC client that don't support QEMU Extended Key Event
Message (e.g. TightVNC).
-.It Va tpm.path Ta string Ta Ta
-Path to the host TPM device.
-This is typically /dev/tpm0.
-.It Va tpm.type Ta string Ta Ta
-Type of the TPM device passed to the guest.
-Currently, only "passthru" is supported.
-.It Va tpm.version Ta string Ta 2.0 Ta
-Version of the TPM device according to the TCG specification.
-Currently, only version 2.0 is supported.
.It Va rtc.use_localtime Ta bool Ta true Ta
The real time clock uses the local time of the host.
If this is set to false, the real time clock uses UTC.
@@ -274,9 +265,8 @@
VGA framebuffer device attached to VNC server.
.It Li lpc
LPC PCI-ISA bridge with COM1-COM4 16550 serial ports,
-a boot ROM,
-an optional fwcfg type,
-and an optional debug/test device.
+a boot ROM, and, optionally, a TPM module, a fwcfg type,
+and a debug/test device.
This device must be configured on bus 0.
.It Li hda
High Definition audio controller.
@@ -593,6 +583,37 @@
.It Va subdevice Ta 0
.El
.El
+.Ss TPM Device Settings
+The TPM device stores its configuration under a top-level
+.Va tpm
+node rather than under the LPC TPM device's node.
+Only one TPM device is supported.
+The following nodes are available under
+.Va tpm :
+.Bl -column "pc-testdev" "Format" "Default"
+.It Sy Name Ta Sy Format Ta Sy Default Ta Sy Description
+.It Va tpm.path Ta string Ta Ta
+Path to the TPM backend.
+Depending on the
+.Va tpm.type ,
+this is either the host TPM device, typically
+.Pa /dev/tpm0 ,
+or any UNIX domain socket on which a
+.Cm swtpm
+process is listening.
+.It Va tpm.type Ta string Ta Ta
+Type of the TPM device passed to the guest.
+This can be either
+.Dq passthru
+to use the host TPM devices, or
+.Dq swtpm
+to connect to a running
+.Cm swtpm
+process.
+.It Va tpm.version Ta string Ta 2.0 Ta
+Version of the TPM device according to the TCG specification.
+Currently, only version 2.0 is supported.
+.El
.Ss NVMe Controller Settings
Each NVMe controller supports a single storage device.
The device can be backed either by a memory disk described by the
diff --git a/usr.sbin/bhyve/tpm_emul_swtpm.c b/usr.sbin/bhyve/tpm_emul_swtpm.c
new file mode 100644
--- /dev/null
+++ b/usr.sbin/bhyve/tpm_emul_swtpm.c
@@ -0,0 +1,148 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Hans Rosenfeld
+ * Author: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <malloc_np.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "tpm_device.h"
+#include "tpm_emul.h"
+
+struct tpm_swtpm {
+ int fd;
+};
+
+struct tpm_req_hdr {
+ uint16_t tag;
+ uint32_t len;
+ uint32_t ordinal;
+} __packed;
+
+struct tpm_resp_hdr {
+ uint16_t tag;
+ uint32_t len;
+ uint32_t errcode;
+} __packed;
+
+static int
+tpm_swtpm_init(void **sc, nvlist_t *nvl)
+{
+ struct tpm_swtpm *tpm;
+ const char *path;
+ struct sockaddr_un tpm_addr;
+
+ tpm = calloc(1, sizeof (struct tpm_swtpm));
+ if (tpm == NULL) {
+ warnx("%s: failed to allocate tpm_swtpm", __func__);
+ return (ENOMEM);
+ }
+
+ path = get_config_value_node(nvl, "path");
+ if (path == NULL) {
+ warnx("%s: no socket path specified", __func__);
+ return (ENOENT);
+ }
+
+ tpm->fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (tpm->fd < 0) {
+ warnx("%s: unable to open tpm socket", __func__);
+ return (ENOENT);
+ }
+
+ bzero(&tpm_addr, sizeof (tpm_addr));
+ tpm_addr.sun_family = AF_UNIX;
+ strlcpy(tpm_addr.sun_path, path, sizeof (tpm_addr.sun_path) - 1);
+
+ if (connect(tpm->fd, (struct sockaddr *)&tpm_addr, sizeof (tpm_addr)) ==
+ -1) {
+ warnx("%s: unable to connect to tpm socket \"%s\"", __func__,
+ path);
+ return (ENOENT);
+ }
+
+ *sc = tpm;
+
+ return (0);
+}
+
+static int
+tpm_swtpm_execute_cmd(void *sc, void *cmd, uint32_t cmd_size, void *rsp,
+ uint32_t rsp_size)
+{
+ struct tpm_swtpm *tpm;
+ struct tpm_req_hdr *hdr;
+ ssize_t len;
+
+ if (rsp_size < (ssize_t)sizeof(struct tpm_resp_hdr)) {
+ warn("%s: rsp_size of %u is too small", __func__, rsp_size);
+ return (EINVAL);
+ }
+
+ tpm = sc;
+
+ /*
+ * Reduce cmd_size to the size specified in the request header. This is
+ * necessary because swtpm returns an error when it is sent more data
+ * than it rightfully expects.
+ */
+ hdr = cmd;
+ if (cmd_size > be32toh(hdr->len))
+ cmd_size = be32toh(hdr->len);
+
+ len = send(tpm->fd, cmd, cmd_size, MSG_NOSIGNAL|MSG_DONTWAIT);
+ if (len == -1)
+ err(1, "%s: cmd send failed, is swtpm running?", __func__);
+ if (len != cmd_size) {
+ warn("%s: cmd write failed (bytes written: %zd / %d)", __func__,
+ len, cmd_size);
+ return (EFAULT);
+ }
+
+ len = recv(tpm->fd, rsp, rsp_size, 0);
+ if (len == -1)
+ err(1, "%s: rsp recv failed, is swtpm running?", __func__);
+ if (len < (ssize_t)sizeof(struct tpm_resp_hdr)) {
+ warn("%s: rsp read failed (bytes read: %zd / %d)", __func__,
+ len, rsp_size);
+ return (EFAULT);
+ }
+
+ return (0);
+}
+
+static void
+tpm_swtpm_deinit(void *sc)
+{
+ struct tpm_swtpm *tpm;
+
+ tpm = sc;
+ if (tpm == NULL)
+ return;
+
+ if (tpm->fd >= 0)
+ close(tpm->fd);
+
+ free(tpm);
+}
+
+static const struct tpm_emul tpm_emul_swtpm = {
+ .name = "swtpm",
+ .init = tpm_swtpm_init,
+ .deinit = tpm_swtpm_deinit,
+ .execute_cmd = tpm_swtpm_execute_cmd,
+};
+TPM_EMUL_SET(tpm_emul_swtpm);

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 8, 1:28 AM (22 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14524786
Default Alt Text
D46373.id142285.diff (7 KB)

Event Timeline