xref: /freebsd/usr.sbin/bhyve/tpm_emul_passthru.c (revision 29200a8133c0963c17508035b63f5ca43db174c8)
111ba2146SCorvin Köhne /*-
211ba2146SCorvin Köhne  * SPDX-License-Identifier: BSD-2-Clause
311ba2146SCorvin Köhne  *
411ba2146SCorvin Köhne  * Copyright (c) 2023 Beckhoff Automation GmbH & Co. KG
511ba2146SCorvin Köhne  * Author: Corvin Köhne <corvink@FreeBSD.org>
611ba2146SCorvin Köhne  */
711ba2146SCorvin Köhne 
811ba2146SCorvin Köhne #include <sys/types.h>
911ba2146SCorvin Köhne 
1011ba2146SCorvin Köhne #include <err.h>
1111ba2146SCorvin Köhne #include <errno.h>
1211ba2146SCorvin Köhne #include <fcntl.h>
1311ba2146SCorvin Köhne #include <malloc_np.h>
1411ba2146SCorvin Köhne #include <stdlib.h>
1511ba2146SCorvin Köhne #include <unistd.h>
1611ba2146SCorvin Köhne 
1711ba2146SCorvin Köhne #include "config.h"
1811ba2146SCorvin Köhne #include "tpm_device.h"
1911ba2146SCorvin Köhne #include "tpm_emul.h"
2011ba2146SCorvin Köhne 
2111ba2146SCorvin Köhne struct tpm_passthru {
2211ba2146SCorvin Köhne 	int fd;
2311ba2146SCorvin Köhne };
2411ba2146SCorvin Köhne 
25*29200a81SCorvin Köhne struct tpm_resp_hdr {
26*29200a81SCorvin Köhne 	uint16_t tag;
27*29200a81SCorvin Köhne 	uint32_t len;
28*29200a81SCorvin Köhne 	uint32_t errcode;
29*29200a81SCorvin Köhne } __packed;
30*29200a81SCorvin Köhne 
3111ba2146SCorvin Köhne static int
tpm_passthru_init(void ** sc,nvlist_t * nvl)3211ba2146SCorvin Köhne tpm_passthru_init(void **sc, nvlist_t *nvl)
3311ba2146SCorvin Köhne {
3411ba2146SCorvin Köhne 	struct tpm_passthru *tpm;
3511ba2146SCorvin Köhne 	const char *path;
3611ba2146SCorvin Köhne 
3711ba2146SCorvin Köhne 	tpm = calloc(1, sizeof(struct tpm_passthru));
3811ba2146SCorvin Köhne 	if (tpm == NULL) {
3911ba2146SCorvin Köhne 		warnx("%s: failed to allocate tpm passthru", __func__);
4011ba2146SCorvin Köhne 		return (ENOMEM);
4111ba2146SCorvin Köhne 	}
4211ba2146SCorvin Köhne 
4311ba2146SCorvin Köhne 	path = get_config_value_node(nvl, "path");
4411ba2146SCorvin Köhne 	tpm->fd = open(path, O_RDWR);
4511ba2146SCorvin Köhne 	if (tpm->fd < 0) {
4611ba2146SCorvin Köhne 		warnx("%s: unable to open tpm device \"%s\"", __func__, path);
4711ba2146SCorvin Köhne 		return (ENOENT);
4811ba2146SCorvin Köhne 	}
4911ba2146SCorvin Köhne 
5011ba2146SCorvin Köhne 	*sc = tpm;
5111ba2146SCorvin Köhne 
5211ba2146SCorvin Köhne 	return (0);
5311ba2146SCorvin Köhne }
5411ba2146SCorvin Köhne 
55*29200a81SCorvin Köhne static int
tpm_passthru_execute_cmd(void * sc,void * cmd,uint32_t cmd_size,void * rsp,uint32_t rsp_size)56*29200a81SCorvin Köhne tpm_passthru_execute_cmd(void *sc, void *cmd, uint32_t cmd_size, void *rsp,
57*29200a81SCorvin Köhne     uint32_t rsp_size)
58*29200a81SCorvin Köhne {
59*29200a81SCorvin Köhne 	struct tpm_passthru *tpm;
60*29200a81SCorvin Köhne 	ssize_t len;
61*29200a81SCorvin Köhne 
62*29200a81SCorvin Köhne 	if (rsp_size < (ssize_t)sizeof(struct tpm_resp_hdr)) {
63*29200a81SCorvin Köhne 		warn("%s: rsp_size of %u is too small", __func__, rsp_size);
64*29200a81SCorvin Köhne 		return (EINVAL);
65*29200a81SCorvin Köhne 	}
66*29200a81SCorvin Köhne 
67*29200a81SCorvin Köhne 	tpm = sc;
68*29200a81SCorvin Köhne 
69*29200a81SCorvin Köhne 	len = write(tpm->fd, cmd, cmd_size);
70*29200a81SCorvin Köhne 	if (len != cmd_size) {
71*29200a81SCorvin Köhne 		warn("%s: cmd write failed (bytes written: %zd / %d)", __func__,
72*29200a81SCorvin Köhne 		    len, cmd_size);
73*29200a81SCorvin Köhne 		return (EFAULT);
74*29200a81SCorvin Köhne 	}
75*29200a81SCorvin Köhne 
76*29200a81SCorvin Köhne 	len = read(tpm->fd, rsp, rsp_size);
77*29200a81SCorvin Köhne 	if (len < (ssize_t)sizeof(struct tpm_resp_hdr)) {
78*29200a81SCorvin Köhne 		warn("%s: rsp read failed (bytes read: %zd / %d)", __func__,
79*29200a81SCorvin Köhne 		    len, rsp_size);
80*29200a81SCorvin Köhne 		return (EFAULT);
81*29200a81SCorvin Köhne 	}
82*29200a81SCorvin Köhne 
83*29200a81SCorvin Köhne 	return (0);
84*29200a81SCorvin Köhne }
85*29200a81SCorvin Köhne 
8611ba2146SCorvin Köhne static void
tpm_passthru_deinit(void * sc)8711ba2146SCorvin Köhne tpm_passthru_deinit(void *sc)
8811ba2146SCorvin Köhne {
8911ba2146SCorvin Köhne 	struct tpm_passthru *tpm;
9011ba2146SCorvin Köhne 
9111ba2146SCorvin Köhne 	tpm = sc;
9211ba2146SCorvin Köhne 	if (tpm == NULL)
9311ba2146SCorvin Köhne 		return;
9411ba2146SCorvin Köhne 
9511ba2146SCorvin Köhne 	if (tpm->fd >= 0)
9611ba2146SCorvin Köhne 		close(tpm->fd);
9711ba2146SCorvin Köhne 
9811ba2146SCorvin Köhne 	free(tpm);
9911ba2146SCorvin Köhne }
10011ba2146SCorvin Köhne 
10111ba2146SCorvin Köhne static const struct tpm_emul tpm_emul_passthru = {
10211ba2146SCorvin Köhne 	.name = "passthru",
10311ba2146SCorvin Köhne 	.init = tpm_passthru_init,
10411ba2146SCorvin Köhne 	.deinit = tpm_passthru_deinit,
105*29200a81SCorvin Köhne 	.execute_cmd = tpm_passthru_execute_cmd,
10611ba2146SCorvin Köhne };
10711ba2146SCorvin Köhne TPM_EMUL_SET(tpm_emul_passthru);
108