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 #ifdef __FreeBSD__ 14 #include <malloc_np.h> 15 #else 16 #include <sys/vmm.h> 17 #endif 18 #include <stdlib.h> 19 #include <unistd.h> 20 21 #include "config.h" 22 #include "tpm_device.h" 23 #include "tpm_emul.h" 24 25 struct tpm_passthru { 26 int fd; 27 }; 28 29 struct tpm_resp_hdr { 30 uint16_t tag; 31 uint32_t len; 32 uint32_t errcode; 33 } __packed; 34 35 static int 36 tpm_passthru_init(void **sc, nvlist_t *nvl) 37 { 38 struct tpm_passthru *tpm; 39 const char *path; 40 41 tpm = calloc(1, sizeof(struct tpm_passthru)); 42 if (tpm == NULL) { 43 warnx("%s: failed to allocate tpm passthru", __func__); 44 return (ENOMEM); 45 } 46 47 path = get_config_value_node(nvl, "path"); 48 tpm->fd = open(path, O_RDWR); 49 if (tpm->fd < 0) { 50 warnx("%s: unable to open tpm device \"%s\"", __func__, path); 51 return (ENOENT); 52 } 53 54 *sc = tpm; 55 56 return (0); 57 } 58 59 static int 60 tpm_passthru_execute_cmd(void *sc, void *cmd, uint32_t cmd_size, void *rsp, 61 uint32_t rsp_size) 62 { 63 struct tpm_passthru *tpm; 64 ssize_t len; 65 66 if (rsp_size < (ssize_t)sizeof(struct tpm_resp_hdr)) { 67 warn("%s: rsp_size of %u is too small", __func__, rsp_size); 68 return (EINVAL); 69 } 70 71 tpm = sc; 72 73 len = write(tpm->fd, cmd, cmd_size); 74 if (len != cmd_size) { 75 warn("%s: cmd write failed (bytes written: %zd / %d)", __func__, 76 len, cmd_size); 77 return (EFAULT); 78 } 79 80 len = read(tpm->fd, rsp, rsp_size); 81 if (len < (ssize_t)sizeof(struct tpm_resp_hdr)) { 82 warn("%s: rsp read failed (bytes read: %zd / %d)", __func__, 83 len, rsp_size); 84 return (EFAULT); 85 } 86 87 return (0); 88 } 89 90 static void 91 tpm_passthru_deinit(void *sc) 92 { 93 struct tpm_passthru *tpm; 94 95 tpm = sc; 96 if (tpm == NULL) 97 return; 98 99 if (tpm->fd >= 0) 100 close(tpm->fd); 101 102 free(tpm); 103 } 104 105 static const struct tpm_emul tpm_emul_passthru = { 106 .name = "passthru", 107 .init = tpm_passthru_init, 108 .deinit = tpm_passthru_deinit, 109 .execute_cmd = tpm_passthru_execute_cmd, 110 }; 111 TPM_EMUL_SET(tpm_emul_passthru); 112