Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102054708
D46373.id142285.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D46373.id142285.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D46373: bhyve: TPM 2.0 emulation with swtpm
Attached
Detach File
Event Timeline
Log In to Comment