1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3 * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
4 * Copyright 2019, Intel Corporation
5 * All rights reserved.
6 *******************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdlib.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <inttypes.h>
16 #include <dlfcn.h>
17 #include <limits.h>
18 #include <stdio.h>
19
20 #include "tss2_tcti.h"
21 #include "tctildr-interface.h"
22 #include "tctildr.h"
23 #define LOGMODULE tcti
24 #include "util/log.h"
25
26 #define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0]))
27
28 struct {
29 char *file;
30 char *conf;
31 char *description;
32 } tctis[] = {
33 {
34 .file = "libtss2-tcti-default.so",
35 .description = "Access libtss2-tcti-default.so",
36 },
37 {
38 .file = "libtss2-tcti-tabrmd.so.0",
39 .description = "Access libtss2-tcti-tabrmd.so",
40 },
41 {
42 .file = "libtss2-tcti-device.so.0",
43 .conf = "/dev/tpmrm0",
44 .description = "Access libtss2-tcti-device.so.0 with /dev/tpmrm0",
45 },
46 {
47 .file = "libtss2-tcti-device.so.0",
48 .conf = "/dev/tpm0",
49 .description = "Access libtss2-tcti-device.so.0 with /dev/tpm0",
50 },
51 {
52 .file = "libtss2-tcti-mssim.so.0",
53 .description = "Access to libtss2-tcti-mssim.so",
54 },
55 };
56
57 const TSS2_TCTI_INFO*
info_from_handle(void * dlhandle)58 info_from_handle (void *dlhandle)
59 {
60 TSS2_TCTI_INFO_FUNC info_func;
61
62 if (dlhandle == NULL)
63 return NULL;
64
65 info_func = dlsym (dlhandle, TSS2_TCTI_INFO_SYMBOL);
66 if (info_func == NULL) {
67 LOG_ERROR ("Failed to get reference to TSS2_TCTI_INFO_SYMBOL: %s",
68 dlerror());
69 return NULL;
70 }
71
72 return info_func ();
73 }
74 TSS2_RC
handle_from_name(const char * file,void ** handle)75 handle_from_name(const char *file,
76 void **handle)
77 {
78 char file_xfrm [PATH_MAX] = { 0, };
79 size_t size;
80
81 if (handle == NULL) {
82 return TSS2_TCTI_RC_BAD_REFERENCE;
83 }
84 *handle = dlopen(file, RTLD_NOW);
85 if (*handle != NULL) {
86 return TSS2_RC_SUCCESS;
87 } else {
88 LOG_DEBUG("Could not load TCTI file: \"%s\": %s", file, dlerror());
89 }
90 /* 'name' alone didn't work, try libtss2-tcti-<name>.so.0 */
91 size = snprintf(file_xfrm,
92 sizeof (file_xfrm),
93 TCTI_NAME_TEMPLATE_0,
94 file);
95 if (size >= sizeof (file_xfrm)) {
96 LOG_ERROR("TCTI name truncated in transform.");
97 return TSS2_TCTI_RC_BAD_VALUE;
98 }
99 *handle = dlopen(file_xfrm, RTLD_NOW);
100 if (*handle != NULL) {
101 return TSS2_RC_SUCCESS;
102 } else {
103 LOG_DEBUG("Could not load TCTI file \"%s\": %s", file, dlerror());
104 }
105 /* libtss2-tcti-<name>.so.0 didn't work, try libtss2-tcti-<name>.so */
106 size = snprintf(file_xfrm,
107 sizeof (file_xfrm),
108 TCTI_NAME_TEMPLATE,
109 file);
110 if (size >= sizeof (file_xfrm)) {
111 LOG_ERROR("TCTI name truncated in transform.");
112 return TSS2_TCTI_RC_BAD_VALUE;
113 }
114 *handle = dlopen(file_xfrm, RTLD_NOW);
115 if (*handle == NULL) {
116 LOG_DEBUG("Failed to load TCTI for name \"%s\": %s", file, dlerror());
117 return TSS2_TCTI_RC_NOT_SUPPORTED;
118 }
119
120 return TSS2_RC_SUCCESS;
121 }
122 TSS2_RC
tcti_from_file(const char * file,const char * conf,TSS2_TCTI_CONTEXT ** tcti,void ** dlhandle)123 tcti_from_file(const char *file,
124 const char* conf,
125 TSS2_TCTI_CONTEXT **tcti,
126 void **dlhandle)
127 {
128 TSS2_RC r;
129 void *handle;
130 TSS2_TCTI_INFO_FUNC infof;
131
132 LOG_TRACE("Attempting to load TCTI file: %s", file);
133 if (tcti == NULL) {
134 return TSS2_TCTI_RC_BAD_REFERENCE;
135 }
136 r = handle_from_name(file, &handle);
137 if (r != TSS2_RC_SUCCESS) {
138 return r;
139 }
140
141 infof = (TSS2_TCTI_INFO_FUNC) dlsym(handle, TSS2_TCTI_INFO_SYMBOL);
142 if (infof == NULL) {
143 LOG_ERROR("Info not found in TCTI file: %s", file);
144 dlclose(handle);
145 return TSS2_ESYS_RC_BAD_REFERENCE;
146 }
147
148 r = tcti_from_info(infof, conf, tcti);
149 if (r != TSS2_RC_SUCCESS) {
150 LOG_ERROR("Could not initialize TCTI file: %s", file);
151 dlclose(handle);
152 return r;
153 }
154
155 if (dlhandle)
156 *dlhandle = handle;
157
158 LOG_DEBUG("Initialized TCTI file: %s", file);
159
160 return TSS2_RC_SUCCESS;
161 }
162 TSS2_RC
get_info_default(const TSS2_TCTI_INFO ** info,void ** dlhandle)163 get_info_default(const TSS2_TCTI_INFO **info,
164 void **dlhandle)
165 {
166 void *handle = NULL;
167 const TSS2_TCTI_INFO *info_src;
168 char *name = NULL;
169 TSS2_RC rc = TSS2_TCTI_RC_GENERAL_FAILURE;
170
171 LOG_DEBUG("%s", __func__);
172 if (info == NULL || dlhandle == NULL) {
173 LOG_ERROR("parameters cannot be NULL");
174 return TSS2_TCTI_RC_BAD_REFERENCE;
175 }
176 #ifdef ESYS_TCTI_DEFAULT_MODULE
177 name = ESYS_TCTI_DEFAULT_MODULE;
178 LOG_DEBUG("name: %s", name);
179 rc = handle_from_name (name, &handle);
180 if (rc != TSS2_RC_SUCCESS)
181 return rc;
182 else if (handle == NULL)
183 return TSS2_TCTI_RC_IO_ERROR;
184 #else
185 size_t i;
186 for (i = 0; i < ARRAY_SIZE(tctis); i++) {
187 name = tctis[i].file;
188 LOG_DEBUG("name: %s", name);
189 if (name == NULL) {
190 continue;
191 }
192 rc = handle_from_name (name, &handle);
193 if (rc != TSS2_RC_SUCCESS || handle == NULL) {
194 LOG_DEBUG("Failed to get handle for TCTI with name: %s", name);
195 continue;
196 }
197
198 break;
199 }
200 #endif /* ESYS_TCTI_DEFAULT_MODULE */
201
202 info_src = info_from_handle (handle);
203 if (info_src != NULL) {
204 *info = info_src;
205 } else {
206 tctildr_finalize_data (&handle);
207 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
208 }
209 *dlhandle = handle;
210
211 return rc;
212 }
213
214 TSS2_RC
tctildr_get_default(TSS2_TCTI_CONTEXT ** tcticontext,void ** dlhandle)215 tctildr_get_default(TSS2_TCTI_CONTEXT ** tcticontext, void **dlhandle)
216 {
217 if (tcticontext == NULL) {
218 LOG_ERROR("tcticontext must not be NULL");
219 return TSS2_TCTI_RC_BAD_REFERENCE;
220 }
221 *tcticontext = NULL;
222 #ifdef ESYS_TCTI_DEFAULT_MODULE
223
224 #ifdef ESYS_TCTI_DEFAULT_CONFIG
225 const char *config = ESYS_TCTI_DEFAULT_CONFIG;
226 #else /* ESYS_TCTI_DEFAULT_CONFIG */
227 const char *config = NULL;
228 #endif /* ESYS_TCTI_DEFAULT_CONFIG */
229
230 LOG_DEBUG("Attempting to initialize TCTI defined during compilation: %s:%s",
231 ESYS_TCTI_DEFAULT_MODULE, config);
232 return tcti_from_file(ESYS_TCTI_DEFAULT_MODULE, config, tcticontext,
233 dlhandle);
234
235 #else /* ESYS_TCTI_DEFAULT_MODULE */
236
237 TSS2_RC r;
238 size_t i;
239
240 for (i = 0; i < ARRAY_SIZE(tctis); i++) {
241 LOG_DEBUG("Attempting to connect using standard TCTI: %s",
242 tctis[i].description);
243 r = tcti_from_file(tctis[i].file, tctis[i].conf, tcticontext,
244 dlhandle);
245 if (r == TSS2_RC_SUCCESS)
246 return TSS2_RC_SUCCESS;
247 LOG_DEBUG("Failed to load standard TCTI number %zu", i);
248 }
249
250 LOG_ERROR("No standard TCTI could be loaded");
251 return TSS2_TCTI_RC_IO_ERROR;
252
253 #endif /* ESYS_TCTI_DEFAULT_MODULE */
254 }
255 TSS2_RC
info_from_name(const char * name,const TSS2_TCTI_INFO ** info,void ** data)256 info_from_name (const char *name,
257 const TSS2_TCTI_INFO **info,
258 void **data)
259 {
260 TSS2_RC rc;
261
262 if (data == NULL || info == NULL)
263 return TSS2_TCTI_RC_BAD_REFERENCE;
264 rc = handle_from_name (name, data);
265 if (rc != TSS2_RC_SUCCESS)
266 return rc;
267 *info = (TSS2_TCTI_INFO*)info_from_handle (*data);
268 if (*info == NULL) {
269 tctildr_finalize_data (data);
270 return TSS2_TCTI_RC_IO_ERROR;
271 }
272 return rc;
273 }
274 TSS2_RC
tctildr_get_info(const char * name,const TSS2_TCTI_INFO ** info,void ** data)275 tctildr_get_info(const char *name,
276 const TSS2_TCTI_INFO **info,
277 void **data)
278 {
279 if (info == NULL) {
280 LOG_ERROR("info must not be NULL");
281 return TSS2_TCTI_RC_BAD_REFERENCE;
282 }
283 if (name != NULL) {
284 return info_from_name (name, info, data);
285 } else {
286 return get_info_default (info, data);
287 }
288 }
289 TSS2_RC
tctildr_get_tcti(const char * name,const char * conf,TSS2_TCTI_CONTEXT ** tcti,void ** data)290 tctildr_get_tcti(const char *name,
291 const char* conf,
292 TSS2_TCTI_CONTEXT **tcti,
293 void **data)
294 {
295 LOG_DEBUG("name: \"%s\", conf: \"%s\"", name, conf);
296 if (tcti == NULL) {
297 LOG_ERROR("tcticontext must not be NULL");
298 return TSS2_TCTI_RC_BAD_REFERENCE;
299 }
300 *tcti = NULL;
301 if (name == NULL) {
302 return tctildr_get_default (tcti, data);
303 }
304
305 return tcti_from_file (name, conf, tcti, data);
306 }
307
308 void
tctildr_finalize_data(void ** data)309 tctildr_finalize_data (void **data)
310 {
311 if (data != NULL && *data != NULL) {
312 dlclose(*data);
313 *data = NULL;
314 }
315 }
316