blob: a5d0f4783d603f5bf6eb487a6af64dc88d49bd3e [file] [log] [blame]
Peter Huewed5a36f62018-06-12 00:59:26 +02001/* SPDX-License-Identifier: BSD-2 */
Philip Tricca21fa3212018-02-19 06:43:56 -08002/*
3 * Copyright (c) 2015 - 2018 Intel Corporation
Philip Triccaa003d762017-10-17 13:25:42 -07004 * All rights reserved.
Philip Tricca21fa3212018-02-19 06:43:56 -08005 */
Will Arthurca8e7f32015-08-03 15:35:19 -04006
Will Arthurca8e7f32015-08-03 15:35:19 -04007#include <errno.h>
Will Arthurca8e7f32015-08-03 15:35:19 -04008#include <fcntl.h>
Andreas Fuchs43a0d762017-11-30 15:41:05 +01009#include <inttypes.h>
Philip Triccab5fe1032018-02-27 15:05:44 -080010#include <stdio.h>
11#include <stdlib.h>
Philip Tricca72976fc2018-02-27 16:54:58 -080012#include <string.h>
Philip Triccab5fe1032018-02-27 15:05:44 -080013#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
16
Philip Tricca910f17c2018-03-15 12:38:37 -070017#include "tss2_tcti.h"
Philip Tricca8ffd3c42018-03-09 16:27:24 -080018#include "tss2_tcti_device.h"
Philip Tricca850bb592018-04-03 09:29:22 -070019
20#include "tcti-common.h"
21#include "tcti-device.h"
22#include "util/io.h"
Andreas Fuchs43a0d762017-11-30 15:41:05 +010023#define LOGMODULE tcti
Philip Triccaa7c51ce2018-03-10 18:28:25 -080024#include "util/log.h"
Will Arthurca8e7f32015-08-03 15:35:19 -040025
Philip Tricca5a235282018-02-27 14:59:49 -080026#define TCTI_DEVICE_DEFAULT "/dev/tpm0"
Philip Tricca850bb592018-04-03 09:29:22 -070027/*
28 * This function wraps the "up-cast" of the opaque TCTI context type to the
29 * type for the device TCTI context. The only safe-guard we have to ensure
30 * this operation is possible is the magic number for the device TCTI context.
31 * If passed a NULL context, or the magic number check fails, this function
32 * will return NULL.
33 */
34TSS2_TCTI_DEVICE_CONTEXT*
35tcti_device_context_cast (TSS2_TCTI_CONTEXT *tcti_ctx)
36{
37 if (tcti_ctx != NULL && TSS2_TCTI_MAGIC (tcti_ctx) == TCTI_DEVICE_MAGIC) {
38 return (TSS2_TCTI_DEVICE_CONTEXT*)tcti_ctx;
39 }
40 return NULL;
41}
42/*
43 * This function down-casts the device TCTI context to the common context
44 * defined in the tcti-common module.
45 */
46TSS2_TCTI_COMMON_CONTEXT*
47tcti_device_down_cast (TSS2_TCTI_DEVICE_CONTEXT *tcti_dev)
48{
49 if (tcti_dev == NULL) {
50 return NULL;
51 }
52 return &tcti_dev->common;
53}
Philip Tricca5a235282018-02-27 14:59:49 -080054
Philip Triccadf25eae2018-02-27 15:21:20 -080055TSS2_RC
56tcti_device_transmit (
Philip Triccaa003d762017-10-17 13:25:42 -070057 TSS2_TCTI_CONTEXT *tctiContext,
58 size_t command_size,
Philip Triccadf25eae2018-02-27 15:21:20 -080059 const uint8_t *command_buffer)
Will Arthurca8e7f32015-08-03 15:35:19 -040060{
Philip Tricca850bb592018-04-03 09:29:22 -070061 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev = tcti_device_context_cast (tctiContext);
62 TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_device_down_cast (tcti_dev);
Philip Triccacac4c3a2018-03-05 18:21:41 -080063 TSS2_RC rc = TSS2_RC_SUCCESS;
Will Arthurca8e7f32015-08-03 15:35:19 -040064 ssize_t size;
65
Philip Tricca850bb592018-04-03 09:29:22 -070066 if (tcti_dev == NULL) {
67 return TSS2_TCTI_RC_BAD_CONTEXT;
68 }
69 rc = tcti_common_transmit_checks (tcti_common, command_buffer);
Philip Triccacac4c3a2018-03-05 18:21:41 -080070 if (rc != TSS2_RC_SUCCESS) {
71 return rc;
Philip Triccaa003d762017-10-17 13:25:42 -070072 }
Philip Tricca382f40e2018-02-19 07:43:00 -080073 LOGBLOB_DEBUG (command_buffer,
74 command_size,
Philip Triccaefe1d062018-02-19 07:59:21 -080075 "sending %zu byte command buffer:",
Philip Tricca382f40e2018-02-19 07:43:00 -080076 command_size);
Philip Tricca850bb592018-04-03 09:29:22 -070077 size = write_all (tcti_dev->fd,
Philip Triccae487b992018-02-19 15:42:48 -080078 command_buffer,
79 command_size);
Philip Triccaa003d762017-10-17 13:25:42 -070080 if (size < 0) {
Philip Triccaa003d762017-10-17 13:25:42 -070081 return TSS2_TCTI_RC_IO_ERROR;
82 } else if ((size_t)size != command_size) {
Philip Triccaefe1d062018-02-19 07:59:21 -080083 LOG_ERROR ("wrong number of bytes written. Expected %zu, wrote %zd.",
84 command_size,
85 size);
Philip Triccaa003d762017-10-17 13:25:42 -070086 return TSS2_TCTI_RC_IO_ERROR;
wcarthureedecd62015-11-20 16:59:45 -050087 }
Philip Triccadfa41a52016-07-20 17:43:57 -070088
Philip Tricca850bb592018-04-03 09:29:22 -070089 tcti_common->state = TCTI_STATE_RECEIVE;
Philip Triccaa003d762017-10-17 13:25:42 -070090 return TSS2_RC_SUCCESS;
Will Arthurca8e7f32015-08-03 15:35:19 -040091}
Philip Tricca7ce0cc42018-04-08 18:41:05 -070092/*
93 * This receive function deviates from the spec a bit. Calling this function
94 * with a NULL 'tctiContext' parameter *should* result in the required size for
95 * the response buffer being returned to the caller. We would typically do this
96 * by reading the response's header and then returning the size to the caller.
97 * We can't do that on account of the TPM2 kernel driver closing any connection
98 * that doesn't read the whole response buffer in one 'read' call.
99 *
100 * Instead, if the caller queries the size, we return 4k just to be on the
101 * safe side. We do *not* however verify that the provided buffer is large
102 * enough to hold the full response (we can't). If the caller provides us with
103 * a buffer less than 4k we'll read as much of the response as we can given
104 * the size of the buffer. If we get enough of the response to read the size
105 * field, we check to see if the buffer was large enough to get the full
106 * response. If the response header claims it's larger than the provided
107 * buffer we print a warning. This allows "expert applications" to
108 * precalculate the required response buffer size for whatever commands they
109 * may send.
110 */
Philip Triccadf25eae2018-02-27 15:21:20 -0800111TSS2_RC
112tcti_device_receive (
Philip Triccaa003d762017-10-17 13:25:42 -0700113 TSS2_TCTI_CONTEXT *tctiContext,
114 size_t *response_size,
Philip Tricca32c41582018-02-23 05:28:23 +0000115 uint8_t *response_buffer,
Philip Triccadf25eae2018-02-27 15:21:20 -0800116 int32_t timeout)
Will Arthurca8e7f32015-08-03 15:35:19 -0400117{
Philip Tricca850bb592018-04-03 09:29:22 -0700118 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev = tcti_device_context_cast (tctiContext);
119 TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_device_down_cast (tcti_dev);
Philip Triccacac4c3a2018-03-05 18:21:41 -0800120 TSS2_RC rc = TSS2_RC_SUCCESS;
Will Arthurca8e7f32015-08-03 15:35:19 -0400121 ssize_t size;
Philip Triccadfa41a52016-07-20 17:43:57 -0700122
Philip Tricca850bb592018-04-03 09:29:22 -0700123 if (tcti_dev == NULL) {
124 return TSS2_TCTI_RC_BAD_CONTEXT;
125 }
126 rc = tcti_common_receive_checks (tcti_common, response_size);
Philip Triccacac4c3a2018-03-05 18:21:41 -0800127 if (rc != TSS2_RC_SUCCESS) {
Philip Tricca5477c2a2018-03-07 15:39:28 -0800128 return rc;
Philip Triccadfa41a52016-07-20 17:43:57 -0700129 }
Philip Triccae9416f32018-02-27 16:08:00 -0800130 if (timeout != TSS2_TCTI_TIMEOUT_BLOCK) {
131 LOG_WARNING ("The underlying IPC mechanism does not support "
132 "asynchronous I/O. The 'timeout' parameter must be "
133 "TSS2_TCTI_TIMEOUT_BLOCK");
134 return TSS2_TCTI_RC_BAD_VALUE;
135 }
Philip Triccaa003d762017-10-17 13:25:42 -0700136 if (response_buffer == NULL) {
Philip Tricca7ce0cc42018-04-08 18:41:05 -0700137 LOG_DEBUG ("Caller queried for size but linux kernel doesn't allow this. "
138 "Returning 4k which is the max size for a response buffer.");
139 *response_size = 4096;
Philip Tricca5477c2a2018-03-07 15:39:28 -0800140 return TSS2_RC_SUCCESS;
Will Arthurca8e7f32015-08-03 15:35:19 -0400141 }
Philip Tricca7ce0cc42018-04-08 18:41:05 -0700142 if (*response_size < 4096) {
143 LOG_INFO ("Caller provided buffer that *may* not be large enough to "
144 "hold the response buffer.");
Philip Triccadfa41a52016-07-20 17:43:57 -0700145 }
Philip Tricca7ce0cc42018-04-08 18:41:05 -0700146 /*
147 * The kernel driver will only return a response buffer in a single read
148 * operation. If we try to read again before sending another command
149 * the kernel will close the file descriptor and we'll get an EOF.
150 */
David J. Maria06db5752018-06-19 14:52:37 -0700151 TEMP_RETRY (size, read (tcti_dev->fd, response_buffer, *response_size));
Philip Tricca7a10ee32018-03-06 12:48:39 -0800152 if (size < 0) {
Philip Tricca7ce0cc42018-04-08 18:41:05 -0700153 LOG_ERROR ("Failed to read response from fd %d, got errno %d: %s",
154 tcti_dev->fd, errno, strerror (errno));
155 return TSS2_TCTI_RC_IO_ERROR;
156 }
157 if (size == 0) {
158 LOG_WARNING ("Got EOF instead of response.");
159 rc = TSS2_TCTI_RC_NO_CONNECTION;
Philip Tricca850bb592018-04-03 09:29:22 -0700160 goto out;
wcarthur74a92a42015-12-07 16:02:12 -0500161 }
Philip Tricca7ce0cc42018-04-08 18:41:05 -0700162 LOGBLOB_DEBUG(response_buffer, size, "Response Received");
163 if (size < (ssize_t)TPM_HEADER_SIZE) {
164 LOG_ERROR ("Received %zu bytes, not enough to hold a TPM2 response "
165 "header.", size);
166 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
167 goto out;
168 }
169 rc = header_unmarshal (response_buffer, &tcti_common->header);
170 if (rc != TSS2_RC_SUCCESS) {
171 goto out;
172 }
173 if ((size_t)size != tcti_common->header.size) {
174 LOG_WARNING ("TPM2 header size disagrees with number of bytes read "
175 "from fd %d. Header says %u but we read %zu bytes.",
Philip Tricca097cae62018-04-08 13:42:29 -0700176 tcti_dev->fd, tcti_common->header.size, size);
Philip Tricca7ce0cc42018-04-08 18:41:05 -0700177 }
178 if (*response_size < tcti_common->header.size) {
179 LOG_WARNING ("TPM2 response header size is larger than the provided "
180 "buffer: future use of this TCTI will likely fail.");
181 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
182 }
183 *response_size = size;
Philip Tricca5477c2a2018-03-07 15:39:28 -0800184 /*
185 * Executing code beyond this point transitions the state machine to
186 * TRANSMIT. Another call to this function will not be possible until
187 * another command is sent to the TPM.
188 */
Philip Tricca850bb592018-04-03 09:29:22 -0700189out:
Philip Tricca850bb592018-04-03 09:29:22 -0700190 tcti_common->state = TCTI_STATE_TRANSMIT;
Philip Triccadfa41a52016-07-20 17:43:57 -0700191
Philip Triccacac4c3a2018-03-05 18:21:41 -0800192 return rc;
Will Arthurca8e7f32015-08-03 15:35:19 -0400193}
194
Philip Triccadf25eae2018-02-27 15:21:20 -0800195void
196tcti_device_finalize (
197 TSS2_TCTI_CONTEXT *tctiContext)
Will Arthurca8e7f32015-08-03 15:35:19 -0400198{
Philip Tricca850bb592018-04-03 09:29:22 -0700199 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev = tcti_device_context_cast (tctiContext);
200 TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_device_down_cast (tcti_dev);
Philip Tricca24f555c2017-10-13 17:51:53 -0700201
Philip Tricca850bb592018-04-03 09:29:22 -0700202 if (tcti_dev == NULL) {
Philip Tricca3f1828c2017-10-18 18:44:13 -0700203 return;
wcarthurf979e352015-11-24 17:34:44 -0500204 }
Philip Tricca850bb592018-04-03 09:29:22 -0700205 close (tcti_dev->fd);
206 tcti_common->state = TCTI_STATE_FINAL;
Will Arthurca8e7f32015-08-03 15:35:19 -0400207}
208
Philip Triccadf25eae2018-02-27 15:21:20 -0800209TSS2_RC
210tcti_device_cancel (
211 TSS2_TCTI_CONTEXT *tctiContext)
Will Arthurca8e7f32015-08-03 15:35:19 -0400212{
Philip Tricca5917fbf2017-06-29 08:24:09 -0700213 /* Linux driver doesn't expose a mechanism to cancel commands. */
Andreas Fuchsbaeb2be2018-03-29 15:39:50 +0200214 (void)(tctiContext);
Philip Tricca5917fbf2017-06-29 08:24:09 -0700215 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
216}
Will Arthurca8e7f32015-08-03 15:35:19 -0400217
Philip Triccadf25eae2018-02-27 15:21:20 -0800218TSS2_RC
219tcti_device_get_poll_handles (
Philip Triccaa003d762017-10-17 13:25:42 -0700220 TSS2_TCTI_CONTEXT *tctiContext,
Philip Tricca5917fbf2017-06-29 08:24:09 -0700221 TSS2_TCTI_POLL_HANDLE *handles,
Philip Triccaa003d762017-10-17 13:25:42 -0700222 size_t *num_handles)
Philip Tricca5917fbf2017-06-29 08:24:09 -0700223{
224 /* Linux driver doesn't support polling. */
Andreas Fuchsbaeb2be2018-03-29 15:39:50 +0200225 (void)(tctiContext);
226 (void)(handles);
227 (void)(num_handles);
Philip Tricca5917fbf2017-06-29 08:24:09 -0700228 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
Will Arthurca8e7f32015-08-03 15:35:19 -0400229}
230
Philip Triccadf25eae2018-02-27 15:21:20 -0800231TSS2_RC
232tcti_device_set_locality (
Philip Triccaa003d762017-10-17 13:25:42 -0700233 TSS2_TCTI_CONTEXT *tctiContext,
Philip Triccadf25eae2018-02-27 15:21:20 -0800234 uint8_t locality)
Will Arthurca8e7f32015-08-03 15:35:19 -0400235{
Philip Tricca5917fbf2017-06-29 08:24:09 -0700236 /*
237 * Linux driver doesn't expose a mechanism for user space applications
238 * to set locality.
239 */
Andreas Fuchsbaeb2be2018-03-29 15:39:50 +0200240 (void)(tctiContext);
241 (void)(locality);
Philip Tricca5917fbf2017-06-29 08:24:09 -0700242 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
Will Arthurca8e7f32015-08-03 15:35:19 -0400243}
244
Philip Triccadf25eae2018-02-27 15:21:20 -0800245TSS2_RC
246Tss2_Tcti_Device_Init (
Philip Triccaa003d762017-10-17 13:25:42 -0700247 TSS2_TCTI_CONTEXT *tctiContext,
Philip Tricca5a235282018-02-27 14:59:49 -0800248 size_t *size,
Philip Triccadf25eae2018-02-27 15:21:20 -0800249 const char *conf)
Will Arthurca8e7f32015-08-03 15:35:19 -0400250{
Philip Tricca850bb592018-04-03 09:29:22 -0700251 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev;
252 TSS2_TCTI_COMMON_CONTEXT *tcti_common;
Philip Tricca5a235282018-02-27 14:59:49 -0800253 const char *dev_path = conf != NULL ? conf : TCTI_DEVICE_DEFAULT;
Will Arthurca8e7f32015-08-03 15:35:19 -0400254
Philip Tricca5a235282018-02-27 14:59:49 -0800255 if (tctiContext == NULL && size == NULL) {
Philip Tricca5fd02f72016-11-17 18:22:04 -0800256 return TSS2_TCTI_RC_BAD_VALUE;
Philip Triccaa003d762017-10-17 13:25:42 -0700257 } else if (tctiContext == NULL) {
Philip Tricca850bb592018-04-03 09:29:22 -0700258 *size = sizeof (TSS2_TCTI_DEVICE_CONTEXT);
Will Arthurca8e7f32015-08-03 15:35:19 -0400259 return TSS2_RC_SUCCESS;
260 }
Philip Tricca068d5632016-03-11 12:23:40 -0800261
Philip Triccaa003d762017-10-17 13:25:42 -0700262 /* Init TCTI context */
Philip Tricca850bb592018-04-03 09:29:22 -0700263 TSS2_TCTI_MAGIC (tctiContext) = TCTI_DEVICE_MAGIC;
Philip Triccaa003d762017-10-17 13:25:42 -0700264 TSS2_TCTI_VERSION (tctiContext) = TCTI_VERSION;
Philip Triccadf25eae2018-02-27 15:21:20 -0800265 TSS2_TCTI_TRANSMIT (tctiContext) = tcti_device_transmit;
266 TSS2_TCTI_RECEIVE (tctiContext) = tcti_device_receive;
267 TSS2_TCTI_FINALIZE (tctiContext) = tcti_device_finalize;
268 TSS2_TCTI_CANCEL (tctiContext) = tcti_device_cancel;
269 TSS2_TCTI_GET_POLL_HANDLES (tctiContext) = tcti_device_get_poll_handles;
270 TSS2_TCTI_SET_LOCALITY (tctiContext) = tcti_device_set_locality;
Philip Triccaee411152018-02-23 19:16:04 -0800271 TSS2_TCTI_MAKE_STICKY (tctiContext) = tcti_make_sticky_not_implemented;
Philip Tricca850bb592018-04-03 09:29:22 -0700272 tcti_dev = tcti_device_context_cast (tctiContext);
273 tcti_common = tcti_device_down_cast (tcti_dev);
274 tcti_common->state = TCTI_STATE_TRANSMIT;
275 memset (&tcti_common->header, 0, sizeof (tcti_common->header));
276 tcti_common->locality = 3;
Philip Triccaa003d762017-10-17 13:25:42 -0700277
Philip Tricca850bb592018-04-03 09:29:22 -0700278 tcti_dev->fd = open (dev_path, O_RDWR);
279 if (tcti_dev->fd < 0) {
Philip Tricca72976fc2018-02-27 16:54:58 -0800280 LOG_ERROR ("Failed to open device file %s: %s",
281 dev_path, strerror (errno));
Philip Triccaa003d762017-10-17 13:25:42 -0700282 return TSS2_TCTI_RC_IO_ERROR;
Will Arthurca8e7f32015-08-03 15:35:19 -0400283 }
284
Philip Tricca5a235282018-02-27 14:59:49 -0800285 return TSS2_RC_SUCCESS;
Philip Tricca6d4ae3e2017-12-06 14:23:52 -0800286}
287
Andreas Fuchs37b45c62018-03-29 16:54:33 +0200288const TSS2_TCTI_INFO tss2_tcti_info = {
Philip Triccadf1410e2018-04-23 13:07:17 -0700289 .version = TCTI_VERSION,
Philip Tricca6d4ae3e2017-12-06 14:23:52 -0800290 .name = "tcti-device",
291 .description = "TCTI module for communication with Linux kernel interface.",
Philip Tricca001e8bf2018-01-08 16:52:09 -0800292 .config_help = "Path to TPM character device. Default value is: "
293 "TCTI_DEVICE_DEFAULT",
Philip Tricca6d4ae3e2017-12-06 14:23:52 -0800294 .init = Tss2_Tcti_Device_Init,
295};
296
297const TSS2_TCTI_INFO*
298Tss2_Tcti_Info (void)
299{
300 return &tss2_tcti_info;
301}