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