1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (c) 2015 - 2018 Intel Corporation
4 * All rights reserved.
5 * Copyright (c) 2019, Wind River Systems.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <inttypes.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/stat.h>
42 #include <sys/types.h>
43 #ifdef __VXWORKS__
44 #include <sys/poll.h>
45 #else
46 #include <poll.h>
47 #endif
48 #include <unistd.h>
49
50 #include "tss2_tcti.h"
51 #include "tss2_tcti_device.h"
52 #include "tss2_mu.h"
53 #include "tcti-common.h"
54 #include "tcti-device.h"
55 #include "util/io.h"
56 #define LOGMODULE tcti
57 #include "util/log.h"
58
59 #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
60
61 static char *default_conf[] = {
62 #ifdef __VXWORKS__
63 "/tpm0"
64 #else
65 "/dev/tpmrm0",
66 "/dev/tpm0",
67 #endif /* __VX_WORKS__ */
68 };
69
70 /*
71 * This function wraps the "up-cast" of the opaque TCTI context type to the
72 * type for the device TCTI context. The only safe-guard we have to ensure
73 * this operation is possible is the magic number for the device TCTI context.
74 * If passed a NULL context, or the magic number check fails, this function
75 * will return NULL.
76 */
77 TSS2_TCTI_DEVICE_CONTEXT*
tcti_device_context_cast(TSS2_TCTI_CONTEXT * tcti_ctx)78 tcti_device_context_cast (TSS2_TCTI_CONTEXT *tcti_ctx)
79 {
80 if (tcti_ctx != NULL && TSS2_TCTI_MAGIC (tcti_ctx) == TCTI_DEVICE_MAGIC) {
81 return (TSS2_TCTI_DEVICE_CONTEXT*)tcti_ctx;
82 }
83 return NULL;
84 }
85 /*
86 * This function down-casts the device TCTI context to the common context
87 * defined in the tcti-common module.
88 */
89 TSS2_TCTI_COMMON_CONTEXT*
tcti_device_down_cast(TSS2_TCTI_DEVICE_CONTEXT * tcti_dev)90 tcti_device_down_cast (TSS2_TCTI_DEVICE_CONTEXT *tcti_dev)
91 {
92 if (tcti_dev == NULL) {
93 return NULL;
94 }
95 return &tcti_dev->common;
96 }
97
98 TSS2_RC
tcti_device_transmit(TSS2_TCTI_CONTEXT * tctiContext,size_t command_size,const uint8_t * command_buffer)99 tcti_device_transmit (
100 TSS2_TCTI_CONTEXT *tctiContext,
101 size_t command_size,
102 const uint8_t *command_buffer)
103 {
104 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev = tcti_device_context_cast (tctiContext);
105 TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_device_down_cast (tcti_dev);
106 TSS2_RC rc = TSS2_RC_SUCCESS;
107 ssize_t size;
108
109 if (tcti_dev == NULL) {
110 return TSS2_TCTI_RC_BAD_CONTEXT;
111 }
112 rc = tcti_common_transmit_checks (tcti_common, command_buffer);
113 if (rc != TSS2_RC_SUCCESS) {
114 return rc;
115 }
116 LOGBLOB_DEBUG (command_buffer,
117 command_size,
118 "sending %zu byte command buffer:",
119 command_size);
120 size = write_all (tcti_dev->fd,
121 command_buffer,
122 command_size);
123 if (size < 0) {
124 return TSS2_TCTI_RC_IO_ERROR;
125 } else if ((size_t)size != command_size) {
126 LOG_ERROR ("wrong number of bytes written. Expected %zu, wrote %zd.",
127 command_size,
128 size);
129 return TSS2_TCTI_RC_IO_ERROR;
130 }
131
132 tcti_common->state = TCTI_STATE_RECEIVE;
133 return TSS2_RC_SUCCESS;
134 }
135 /*
136 * This receive function deviates from the spec a bit. Calling this function
137 * with a NULL 'tctiContext' parameter *should* result in the required size for
138 * the response buffer being returned to the caller. We would typically do this
139 * by reading the response's header and then returning the size to the caller.
140 * We can't do that on account of the TPM2 kernel driver closing any connection
141 * that doesn't read the whole response buffer in one 'read' call.
142 *
143 * Instead, if the caller queries the size, we return 4k just to be on the
144 * safe side. We do *not* however verify that the provided buffer is large
145 * enough to hold the full response (we can't). If the caller provides us with
146 * a buffer less than 4k we'll read as much of the response as we can given
147 * the size of the buffer. If we get enough of the response to read the size
148 * field, we check to see if the buffer was large enough to get the full
149 * response. If the response header claims it's larger than the provided
150 * buffer we print a warning. This allows "expert applications" to
151 * precalculate the required response buffer size for whatever commands they
152 * may send.
153 */
154 TSS2_RC
tcti_device_receive(TSS2_TCTI_CONTEXT * tctiContext,size_t * response_size,uint8_t * response_buffer,int32_t timeout)155 tcti_device_receive (
156 TSS2_TCTI_CONTEXT *tctiContext,
157 size_t *response_size,
158 uint8_t *response_buffer,
159 int32_t timeout)
160 {
161 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev = tcti_device_context_cast (tctiContext);
162 TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_device_down_cast (tcti_dev);
163 TSS2_RC rc = TSS2_RC_SUCCESS;
164 ssize_t size = 0;
165 struct pollfd fds;
166 int rc_poll, nfds = 1;
167 #ifdef TCTI_PARTIAL_READ
168 uint8_t header[TPM_HEADER_SIZE];
169 size_t offset = 2;
170 UINT32 partial_size;
171 #endif
172
173 if (tcti_dev == NULL) {
174 return TSS2_TCTI_RC_BAD_CONTEXT;
175 }
176 rc = tcti_common_receive_checks (tcti_common, response_size);
177 if (rc != TSS2_RC_SUCCESS) {
178 return rc;
179 }
180 #ifndef TCTI_ASYNC
181 /* For async the valid timeout values are -1 - block forever,
182 * 0 - nonblocking, and any positive value - the actual timeout
183 * value in millisec.
184 * For sync the only valid value is -1 - block forever.
185 */
186 if (timeout != TSS2_TCTI_TIMEOUT_BLOCK) {
187 LOG_WARNING ("The underlying IPC mechanism does not support "
188 "asynchronous I/O. The 'timeout' parameter is set to "
189 "TSS2_TCTI_TIMEOUT_BLOCK");
190 timeout = TSS2_TCTI_TIMEOUT_BLOCK;
191 }
192 #endif
193 if (response_buffer == NULL) {
194 #ifndef TCTI_PARTIAL_READ
195 LOG_DEBUG ("Caller queried for size but linux kernel doesn't allow this. "
196 "Returning 4k which is the max size for a response buffer.");
197 *response_size = 4096;
198 return TSS2_RC_SUCCESS;
199 }
200 #else
201 /* Read the header only and get the response size out of it */
202 LOG_DEBUG("Partial read - reading response size");
203 fds.fd = tcti_dev->fd;
204 fds.events = POLLIN;
205
206 rc_poll = poll(&fds, nfds, timeout);
207 if (rc_poll < 0) {
208 LOG_ERROR ("Failed to poll for response from fd %d, got errno %d: %s",
209 tcti_dev->fd, errno, strerror (errno));
210 return TSS2_TCTI_RC_IO_ERROR;
211 } else if (rc_poll == 0) {
212 LOG_INFO ("Poll timed out on fd %d.", tcti_dev->fd);
213 return TSS2_TCTI_RC_TRY_AGAIN;
214 } else if (fds.revents == POLLIN) {
215 TEMP_RETRY (size, read (tcti_dev->fd, header, TPM_HEADER_SIZE));
216 if (size < 0 || size != TPM_HEADER_SIZE) {
217 LOG_ERROR ("Failed to get response size fd %d, got errno %d: %s",
218 tcti_dev->fd, errno, strerror (errno));
219 return TSS2_TCTI_RC_IO_ERROR;
220 }
221 }
222 LOG_DEBUG("Partial read - received header");
223 rc = Tss2_MU_UINT32_Unmarshal(header, TPM_HEADER_SIZE,
224 &offset, &partial_size);
225 if (rc != TSS2_RC_SUCCESS) {
226 LOG_ERROR ("Failed to unmarshal response size.");
227 return rc;
228 }
229 if (partial_size < TPM_HEADER_SIZE) {
230 LOG_ERROR ("Received %zu bytes, not enough to hold a TPM2 response "
231 "header.", size);
232 return TSS2_TCTI_RC_GENERAL_FAILURE;
233 }
234
235 LOG_DEBUG("Partial read - received response size %d.", partial_size);
236 tcti_common->partial = true;
237 *response_size = partial_size;
238 memcpy(&tcti_common->header, header, TPM_HEADER_SIZE);
239 return rc;
240 }
241 #endif
242
243 #ifndef TCTI_PARTIAL_READ
244 if (*response_size < 4096) {
245 #else
246 if (*response_size < TPM_HEADER_SIZE) {
247 #endif
248 LOG_INFO ("Caller provided buffer that *may* not be large enough to "
249 "hold the response buffer.");
250 }
251
252 /* In case when the whole response is just the 10 bytes header
253 * and we have read it already to get the size, we don't need
254 * to call poll and read again. Just copy what we have read
255 * and return.
256 */
257 if (tcti_common->partial == true && *response_size == TPM_HEADER_SIZE) {
258 memcpy(response_buffer, &tcti_common->header, TPM_HEADER_SIZE);
259 tcti_common->partial = false;
260 goto out;
261 }
262
263 /*
264 * The older kernel driver will only return a response buffer in a single
265 * read operation. If we try to read again before sending another command
266 * the kernel will close the file descriptor and we'll get an EOF.
267 * Newer kernels should have partial reads enabled.
268 */
269 fds.fd = tcti_dev->fd;
270 fds.events = POLLIN;
271
272 rc_poll = poll(&fds, nfds, timeout);
273 if (rc_poll < 0) {
274 LOG_ERROR ("Failed to poll for response from fd %d, got errno %d: %s",
275 tcti_dev->fd, errno, strerror (errno));
276 return TSS2_TCTI_RC_IO_ERROR;
277 } else if (rc_poll == 0) {
278 LOG_INFO ("Poll timed out on fd %d.", tcti_dev->fd);
279 return TSS2_TCTI_RC_TRY_AGAIN;
280 } else if (fds.revents == POLLIN) {
281 if (tcti_common->partial == true) {
282 memcpy(response_buffer, &tcti_common->header, TPM_HEADER_SIZE);
283 TEMP_RETRY (size, read (tcti_dev->fd, response_buffer +
284 TPM_HEADER_SIZE, *response_size - TPM_HEADER_SIZE));
285 } else {
286 TEMP_RETRY (size, read (tcti_dev->fd, response_buffer,
287 *response_size));
288 }
289 if (size < 0) {
290 LOG_ERROR ("Failed to read response from fd %d, got errno %d: %s",
291 tcti_dev->fd, errno, strerror (errno));
292 return TSS2_TCTI_RC_IO_ERROR;
293 }
294 }
295 if (size == 0) {
296 LOG_WARNING ("Got EOF instead of response.");
297 rc = TSS2_TCTI_RC_NO_CONNECTION;
298 goto out;
299 }
300
301 size += tcti_common->partial ? TPM_HEADER_SIZE : 0;
302 LOGBLOB_DEBUG(response_buffer, size, "Response Received");
303 tcti_common->partial = false;
304
305 if ((size_t)size < TPM_HEADER_SIZE) {
306 LOG_ERROR ("Received %zu bytes, not enough to hold a TPM2 response "
307 "header.", size);
308 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
309 goto out;
310 }
311
312 rc = header_unmarshal (response_buffer, &tcti_common->header);
313 if (rc != TSS2_RC_SUCCESS)
314 goto out;
315
316 LOG_DEBUG("Size from header %u bytes read %zu", tcti_common->header.size, size);
317
318 if ((size_t)size != tcti_common->header.size) {
319 LOG_WARNING ("TPM2 response size disagrees with number of bytes read "
320 "from fd %d. Header says %u but we read %zu bytes.",
321 tcti_dev->fd, tcti_common->header.size, size);
322 }
323 if (*response_size < tcti_common->header.size) {
324 LOG_WARNING ("TPM2 response size is larger than the provided "
325 "buffer: future use of this TCTI will likely fail.");
326 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
327 }
328 *response_size = size;
329 /*
330 * Executing code beyond this point transitions the state machine to
331 * TRANSMIT. Another call to this function will not be possible until
332 * another command is sent to the TPM.
333 */
334 out:
335 tcti_common->state = TCTI_STATE_TRANSMIT;
336
337 return rc;
338 }
339
340 void
tcti_device_finalize(TSS2_TCTI_CONTEXT * tctiContext)341 tcti_device_finalize (
342 TSS2_TCTI_CONTEXT *tctiContext)
343 {
344 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev = tcti_device_context_cast (tctiContext);
345 TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_device_down_cast (tcti_dev);
346
347 if (tcti_dev == NULL) {
348 return;
349 }
350 close (tcti_dev->fd);
351 tcti_common->state = TCTI_STATE_FINAL;
352 }
353
354 TSS2_RC
tcti_device_cancel(TSS2_TCTI_CONTEXT * tctiContext)355 tcti_device_cancel (
356 TSS2_TCTI_CONTEXT *tctiContext)
357 {
358 /* Linux driver doesn't expose a mechanism to cancel commands. */
359 (void)(tctiContext);
360 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
361 }
362
363 TSS2_RC
tcti_device_get_poll_handles(TSS2_TCTI_CONTEXT * tctiContext,TSS2_TCTI_POLL_HANDLE * handles,size_t * num_handles)364 tcti_device_get_poll_handles (
365 TSS2_TCTI_CONTEXT *tctiContext,
366 TSS2_TCTI_POLL_HANDLE *handles,
367 size_t *num_handles)
368 {
369 #ifdef TCTI_ASYNC
370 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev = tcti_device_context_cast (tctiContext);
371
372 if (tcti_dev == NULL) {
373 return TSS2_TCTI_RC_BAD_CONTEXT;
374 }
375
376 if (num_handles == NULL) {
377 return TSS2_TCTI_RC_BAD_REFERENCE;
378 }
379
380 if (handles != NULL && *num_handles < 1) {
381 return TSS2_TCTI_RC_INSUFFICIENT_BUFFER;
382 }
383
384 *num_handles = 1;
385 if (handles != NULL) {
386 handles->fd = tcti_dev->fd;
387 }
388
389 return TSS2_RC_SUCCESS;
390 #else
391 (void)(tctiContext);
392 (void)(handles);
393 (void)(num_handles);
394 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
395 #endif
396 }
397
398 TSS2_RC
tcti_device_set_locality(TSS2_TCTI_CONTEXT * tctiContext,uint8_t locality)399 tcti_device_set_locality (
400 TSS2_TCTI_CONTEXT *tctiContext,
401 uint8_t locality)
402 {
403 /*
404 * Linux driver doesn't expose a mechanism for user space applications
405 * to set locality.
406 */
407 (void)(tctiContext);
408 (void)(locality);
409 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
410 }
411
open_tpm(const char * pathname)412 static int open_tpm (
413 const char* pathname) {
414 #ifdef __VXWORKS__
415 return open (pathname, O_RDWR, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
416 #else
417 return open (pathname, O_RDWR | O_NONBLOCK);
418 #endif
419 }
420
421 TSS2_RC
Tss2_Tcti_Device_Init(TSS2_TCTI_CONTEXT * tctiContext,size_t * size,const char * conf)422 Tss2_Tcti_Device_Init (
423 TSS2_TCTI_CONTEXT *tctiContext,
424 size_t *size,
425 const char *conf)
426 {
427 TSS2_TCTI_DEVICE_CONTEXT *tcti_dev;
428 TSS2_TCTI_COMMON_CONTEXT *tcti_common;
429
430 if (tctiContext == NULL && size == NULL) {
431 return TSS2_TCTI_RC_BAD_VALUE;
432 } else if (tctiContext == NULL) {
433 *size = sizeof (TSS2_TCTI_DEVICE_CONTEXT);
434 return TSS2_RC_SUCCESS;
435 }
436
437 /* Init TCTI context */
438 TSS2_TCTI_MAGIC (tctiContext) = TCTI_DEVICE_MAGIC;
439 TSS2_TCTI_VERSION (tctiContext) = TCTI_VERSION;
440 TSS2_TCTI_TRANSMIT (tctiContext) = tcti_device_transmit;
441 TSS2_TCTI_RECEIVE (tctiContext) = tcti_device_receive;
442 TSS2_TCTI_FINALIZE (tctiContext) = tcti_device_finalize;
443 TSS2_TCTI_CANCEL (tctiContext) = tcti_device_cancel;
444 TSS2_TCTI_GET_POLL_HANDLES (tctiContext) = tcti_device_get_poll_handles;
445 TSS2_TCTI_SET_LOCALITY (tctiContext) = tcti_device_set_locality;
446 TSS2_TCTI_MAKE_STICKY (tctiContext) = tcti_make_sticky_not_implemented;
447 tcti_dev = tcti_device_context_cast (tctiContext);
448 tcti_common = tcti_device_down_cast (tcti_dev);
449 tcti_common->state = TCTI_STATE_TRANSMIT;
450 memset (&tcti_common->header, 0, sizeof (tcti_common->header));
451 tcti_common->locality = 3;
452
453 if (conf == NULL) {
454 LOG_TRACE ("No TCTI device file specified");
455
456 for (size_t i = 0; i < ARRAY_LEN(default_conf); i++) {
457 LOG_DEBUG ("Trying to open default TCTI device file %s",
458 default_conf[i]);
459 tcti_dev->fd = open_tpm (default_conf[i]);
460 if (tcti_dev->fd >= 0) {
461 LOG_TRACE ("Successfully opened default TCTI device file %s",
462 default_conf[i]);
463 break;
464 } else {
465 LOG_WARNING ("Failed to open default TCTI device file %s: %s",
466 default_conf[i], strerror (errno));
467 }
468 }
469 if (tcti_dev->fd < 0) {
470 LOG_ERROR ("Could not open any default TCTI device file");
471 return TSS2_TCTI_RC_IO_ERROR;
472 }
473 } else {
474 LOG_DEBUG ("Trying to open specified TCTI device file %s", conf);
475 tcti_dev->fd = open_tpm (conf);
476 if (tcti_dev->fd < 0) {
477 LOG_ERROR ("Failed to open specified TCTI device file %s: %s",
478 conf, strerror (errno));
479 return TSS2_TCTI_RC_IO_ERROR;
480 } else {
481 LOG_TRACE ("Successfully opened specified TCTI device file %s", conf);
482 }
483 }
484
485
486 return TSS2_RC_SUCCESS;
487 }
488
489 const TSS2_TCTI_INFO tss2_tcti_info = {
490 .version = TCTI_VERSION,
491 .name = "tcti-device",
492 .description = "TCTI module for communication with Linux kernel interface.",
493 .config_help = "Path to TPM character device. Default value is: "
494 "TCTI_DEVICE_DEFAULT",
495 .init = Tss2_Tcti_Device_Init,
496 };
497
498 const TSS2_TCTI_INFO*
Tss2_Tcti_Info(void)499 Tss2_Tcti_Info (void)
500 {
501 return &tss2_tcti_info;
502 }
503