1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /***********************************************************************
3  * Copyright (c) 2017-2018, Intel Corporation
4  *
5  * All rights reserved.
6  ***********************************************************************/
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <errno.h>
12 #include <inttypes.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include "tss2_tcti_device.h"
18 #include "tss2_tcti_mssim.h"
19 #include "tss2_tcti_swtpm.h"
20 #ifdef TCTI_FUZZING
21 #include "tss2_tcti_fuzzing.h"
22 #endif /* TCTI_FUZZING */
23 
24 #include "context-util.h"
25 #include "tss2-tcti/tcti-mssim.h"
26 #include "tss2-tcti/tcti-swtpm.h"
27 
28 #ifdef TCTI_DEVICE
29 /*
30  * Initialize a TSS2_TCTI_CONTEXT for the device TCTI.
31  */
32 TSS2_TCTI_CONTEXT *
tcti_device_init(char const * device_path)33 tcti_device_init(char const *device_path)
34 {
35     size_t size;
36     TSS2_RC rc;
37     TSS2_TCTI_CONTEXT *tcti_ctx;
38 
39     rc = Tss2_Tcti_Device_Init(NULL, &size, 0);
40     if (rc != TSS2_RC_SUCCESS) {
41         fprintf(stderr,
42                 "Failed to get allocation size for device tcti context: "
43                 "0x%x\n", rc);
44         return NULL;
45     }
46     tcti_ctx = (TSS2_TCTI_CONTEXT *) calloc(1, size);
47     if (tcti_ctx == NULL) {
48         fprintf(stderr,
49                 "Allocation for device TCTI context failed: %s\n",
50                 strerror(errno));
51         return NULL;
52     }
53     rc = Tss2_Tcti_Device_Init(tcti_ctx, &size, device_path);
54     if (rc != TSS2_RC_SUCCESS) {
55         fprintf(stderr, "Failed to initialize device TCTI context: 0x%x\n", rc);
56         free(tcti_ctx);
57         return NULL;
58     }
59     return tcti_ctx;
60 }
61 #endif /* TCTI_DEVICE */
62 
63 #ifdef TCTI_MSSIM
64 /*
65  * Initialize a socket TCTI instance using the provided options structure.
66  * The hostname and port are the only configuration options used.
67  * The caller is returned a TCTI context structure that is allocated by this
68  * function. This structure must be freed by the caller.
69  */
70 TSS2_TCTI_CONTEXT *
tcti_socket_init(char const * host,uint16_t port)71 tcti_socket_init(char const *host, uint16_t port)
72 {
73     size_t size;
74     TSS2_RC rc;
75     TSS2_TCTI_CONTEXT *tcti_ctx;
76     char conf_str[TCTI_MSSIM_CONF_MAX] = { 0 };
77 
78     snprintf(conf_str, TCTI_MSSIM_CONF_MAX, "host=%s,port=%" PRIu16, host, port);
79     rc = Tss2_Tcti_Mssim_Init(NULL, &size, conf_str);
80     if (rc != TSS2_RC_SUCCESS) {
81         fprintf(stderr, "Faled to get allocation size for tcti context: "
82                 "0x%x\n", rc);
83         return NULL;
84     }
85     tcti_ctx = (TSS2_TCTI_CONTEXT *) calloc(1, size);
86     if (tcti_ctx == NULL) {
87         fprintf(stderr, "Allocation for tcti context failed: %s\n",
88                 strerror(errno));
89         return NULL;
90     }
91     rc = Tss2_Tcti_Mssim_Init(tcti_ctx, &size, conf_str);
92     if (rc != TSS2_RC_SUCCESS) {
93         fprintf(stderr, "Failed to initialize tcti context: 0x%x\n", rc);
94         free(tcti_ctx);
95         return NULL;
96     }
97     return tcti_ctx;
98 }
99 #endif /* TCTI_MSSIM */
100 
101 #ifdef TCTI_SWTPM
102 /*
103  * Initialize a socket TCTI instance using the provided options structure.
104  * The hostname and port are the only configuration options used.
105  * The caller is returned a TCTI context structure that is allocated by this
106  * function. This structure must be freed by the caller.
107  */
108 TSS2_TCTI_CONTEXT *
tcti_swtpm_init(char const * host,uint16_t port)109 tcti_swtpm_init(char const *host, uint16_t port)
110 {
111     size_t size;
112     TSS2_RC rc;
113     TSS2_TCTI_CONTEXT *tcti_ctx;
114     char conf_str[TCTI_SWTPM_CONF_MAX] = { 0 };
115 
116     snprintf(conf_str, TCTI_SWTPM_CONF_MAX, "host=%s,port=%" PRIu16, host, port);
117     rc = Tss2_Tcti_Swtpm_Init(NULL, &size, conf_str);
118     if (rc != TSS2_RC_SUCCESS) {
119         fprintf(stderr, "Faled to get allocation size for tcti context: "
120                 "0x%x\n", rc);
121         return NULL;
122     }
123     tcti_ctx = (TSS2_TCTI_CONTEXT *) calloc(1, size);
124     if (tcti_ctx == NULL) {
125         fprintf(stderr, "Allocation for tcti context failed: %s\n",
126                 strerror(errno));
127         return NULL;
128     }
129     rc = Tss2_Tcti_Swtpm_Init(tcti_ctx, &size, conf_str);
130     if (rc != TSS2_RC_SUCCESS) {
131         fprintf(stderr, "Failed to initialize tcti context: 0x%x\n", rc);
132         free(tcti_ctx);
133         return NULL;
134     }
135     return tcti_ctx;
136 }
137 #endif /* TCTI_SWTPM */
138 
139 #ifdef TCTI_FUZZING
140 /*
141  * Initialize a fuzzing TCTI instance using the provided options structure.
142  * The fuzzing_lengths.log file is the only configuration option used.
143  * The caller is returned a TCTI context structure that is allocated by this
144  * function. This structure must be freed by the caller.
145  */
146 TSS2_TCTI_CONTEXT *
tcti_fuzzing_init()147 tcti_fuzzing_init()
148 {
149     size_t size;
150     TSS2_RC rc;
151     TSS2_TCTI_CONTEXT *tcti_ctx;
152 
153     rc = Tss2_Tcti_Fuzzing_Init(NULL, &size, NULL);
154     if (rc != TSS2_RC_SUCCESS) {
155         fprintf(stderr, "Faled to get allocation size for tcti context: "
156                 "0x%x\n", rc);
157         return NULL;
158     }
159     tcti_ctx = (TSS2_TCTI_CONTEXT *) calloc(1, size);
160     if (tcti_ctx == NULL) {
161         fprintf(stderr, "Allocation for tcti context failed: %s\n",
162                 strerror(errno));
163         return NULL;
164     }
165     rc = Tss2_Tcti_Fuzzing_Init(tcti_ctx, &size, NULL);
166     if (rc != TSS2_RC_SUCCESS) {
167         fprintf(stderr, "Failed to initialize tcti context: 0x%x\n", rc);
168         free(tcti_ctx);
169         return NULL;
170     }
171     return tcti_ctx;
172 }
173 #endif /* TCTI_FUZZING */
174 
175 /*
176  * Initialize a SYS context using the TCTI context provided by the caller.
177  * This function allocates memory for the SYS context and returns it to the
178  * caller. This memory must be freed by the caller.
179  */
180 TSS2_SYS_CONTEXT *
sys_init_from_tcti_ctx(TSS2_TCTI_CONTEXT * tcti_ctx)181 sys_init_from_tcti_ctx(TSS2_TCTI_CONTEXT * tcti_ctx)
182 {
183     TSS2_SYS_CONTEXT *sys_ctx;
184     TSS2_RC rc;
185     size_t size;
186     TSS2_ABI_VERSION abi_version = {
187         .tssCreator = 1,
188         .tssFamily = 2,
189         .tssLevel = 1,
190         .tssVersion = 108,
191     };
192 
193     size = Tss2_Sys_GetContextSize(0);
194     sys_ctx = (TSS2_SYS_CONTEXT *) calloc(1, size);
195     if (sys_ctx == NULL) {
196         fprintf(stderr,
197                 "Failed to allocate 0x%zx bytes for the SYS context\n", size);
198         return NULL;
199     }
200     rc = Tss2_Sys_Initialize(sys_ctx, size, tcti_ctx, &abi_version);
201     if (rc != TSS2_RC_SUCCESS) {
202         fprintf(stderr, "Failed to initialize SYS context: 0x%x\n", rc);
203         free(sys_ctx);
204         return NULL;
205     }
206     return sys_ctx;
207 }
208 
209 /*
210  * Initialize a SYS context to use a socket TCTI. Get configuration data from
211  * the provided structure.
212  */
213 TSS2_SYS_CONTEXT *
sys_init_from_opts(test_opts_t * options)214 sys_init_from_opts(test_opts_t * options)
215 {
216     TSS2_TCTI_CONTEXT *tcti_ctx;
217     TSS2_SYS_CONTEXT *sys_ctx;
218 
219     tcti_ctx = tcti_init_from_opts(options);
220     if (tcti_ctx == NULL)
221         return NULL;
222     sys_ctx = sys_init_from_tcti_ctx(tcti_ctx);
223     if (sys_ctx == NULL)
224         return NULL;
225     return sys_ctx;
226 }
227 
228 /*
229  * Initialize a TSS2_TCTI_CONTEXT using whatever TCTI data is in the options
230  * structure. This is a mechanism that allows the calling application to be
231  * mostly ignorant of which TCTI they're creating / initializing.
232  */
233 TSS2_TCTI_CONTEXT *
tcti_init_from_opts(test_opts_t * options)234 tcti_init_from_opts(test_opts_t * options)
235 {
236     switch (options->tcti_type) {
237 #ifdef TCTI_DEVICE
238     case DEVICE_TCTI:
239         return tcti_device_init(options->device_file);
240 #endif /* TCTI_DEVICE */
241 #ifdef TCTI_MSSIM
242     case SOCKET_TCTI:
243         return tcti_socket_init(options->socket_address, options->socket_port);
244 #endif /* TCTI_MSSIM */
245 #ifdef TCTI_SWTPM
246     case SWTPM_TCTI:
247        return tcti_swtpm_init(options->socket_address, options->socket_port);
248 #endif /* TCTI_SWTPM */
249 #ifdef TCTI_FUZZING
250     case FUZZING_TCTI:
251         return tcti_fuzzing_init();
252 #endif /* TCTI_FUZZING */
253     default:
254         return NULL;
255     }
256 }
257 
258 /*
259  * Teardown / Finalize TCTI context and free memory.
260  */
261 void
tcti_teardown(TSS2_TCTI_CONTEXT * tcti_context)262 tcti_teardown(TSS2_TCTI_CONTEXT * tcti_context)
263 {
264     if (tcti_context) {
265         Tss2_Tcti_Finalize(tcti_context);
266         free(tcti_context);
267     }
268 }
269 
270 /*
271  * Teardown and free the resources associated with a SYS context structure.
272  */
273 void
sys_teardown(TSS2_SYS_CONTEXT * sys_context)274 sys_teardown(TSS2_SYS_CONTEXT * sys_context)
275 {
276     Tss2_Sys_Finalize(sys_context);
277     free(sys_context);
278 }
279 
280 /*
281  * Teardown and free the resources associated with a SYS context structure.
282  * This includes tearing down the TCTI as well.
283  */
284 void
sys_teardown_full(TSS2_SYS_CONTEXT * sys_context)285 sys_teardown_full(TSS2_SYS_CONTEXT * sys_context)
286 {
287     TSS2_TCTI_CONTEXT *tcti_context = NULL;
288     TSS2_RC rc;
289 
290     rc = Tss2_Sys_GetTctiContext(sys_context, &tcti_context);
291     if (rc != TSS2_RC_SUCCESS)
292         return;
293 
294     sys_teardown(sys_context);
295     tcti_teardown(tcti_context);
296 }
297