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