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