1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag * Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag * All rights reserved.
5*758e9fbaSOystein Eftevaag *******************************************************************************/
6*758e9fbaSOystein Eftevaag
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag
11*758e9fbaSOystein Eftevaag #include <stdbool.h>
12*758e9fbaSOystein Eftevaag #include <stdlib.h>
13*758e9fbaSOystein Eftevaag #include <string.h>
14*758e9fbaSOystein Eftevaag
15*758e9fbaSOystein Eftevaag #include "tss2_esys.h"
16*758e9fbaSOystein Eftevaag
17*758e9fbaSOystein Eftevaag #include "test-esapi.h"
18*758e9fbaSOystein Eftevaag #include "test-options.h"
19*758e9fbaSOystein Eftevaag #include "context-util.h"
20*758e9fbaSOystein Eftevaag #include "tss2-esys/esys_int.h"
21*758e9fbaSOystein Eftevaag #define LOGMODULE test
22*758e9fbaSOystein Eftevaag #include "util/log.h"
23*758e9fbaSOystein Eftevaag
24*758e9fbaSOystein Eftevaag /** Define a proxy tcti that returns yielded on every second invocation
25*758e9fbaSOystein Eftevaag * thus the corresponding handling code in ESAPI can be tested.
26*758e9fbaSOystein Eftevaag * The first invocation will be Tss2_Sys_StartUp.
27*758e9fbaSOystein Eftevaag */
28*758e9fbaSOystein Eftevaag
29*758e9fbaSOystein Eftevaag TSS2_RC
30*758e9fbaSOystein Eftevaag (*transmit_hook) (const uint8_t *command_buffer, size_t command_size) = NULL;
31*758e9fbaSOystein Eftevaag
32*758e9fbaSOystein Eftevaag #define TCTI_PROXY_MAGIC 0x5250584f0a000000ULL /* 'PROXY\0\0\0' */
33*758e9fbaSOystein Eftevaag #define TCTI_PROXY_VERSION 0x1
34*758e9fbaSOystein Eftevaag
35*758e9fbaSOystein Eftevaag enum state {
36*758e9fbaSOystein Eftevaag forwarding,
37*758e9fbaSOystein Eftevaag intercepting
38*758e9fbaSOystein Eftevaag };
39*758e9fbaSOystein Eftevaag
40*758e9fbaSOystein Eftevaag typedef struct {
41*758e9fbaSOystein Eftevaag uint64_t magic;
42*758e9fbaSOystein Eftevaag uint32_t version;
43*758e9fbaSOystein Eftevaag TSS2_TCTI_TRANSMIT_FCN transmit;
44*758e9fbaSOystein Eftevaag TSS2_TCTI_RECEIVE_FCN receive;
45*758e9fbaSOystein Eftevaag TSS2_RC (*finalize) (TSS2_TCTI_CONTEXT *tctiContext);
46*758e9fbaSOystein Eftevaag TSS2_RC (*cancel) (TSS2_TCTI_CONTEXT *tctiContext);
47*758e9fbaSOystein Eftevaag TSS2_RC (*getPollHandles) (TSS2_TCTI_CONTEXT *tctiContext,
48*758e9fbaSOystein Eftevaag TSS2_TCTI_POLL_HANDLE *handles, size_t *num_handles);
49*758e9fbaSOystein Eftevaag TSS2_RC (*setLocality) (TSS2_TCTI_CONTEXT *tctiContext, uint8_t locality);
50*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tctiInner;
51*758e9fbaSOystein Eftevaag enum state state;
52*758e9fbaSOystein Eftevaag } TSS2_TCTI_CONTEXT_PROXY;
53*758e9fbaSOystein Eftevaag
54*758e9fbaSOystein Eftevaag static TSS2_TCTI_CONTEXT_PROXY*
tcti_proxy_cast(TSS2_TCTI_CONTEXT * ctx)55*758e9fbaSOystein Eftevaag tcti_proxy_cast (TSS2_TCTI_CONTEXT *ctx)
56*758e9fbaSOystein Eftevaag {
57*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT_PROXY *ctxi = (TSS2_TCTI_CONTEXT_PROXY*)ctx;
58*758e9fbaSOystein Eftevaag if (ctxi == NULL || ctxi->magic != TCTI_PROXY_MAGIC) {
59*758e9fbaSOystein Eftevaag LOG_ERROR("Bad tcti passed.");
60*758e9fbaSOystein Eftevaag return NULL;
61*758e9fbaSOystein Eftevaag }
62*758e9fbaSOystein Eftevaag return ctxi;
63*758e9fbaSOystein Eftevaag }
64*758e9fbaSOystein Eftevaag
65*758e9fbaSOystein Eftevaag static TSS2_RC
tcti_proxy_transmit(TSS2_TCTI_CONTEXT * tctiContext,size_t command_size,const uint8_t * command_buffer)66*758e9fbaSOystein Eftevaag tcti_proxy_transmit(
67*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tctiContext,
68*758e9fbaSOystein Eftevaag size_t command_size,
69*758e9fbaSOystein Eftevaag const uint8_t *command_buffer
70*758e9fbaSOystein Eftevaag )
71*758e9fbaSOystein Eftevaag {
72*758e9fbaSOystein Eftevaag TSS2_RC rval;
73*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT_PROXY *tcti_proxy = tcti_proxy_cast(tctiContext);
74*758e9fbaSOystein Eftevaag
75*758e9fbaSOystein Eftevaag if (tcti_proxy->state == intercepting) {
76*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
77*758e9fbaSOystein Eftevaag }
78*758e9fbaSOystein Eftevaag
79*758e9fbaSOystein Eftevaag if (transmit_hook != NULL) {
80*758e9fbaSOystein Eftevaag rval = transmit_hook(command_buffer, command_size);
81*758e9fbaSOystein Eftevaag if (rval != TSS2_RC_SUCCESS) {
82*758e9fbaSOystein Eftevaag LOG_ERROR("transmit hook requested error");
83*758e9fbaSOystein Eftevaag return rval;
84*758e9fbaSOystein Eftevaag }
85*758e9fbaSOystein Eftevaag }
86*758e9fbaSOystein Eftevaag
87*758e9fbaSOystein Eftevaag rval = Tss2_Tcti_Transmit(tcti_proxy->tctiInner, command_size,
88*758e9fbaSOystein Eftevaag command_buffer);
89*758e9fbaSOystein Eftevaag if (rval != TSS2_RC_SUCCESS) {
90*758e9fbaSOystein Eftevaag LOG_ERROR("Calling TCTI Transmit");
91*758e9fbaSOystein Eftevaag return rval;
92*758e9fbaSOystein Eftevaag }
93*758e9fbaSOystein Eftevaag
94*758e9fbaSOystein Eftevaag return rval;
95*758e9fbaSOystein Eftevaag }
96*758e9fbaSOystein Eftevaag
97*758e9fbaSOystein Eftevaag uint8_t yielded_response[] = {
98*758e9fbaSOystein Eftevaag 0x80, 0x01, /* TPM_ST_NO_SESSION */
99*758e9fbaSOystein Eftevaag 0x00, 0x00, 0x00, 0x0A, /* Response Size 10 */
100*758e9fbaSOystein Eftevaag 0x00, 0x00, 0x09, 0x08 /* TPM_RC_YIELDED */
101*758e9fbaSOystein Eftevaag };
102*758e9fbaSOystein Eftevaag
103*758e9fbaSOystein Eftevaag static TSS2_RC
tcti_proxy_receive(TSS2_TCTI_CONTEXT * tctiContext,size_t * response_size,uint8_t * response_buffer,int32_t timeout)104*758e9fbaSOystein Eftevaag tcti_proxy_receive(
105*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tctiContext,
106*758e9fbaSOystein Eftevaag size_t *response_size,
107*758e9fbaSOystein Eftevaag uint8_t *response_buffer,
108*758e9fbaSOystein Eftevaag int32_t timeout
109*758e9fbaSOystein Eftevaag )
110*758e9fbaSOystein Eftevaag {
111*758e9fbaSOystein Eftevaag TSS2_RC rval;
112*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT_PROXY *tcti_proxy = tcti_proxy_cast(tctiContext);
113*758e9fbaSOystein Eftevaag
114*758e9fbaSOystein Eftevaag if (tcti_proxy->state == intercepting) {
115*758e9fbaSOystein Eftevaag *response_size = sizeof(yielded_response);
116*758e9fbaSOystein Eftevaag
117*758e9fbaSOystein Eftevaag if (response_buffer != NULL) {
118*758e9fbaSOystein Eftevaag memcpy(response_buffer, &yielded_response[0], sizeof(yielded_response));
119*758e9fbaSOystein Eftevaag tcti_proxy->state = forwarding;
120*758e9fbaSOystein Eftevaag }
121*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
122*758e9fbaSOystein Eftevaag }
123*758e9fbaSOystein Eftevaag
124*758e9fbaSOystein Eftevaag rval = Tss2_Tcti_Receive(tcti_proxy->tctiInner, response_size,
125*758e9fbaSOystein Eftevaag response_buffer, timeout);
126*758e9fbaSOystein Eftevaag if (rval != TSS2_RC_SUCCESS) {
127*758e9fbaSOystein Eftevaag LOG_ERROR("Calling TCTI Transmit");
128*758e9fbaSOystein Eftevaag return rval;
129*758e9fbaSOystein Eftevaag }
130*758e9fbaSOystein Eftevaag
131*758e9fbaSOystein Eftevaag /* First read with response buffer == NULL is to get the size of the
132*758e9fbaSOystein Eftevaag * response. The subsequent read needs to be forwarded also */
133*758e9fbaSOystein Eftevaag if (response_buffer != NULL)
134*758e9fbaSOystein Eftevaag tcti_proxy->state = intercepting;
135*758e9fbaSOystein Eftevaag
136*758e9fbaSOystein Eftevaag return rval;
137*758e9fbaSOystein Eftevaag }
138*758e9fbaSOystein Eftevaag
139*758e9fbaSOystein Eftevaag static void
tcti_proxy_finalize(TSS2_TCTI_CONTEXT * tctiContext)140*758e9fbaSOystein Eftevaag tcti_proxy_finalize(
141*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tctiContext)
142*758e9fbaSOystein Eftevaag {
143*758e9fbaSOystein Eftevaag memset(tctiContext, 0, sizeof(TSS2_TCTI_CONTEXT_PROXY));
144*758e9fbaSOystein Eftevaag }
145*758e9fbaSOystein Eftevaag
146*758e9fbaSOystein Eftevaag static TSS2_RC
tcti_proxy_initialize(TSS2_TCTI_CONTEXT * tctiContext,size_t * contextSize,TSS2_TCTI_CONTEXT * tctiInner)147*758e9fbaSOystein Eftevaag tcti_proxy_initialize(
148*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tctiContext,
149*758e9fbaSOystein Eftevaag size_t *contextSize,
150*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tctiInner)
151*758e9fbaSOystein Eftevaag {
152*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT_PROXY *tcti_proxy =
153*758e9fbaSOystein Eftevaag (TSS2_TCTI_CONTEXT_PROXY*) tctiContext;
154*758e9fbaSOystein Eftevaag
155*758e9fbaSOystein Eftevaag if (tctiContext == NULL && contextSize == NULL) {
156*758e9fbaSOystein Eftevaag return TSS2_TCTI_RC_BAD_VALUE;
157*758e9fbaSOystein Eftevaag } else if (tctiContext == NULL) {
158*758e9fbaSOystein Eftevaag *contextSize = sizeof(*tcti_proxy);
159*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
160*758e9fbaSOystein Eftevaag }
161*758e9fbaSOystein Eftevaag
162*758e9fbaSOystein Eftevaag /* Init TCTI context */
163*758e9fbaSOystein Eftevaag memset(tcti_proxy, 0, sizeof(*tcti_proxy));
164*758e9fbaSOystein Eftevaag TSS2_TCTI_MAGIC (tctiContext) = TCTI_PROXY_MAGIC;
165*758e9fbaSOystein Eftevaag TSS2_TCTI_VERSION (tctiContext) = TCTI_PROXY_VERSION;
166*758e9fbaSOystein Eftevaag TSS2_TCTI_TRANSMIT (tctiContext) = tcti_proxy_transmit;
167*758e9fbaSOystein Eftevaag TSS2_TCTI_RECEIVE (tctiContext) = tcti_proxy_receive;
168*758e9fbaSOystein Eftevaag TSS2_TCTI_FINALIZE (tctiContext) = tcti_proxy_finalize;
169*758e9fbaSOystein Eftevaag TSS2_TCTI_CANCEL (tctiContext) = NULL;
170*758e9fbaSOystein Eftevaag TSS2_TCTI_GET_POLL_HANDLES (tctiContext) = NULL;
171*758e9fbaSOystein Eftevaag TSS2_TCTI_SET_LOCALITY (tctiContext) = NULL;
172*758e9fbaSOystein Eftevaag tcti_proxy->tctiInner = tctiInner;
173*758e9fbaSOystein Eftevaag tcti_proxy->state = forwarding;
174*758e9fbaSOystein Eftevaag
175*758e9fbaSOystein Eftevaag return TSS2_RC_SUCCESS;
176*758e9fbaSOystein Eftevaag }
177*758e9fbaSOystein Eftevaag
178*758e9fbaSOystein Eftevaag /**
179*758e9fbaSOystein Eftevaag * This program is a template for integration tests (ones that use the TCTI
180*758e9fbaSOystein Eftevaag * and the ESAPI contexts / API directly). It does nothing more than parsing
181*758e9fbaSOystein Eftevaag * command line options that allow the caller (likely a script) to specify
182*758e9fbaSOystein Eftevaag * which TCTI to use for the test.
183*758e9fbaSOystein Eftevaag */
184*758e9fbaSOystein Eftevaag int
main(int argc,char * argv[])185*758e9fbaSOystein Eftevaag main(int argc, char *argv[])
186*758e9fbaSOystein Eftevaag {
187*758e9fbaSOystein Eftevaag TSS2_RC rc;
188*758e9fbaSOystein Eftevaag size_t tcti_size;
189*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tcti_context;
190*758e9fbaSOystein Eftevaag TSS2_TCTI_CONTEXT *tcti_inner;
191*758e9fbaSOystein Eftevaag ESYS_CONTEXT *esys_context;
192*758e9fbaSOystein Eftevaag TSS2_ABI_VERSION abiVersion =
193*758e9fbaSOystein Eftevaag { TSSWG_INTEROP, TSS_SAPI_FIRST_FAMILY, TSS_SAPI_FIRST_LEVEL,
194*758e9fbaSOystein Eftevaag TSS_SAPI_FIRST_VERSION };
195*758e9fbaSOystein Eftevaag
196*758e9fbaSOystein Eftevaag int ret;
197*758e9fbaSOystein Eftevaag test_opts_t opts = {
198*758e9fbaSOystein Eftevaag .tcti_type = TCTI_DEFAULT,
199*758e9fbaSOystein Eftevaag .device_file = DEVICE_PATH_DEFAULT,
200*758e9fbaSOystein Eftevaag .socket_address = HOSTNAME_DEFAULT,
201*758e9fbaSOystein Eftevaag .socket_port = PORT_DEFAULT,
202*758e9fbaSOystein Eftevaag };
203*758e9fbaSOystein Eftevaag
204*758e9fbaSOystein Eftevaag get_test_opts_from_env(&opts);
205*758e9fbaSOystein Eftevaag if (sanity_check_test_opts(&opts) != 0) {
206*758e9fbaSOystein Eftevaag LOG_ERROR("TPM Startup FAILED! Error in sanity check");
207*758e9fbaSOystein Eftevaag exit(1);
208*758e9fbaSOystein Eftevaag }
209*758e9fbaSOystein Eftevaag tcti_inner = tcti_init_from_opts(&opts);
210*758e9fbaSOystein Eftevaag if (tcti_inner == NULL) {
211*758e9fbaSOystein Eftevaag LOG_ERROR("TPM Startup FAILED! Error tcti init");
212*758e9fbaSOystein Eftevaag exit(1);
213*758e9fbaSOystein Eftevaag }
214*758e9fbaSOystein Eftevaag rc = tcti_proxy_initialize(NULL, &tcti_size, tcti_inner);
215*758e9fbaSOystein Eftevaag if (rc != TSS2_RC_SUCCESS) {
216*758e9fbaSOystein Eftevaag LOG_ERROR("tcti initialization FAILED! Response Code : 0x%x", rc);
217*758e9fbaSOystein Eftevaag return 1;
218*758e9fbaSOystein Eftevaag }
219*758e9fbaSOystein Eftevaag tcti_context = calloc(1, tcti_size);
220*758e9fbaSOystein Eftevaag if (tcti_inner == NULL) {
221*758e9fbaSOystein Eftevaag LOG_ERROR("TPM Startup FAILED! Error tcti init");
222*758e9fbaSOystein Eftevaag exit(1);
223*758e9fbaSOystein Eftevaag }
224*758e9fbaSOystein Eftevaag rc = tcti_proxy_initialize(tcti_context, &tcti_size, tcti_inner);
225*758e9fbaSOystein Eftevaag if (rc != TSS2_RC_SUCCESS) {
226*758e9fbaSOystein Eftevaag LOG_ERROR("tcti initialization FAILED! Response Code : 0x%x", rc);
227*758e9fbaSOystein Eftevaag return 1;
228*758e9fbaSOystein Eftevaag }
229*758e9fbaSOystein Eftevaag rc = Esys_Initialize(&esys_context, tcti_context, &abiVersion);
230*758e9fbaSOystein Eftevaag if (rc != TSS2_RC_SUCCESS) {
231*758e9fbaSOystein Eftevaag LOG_ERROR("Esys_Initialize FAILED! Response Code : 0x%x", rc);
232*758e9fbaSOystein Eftevaag return 1;
233*758e9fbaSOystein Eftevaag }
234*758e9fbaSOystein Eftevaag rc = Esys_Startup(esys_context, TPM2_SU_CLEAR);
235*758e9fbaSOystein Eftevaag if (rc != TSS2_RC_SUCCESS && rc != TPM2_RC_INITIALIZE) {
236*758e9fbaSOystein Eftevaag LOG_ERROR("Esys_Startup FAILED! Response Code : 0x%x", rc);
237*758e9fbaSOystein Eftevaag return 1;
238*758e9fbaSOystein Eftevaag }
239*758e9fbaSOystein Eftevaag
240*758e9fbaSOystein Eftevaag rc = Esys_SetTimeout(esys_context, TSS2_TCTI_TIMEOUT_BLOCK);
241*758e9fbaSOystein Eftevaag if (rc != TSS2_RC_SUCCESS) {
242*758e9fbaSOystein Eftevaag LOG_ERROR("Esys_SetTimeout FAILED! Response Code : 0x%x", rc);
243*758e9fbaSOystein Eftevaag return 1;
244*758e9fbaSOystein Eftevaag }
245*758e9fbaSOystein Eftevaag
246*758e9fbaSOystein Eftevaag ret = test_invoke_esapi(esys_context);
247*758e9fbaSOystein Eftevaag
248*758e9fbaSOystein Eftevaag Esys_Finalize(&esys_context);
249*758e9fbaSOystein Eftevaag tcti_teardown(tcti_inner);
250*758e9fbaSOystein Eftevaag tcti_teardown(tcti_context);
251*758e9fbaSOystein Eftevaag return ret;
252*758e9fbaSOystein Eftevaag }
253