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