xref: /illumos-gate/usr/src/cmd/bhyve/tpm_emul_passthru.c (revision 32640292339b07090f10ce34d455f98711077343)
1*32640292SAndy Fiddaman /*-
2*32640292SAndy Fiddaman  * SPDX-License-Identifier: BSD-2-Clause
3*32640292SAndy Fiddaman  *
4*32640292SAndy Fiddaman  * Copyright (c) 2023 Beckhoff Automation GmbH & Co. KG
5*32640292SAndy Fiddaman  * Author: Corvin Köhne <corvink@FreeBSD.org>
6*32640292SAndy Fiddaman  */
7*32640292SAndy Fiddaman 
8*32640292SAndy Fiddaman #include <sys/types.h>
9*32640292SAndy Fiddaman 
10*32640292SAndy Fiddaman #include <err.h>
11*32640292SAndy Fiddaman #include <errno.h>
12*32640292SAndy Fiddaman #include <fcntl.h>
13*32640292SAndy Fiddaman #ifdef	__FreeBSD__
14*32640292SAndy Fiddaman #include <malloc_np.h>
15*32640292SAndy Fiddaman #else
16*32640292SAndy Fiddaman #include <sys/vmm.h>
17*32640292SAndy Fiddaman #endif
18*32640292SAndy Fiddaman #include <stdlib.h>
19*32640292SAndy Fiddaman #include <unistd.h>
20*32640292SAndy Fiddaman 
21*32640292SAndy Fiddaman #include "config.h"
22*32640292SAndy Fiddaman #include "tpm_device.h"
23*32640292SAndy Fiddaman #include "tpm_emul.h"
24*32640292SAndy Fiddaman 
25*32640292SAndy Fiddaman struct tpm_passthru {
26*32640292SAndy Fiddaman 	int fd;
27*32640292SAndy Fiddaman };
28*32640292SAndy Fiddaman 
29*32640292SAndy Fiddaman struct tpm_resp_hdr {
30*32640292SAndy Fiddaman 	uint16_t tag;
31*32640292SAndy Fiddaman 	uint32_t len;
32*32640292SAndy Fiddaman 	uint32_t errcode;
33*32640292SAndy Fiddaman } __packed;
34*32640292SAndy Fiddaman 
35*32640292SAndy Fiddaman static int
tpm_passthru_init(void ** sc,nvlist_t * nvl)36*32640292SAndy Fiddaman tpm_passthru_init(void **sc, nvlist_t *nvl)
37*32640292SAndy Fiddaman {
38*32640292SAndy Fiddaman 	struct tpm_passthru *tpm;
39*32640292SAndy Fiddaman 	const char *path;
40*32640292SAndy Fiddaman 
41*32640292SAndy Fiddaman 	tpm = calloc(1, sizeof(struct tpm_passthru));
42*32640292SAndy Fiddaman 	if (tpm == NULL) {
43*32640292SAndy Fiddaman 		warnx("%s: failed to allocate tpm passthru", __func__);
44*32640292SAndy Fiddaman 		return (ENOMEM);
45*32640292SAndy Fiddaman 	}
46*32640292SAndy Fiddaman 
47*32640292SAndy Fiddaman 	path = get_config_value_node(nvl, "path");
48*32640292SAndy Fiddaman 	tpm->fd = open(path, O_RDWR);
49*32640292SAndy Fiddaman 	if (tpm->fd < 0) {
50*32640292SAndy Fiddaman 		warnx("%s: unable to open tpm device \"%s\"", __func__, path);
51*32640292SAndy Fiddaman 		return (ENOENT);
52*32640292SAndy Fiddaman 	}
53*32640292SAndy Fiddaman 
54*32640292SAndy Fiddaman 	*sc = tpm;
55*32640292SAndy Fiddaman 
56*32640292SAndy Fiddaman 	return (0);
57*32640292SAndy Fiddaman }
58*32640292SAndy Fiddaman 
59*32640292SAndy Fiddaman static int
tpm_passthru_execute_cmd(void * sc,void * cmd,uint32_t cmd_size,void * rsp,uint32_t rsp_size)60*32640292SAndy Fiddaman tpm_passthru_execute_cmd(void *sc, void *cmd, uint32_t cmd_size, void *rsp,
61*32640292SAndy Fiddaman     uint32_t rsp_size)
62*32640292SAndy Fiddaman {
63*32640292SAndy Fiddaman 	struct tpm_passthru *tpm;
64*32640292SAndy Fiddaman 	ssize_t len;
65*32640292SAndy Fiddaman 
66*32640292SAndy Fiddaman 	if (rsp_size < (ssize_t)sizeof(struct tpm_resp_hdr)) {
67*32640292SAndy Fiddaman 		warn("%s: rsp_size of %u is too small", __func__, rsp_size);
68*32640292SAndy Fiddaman 		return (EINVAL);
69*32640292SAndy Fiddaman 	}
70*32640292SAndy Fiddaman 
71*32640292SAndy Fiddaman 	tpm = sc;
72*32640292SAndy Fiddaman 
73*32640292SAndy Fiddaman 	len = write(tpm->fd, cmd, cmd_size);
74*32640292SAndy Fiddaman 	if (len != cmd_size) {
75*32640292SAndy Fiddaman 		warn("%s: cmd write failed (bytes written: %zd / %d)", __func__,
76*32640292SAndy Fiddaman 		    len, cmd_size);
77*32640292SAndy Fiddaman 		return (EFAULT);
78*32640292SAndy Fiddaman 	}
79*32640292SAndy Fiddaman 
80*32640292SAndy Fiddaman 	len = read(tpm->fd, rsp, rsp_size);
81*32640292SAndy Fiddaman 	if (len < (ssize_t)sizeof(struct tpm_resp_hdr)) {
82*32640292SAndy Fiddaman 		warn("%s: rsp read failed (bytes read: %zd / %d)", __func__,
83*32640292SAndy Fiddaman 		    len, rsp_size);
84*32640292SAndy Fiddaman 		return (EFAULT);
85*32640292SAndy Fiddaman 	}
86*32640292SAndy Fiddaman 
87*32640292SAndy Fiddaman 	return (0);
88*32640292SAndy Fiddaman }
89*32640292SAndy Fiddaman 
90*32640292SAndy Fiddaman static void
tpm_passthru_deinit(void * sc)91*32640292SAndy Fiddaman tpm_passthru_deinit(void *sc)
92*32640292SAndy Fiddaman {
93*32640292SAndy Fiddaman 	struct tpm_passthru *tpm;
94*32640292SAndy Fiddaman 
95*32640292SAndy Fiddaman 	tpm = sc;
96*32640292SAndy Fiddaman 	if (tpm == NULL)
97*32640292SAndy Fiddaman 		return;
98*32640292SAndy Fiddaman 
99*32640292SAndy Fiddaman 	if (tpm->fd >= 0)
100*32640292SAndy Fiddaman 		close(tpm->fd);
101*32640292SAndy Fiddaman 
102*32640292SAndy Fiddaman 	free(tpm);
103*32640292SAndy Fiddaman }
104*32640292SAndy Fiddaman 
105*32640292SAndy Fiddaman static const struct tpm_emul tpm_emul_passthru = {
106*32640292SAndy Fiddaman 	.name = "passthru",
107*32640292SAndy Fiddaman 	.init = tpm_passthru_init,
108*32640292SAndy Fiddaman 	.deinit = tpm_passthru_deinit,
109*32640292SAndy Fiddaman 	.execute_cmd = tpm_passthru_execute_cmd,
110*32640292SAndy Fiddaman };
111*32640292SAndy Fiddaman TPM_EMUL_SET(tpm_emul_passthru);
112