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