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 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 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 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