1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2024 Hans Rosenfeld 5 * Author: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> 6 */ 7 8 #include <sys/types.h> 9 #include <sys/socket.h> 10 #include <sys/un.h> 11 12 #include <err.h> 13 #include <errno.h> 14 #include <fcntl.h> 15 #include <malloc_np.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <strings.h> 19 #include <unistd.h> 20 21 #include "config.h" 22 #include "tpm_device.h" 23 #include "tpm_emul.h" 24 25 struct tpm_swtpm { 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_swtpm_init(void **sc, nvlist_t *nvl) 37 { 38 struct tpm_swtpm *tpm; 39 const char *path; 40 struct sockaddr_un tpm_addr; 41 42 tpm = calloc(1, sizeof (struct tpm_swtpm)); 43 if (tpm == NULL) { 44 warnx("%s: failed to allocate tpm_swtpm", __func__); 45 return (ENOMEM); 46 } 47 48 path = get_config_value_node(nvl, "path"); 49 if (path == NULL) { 50 warnx("%s: no socket path specified", __func__); 51 return (ENOENT); 52 } 53 54 tpm->fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 55 if (tpm->fd < 0) { 56 warnx("%s: unable to open tpm socket", __func__); 57 return (ENOENT); 58 } 59 60 bzero(&tpm_addr, sizeof (tpm_addr)); 61 tpm_addr.sun_family = AF_UNIX; 62 strlcpy(tpm_addr.sun_path, path, sizeof (tpm_addr.sun_path) - 1); 63 64 if (connect(tpm->fd, (struct sockaddr *)&tpm_addr, sizeof (tpm_addr)) == 65 -1) { 66 warnx("%s: unable to connect to tpm socket \"%s\"", __func__, 67 path); 68 return (ENOENT); 69 } 70 71 *sc = tpm; 72 73 return (0); 74 } 75 76 static int 77 tpm_swtpm_execute_cmd(void *sc, void *cmd, uint32_t cmd_size, void *rsp, 78 uint32_t rsp_size) 79 { 80 struct tpm_swtpm *tpm; 81 ssize_t len; 82 83 if (rsp_size < (ssize_t)sizeof(struct tpm_resp_hdr)) { 84 warn("%s: rsp_size of %u is too small", __func__, rsp_size); 85 return (EINVAL); 86 } 87 88 tpm = sc; 89 90 len = send(tpm->fd, cmd, cmd_size, MSG_NOSIGNAL|MSG_DONTWAIT); 91 if (len == -1) 92 err(1, "%s: cmd send failed, is swtpm running?", __func__); 93 if (len != cmd_size) { 94 warn("%s: cmd write failed (bytes written: %zd / %d)", __func__, 95 len, cmd_size); 96 return (EFAULT); 97 } 98 99 len = recv(tpm->fd, rsp, rsp_size, 0); 100 if (len == -1) 101 err(1, "%s: rsp recv failed, is swtpm running?", __func__); 102 if (len < (ssize_t)sizeof(struct tpm_resp_hdr)) { 103 warn("%s: rsp read failed (bytes read: %zd / %d)", __func__, 104 len, rsp_size); 105 return (EFAULT); 106 } 107 108 return (0); 109 } 110 111 static void 112 tpm_swtpm_deinit(void *sc) 113 { 114 struct tpm_swtpm *tpm; 115 116 tpm = sc; 117 if (tpm == NULL) 118 return; 119 120 if (tpm->fd >= 0) 121 close(tpm->fd); 122 123 free(tpm); 124 } 125 126 static const struct tpm_emul tpm_emul_swtpm = { 127 .name = "swtpm", 128 .init = tpm_swtpm_init, 129 .deinit = tpm_swtpm_deinit, 130 .execute_cmd = tpm_swtpm_execute_cmd, 131 }; 132 TPM_EMUL_SET(tpm_emul_swtpm); 133