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 <errno.h>
13 #include <inttypes.h>
14 #if defined(__linux__)
15 #include <linux/limits.h>
16 #elif defined(_MSC_VER)
17 #include <windows.h>
18 #include <limits.h>
19 #ifndef PATH_MAX
20 #define PATH_MAX MAX_PATH
21
strndup(const char * s,size_t n)22 static char *strndup(const char* s, size_t n)
23 {
24 char *dst = NULL;
25
26 if (n + 1 >= USHRT_MAX)
27 return NULL;
28
29 dst = calloc(1, n + 1);
30
31 if (dst == NULL)
32 return NULL;
33
34 memcpy(dst, s, n);
35 return dst;
36 }
37 #endif
38 #else
39 #include <limits.h>
40 #endif
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "tss2_tpm2_types.h"
45 #include "tss2_tcti.h"
46
47 #include "tcti-common.h"
48 #include "tctildr.h"
49 #include "tctildr-interface.h"
50 #define LOGMODULE tcti
51 #include "util/log.h"
52
53 TSS2_RC
tcti_from_init(TSS2_TCTI_INIT_FUNC init,const char * conf,TSS2_TCTI_CONTEXT ** tcti)54 tcti_from_init(TSS2_TCTI_INIT_FUNC init,
55 const char* conf,
56 TSS2_TCTI_CONTEXT **tcti)
57 {
58 TSS2_RC r;
59 size_t size;
60
61 LOG_TRACE("Initializing TCTI for config: %s", conf);
62
63 if (init == NULL || tcti == NULL)
64 return TSS2_TCTI_RC_BAD_REFERENCE;
65 r = init(NULL, &size, conf);
66 if (r != TSS2_RC_SUCCESS) {
67 LOG_WARNING("TCTI init for function %p failed with %" PRIx32, init, r);
68 return r;
69 }
70
71 *tcti = (TSS2_TCTI_CONTEXT *) calloc(1, size);
72 if (*tcti == NULL) {
73 LOG_ERROR("Memory allocation for tcti failed: %s", strerror(errno));
74 return TSS2_ESYS_RC_MEMORY;
75 }
76
77 /* Unless tcti loglevel is log_debug or higher
78 * (i.e. TSS2_LOG=tcti+debug) turn the logging
79 * from loaded tctis off completely, including warnings
80 * and error logs. It makes too much noise when tcti
81 * loader tries them all one by one and what we want
82 * use is the last one.
83 */
84 log_level old_loglevel = LOGMODULE_status;
85 if (LOGMODULE_status < LOGLEVEL_INFO)
86 LOGMODULE_status = LOGLEVEL_NONE;
87
88 r = init(*tcti, &size, conf);
89 LOGMODULE_status = old_loglevel;
90
91 if (r != TSS2_RC_SUCCESS) {
92 LOG_DEBUG("TCTI init for function %p failed with %" PRIx32, init, r);
93 free(*tcti);
94 *tcti=NULL;
95 return r;
96 }
97
98 LOG_DEBUG("Initialized TCTI for config: %s", conf);
99
100 return TSS2_RC_SUCCESS;
101 }
102
103 TSS2_RC
tcti_from_info(TSS2_TCTI_INFO_FUNC infof,const char * conf,TSS2_TCTI_CONTEXT ** tcti)104 tcti_from_info(TSS2_TCTI_INFO_FUNC infof,
105 const char* conf,
106 TSS2_TCTI_CONTEXT **tcti)
107 {
108 TSS2_RC r;
109 LOG_TRACE("Attempting to load TCTI info");
110
111 const TSS2_TCTI_INFO* info = infof();
112 if (info == NULL) {
113 LOG_ERROR("TCTI info function failed");
114 return TSS2_ESYS_RC_GENERAL_FAILURE;
115 }
116 LOG_TRACE("Loaded TCTI info named: %s", info->name);
117 LOG_TRACE("TCTI description: %s", info->description);
118 LOG_TRACE("TCTI config_help: %s", info->config_help);
119
120 r = tcti_from_init(info->init, conf, tcti);
121 if (r != TSS2_RC_SUCCESS) {
122 LOG_DEBUG("Could not initialize TCTI named: %s", info->name);
123 return r;
124 }
125 LOG_INFO("Initialized TCTI named: %s", info->name);
126
127 return TSS2_RC_SUCCESS;
128 }
129 /*
130 * name_conf in the form "tcti-name:tcti-conf"
131 * copies 'tcti-name' component to 'name' buffer
132 * copies 'tcti-conf' component to 'conf' buffer
133 * handled name_conf forms:
134 * - "", ":" -> both name and conf are left unchanged
135 * - "tcti-name", "tcti-name:" -> tcti-name copied to 'name', 'conf'
136 * unchanged
137 * - ":tcti-conf" -> tcti-conf copied to 'conf', 'name' unchanged
138 * - "tcti-name:tcti-conf" - "tcti-name" copied to 'name,', "tcti-conf"
139 * copied to 'conf'
140 */
141 TSS2_RC
tctildr_conf_parse(const char * name_conf,char * name,char * conf)142 tctildr_conf_parse (const char *name_conf,
143 char *name,
144 char *conf)
145 {
146 char *split;
147 size_t combined_length;
148
149 if (name_conf == NULL) {
150 LOG_ERROR ("'name_conf' param may NOT be NULL");
151 return TSS2_TCTI_RC_BAD_REFERENCE;
152 }
153 combined_length = strlen (name_conf);
154 if (combined_length > PATH_MAX - 1) {
155 LOG_ERROR ("combined conf length must be between 0 and PATH_MAX");
156 return TSS2_TCTI_RC_BAD_VALUE;
157 }
158
159 LOG_DEBUG ("name_conf: \"%s\"", name_conf);
160 if (combined_length == 0)
161 return TSS2_RC_SUCCESS;
162 split = strchr (name_conf, ':');
163 if (name != NULL && split == NULL) {
164 /* no ':' tcti name only */
165 strcpy (name, name_conf);
166 LOG_DEBUG ("TCTI name: \"%s\"", name);
167 return TSS2_RC_SUCCESS;
168 }
169 if (name != NULL && name_conf[0] != '\0' && name_conf[0] != ':') {
170 /* name is more than empty string */
171 size_t name_length = split - name_conf;
172 if (name_length > PATH_MAX) {
173 return TSS2_TCTI_RC_BAD_VALUE;
174 }
175 memcpy (name, name_conf, name_length);
176 name [name_length] = '\0';
177 LOG_DEBUG ("TCTI name: \"%s\"", name);
178 }
179 if (conf != NULL && split && split [1] != '\0') {
180 /* conf is more than empty string */
181 strcpy (conf, &split [1]);
182 LOG_DEBUG ("TCTI conf: \"%s\"", conf);
183 }
184
185 return TSS2_RC_SUCCESS;
186 }
187 TSS2_TCTILDR_CONTEXT*
tctildr_context_cast(TSS2_TCTI_CONTEXT * ctx)188 tctildr_context_cast (TSS2_TCTI_CONTEXT *ctx)
189 {
190 if (ctx != NULL && TSS2_TCTI_MAGIC (ctx) == TCTILDR_MAGIC) {
191 return (TSS2_TCTILDR_CONTEXT*)ctx;
192 }
193 return NULL;
194 }
195 TSS2_RC
tctildr_transmit(TSS2_TCTI_CONTEXT * tctiContext,size_t command_size,const uint8_t * command_buffer)196 tctildr_transmit (
197 TSS2_TCTI_CONTEXT *tctiContext,
198 size_t command_size,
199 const uint8_t *command_buffer)
200 {
201 TSS2_TCTILDR_CONTEXT *ldr_ctx = tctildr_context_cast (tctiContext);
202 if (ldr_ctx == NULL) {
203 return TSS2_TCTI_RC_BAD_REFERENCE;
204 }
205 return Tss2_Tcti_Transmit (ldr_ctx->tcti, command_size, command_buffer);
206 }
207 TSS2_RC
tctildr_receive(TSS2_TCTI_CONTEXT * tctiContext,size_t * response_size,uint8_t * response_buffer,int32_t timeout)208 tctildr_receive (
209 TSS2_TCTI_CONTEXT *tctiContext,
210 size_t *response_size,
211 uint8_t *response_buffer,
212 int32_t timeout)
213 {
214 TSS2_TCTILDR_CONTEXT *ldr_ctx = tctildr_context_cast (tctiContext);
215 if (ldr_ctx == NULL) {
216 return TSS2_TCTI_RC_BAD_REFERENCE;
217 }
218 return Tss2_Tcti_Receive (ldr_ctx->tcti,
219 response_size,
220 response_buffer,
221 timeout);
222 }
223 TSS2_RC
tctildr_cancel(TSS2_TCTI_CONTEXT * tctiContext)224 tctildr_cancel (
225 TSS2_TCTI_CONTEXT *tctiContext)
226 {
227 TSS2_TCTILDR_CONTEXT *ldr_ctx = tctildr_context_cast (tctiContext);
228 if (ldr_ctx == NULL) {
229 return TSS2_TCTI_RC_BAD_REFERENCE;
230 }
231 return Tss2_Tcti_Cancel (ldr_ctx->tcti);
232 }
233 TSS2_RC
tctildr_get_poll_handles(TSS2_TCTI_CONTEXT * tctiContext,TSS2_TCTI_POLL_HANDLE * handles,size_t * num_handles)234 tctildr_get_poll_handles (
235 TSS2_TCTI_CONTEXT *tctiContext,
236 TSS2_TCTI_POLL_HANDLE *handles,
237 size_t *num_handles)
238 {
239 TSS2_TCTILDR_CONTEXT *ldr_ctx = tctildr_context_cast (tctiContext);
240 if (ldr_ctx == NULL) {
241 return TSS2_TCTI_RC_BAD_REFERENCE;
242 }
243 return Tss2_Tcti_GetPollHandles (ldr_ctx->tcti, handles, num_handles);
244 }
245 TSS2_RC
tctildr_set_locality(TSS2_TCTI_CONTEXT * tctiContext,uint8_t locality)246 tctildr_set_locality (
247 TSS2_TCTI_CONTEXT *tctiContext,
248 uint8_t locality)
249 {
250 TSS2_TCTILDR_CONTEXT *ldr_ctx = tctildr_context_cast (tctiContext);
251 if (ldr_ctx == NULL) {
252 return TSS2_TCTI_RC_BAD_REFERENCE;
253 }
254 return Tss2_Tcti_SetLocality (ldr_ctx->tcti, locality);
255 }
256 TSS2_RC
tctildr_make_sticky(TSS2_TCTI_CONTEXT * tctiContext,TPM2_HANDLE * handle,uint8_t sticky)257 tctildr_make_sticky (
258 TSS2_TCTI_CONTEXT *tctiContext,
259 TPM2_HANDLE *handle,
260 uint8_t sticky)
261 {
262 TSS2_TCTILDR_CONTEXT *ldr_ctx = tctildr_context_cast (tctiContext);
263 if (ldr_ctx == NULL) {
264 return TSS2_TCTI_RC_BAD_REFERENCE;
265 }
266 return Tss2_Tcti_MakeSticky (ldr_ctx->tcti, handle, sticky);
267 }
268
269 void
tctildr_finalize(TSS2_TCTI_CONTEXT * tctiContext)270 tctildr_finalize (
271 TSS2_TCTI_CONTEXT *tctiContext)
272 {
273 TSS2_TCTILDR_CONTEXT *ldr_ctx = tctildr_context_cast (tctiContext);
274 if (ldr_ctx == NULL) {
275 return;
276 }
277 if (ldr_ctx->tcti != NULL) {
278 Tss2_Tcti_Finalize (ldr_ctx->tcti);
279 free (ldr_ctx->tcti);
280 ldr_ctx->tcti = NULL;
281 }
282 }
283
284 void
Tss2_TctiLdr_Finalize(TSS2_TCTI_CONTEXT ** tctiContext)285 Tss2_TctiLdr_Finalize (TSS2_TCTI_CONTEXT **tctiContext)
286 {
287 TSS2_TCTILDR_CONTEXT *ldr_ctx;
288 if (tctiContext == NULL) {
289 return;
290 }
291 ldr_ctx = tctildr_context_cast (*tctiContext);
292 if (ldr_ctx == NULL) {
293 return;
294 }
295 tctildr_finalize (*tctiContext);
296 tctildr_finalize_data (&ldr_ctx->library_handle);
297 free (ldr_ctx);
298 *tctiContext = NULL;
299 }
300
301 TSS2_RC
copy_info(const TSS2_TCTI_INFO * info_src,TSS2_TCTI_INFO * info_dst)302 copy_info (const TSS2_TCTI_INFO *info_src,
303 TSS2_TCTI_INFO *info_dst)
304 {
305 TSS2_RC rc = TSS2_RC_SUCCESS;
306 const char *tmp = NULL;
307
308 if (info_src == NULL || info_dst == NULL) {
309 LOG_ERROR("parameters cannot be NULL");
310 return TSS2_TCTI_RC_BAD_REFERENCE;
311 }
312 tmp = strndup (info_src->name, PATH_MAX);
313 if (tmp != NULL) {
314 info_dst->name = tmp;
315 } else {
316 LOG_ERROR("strndup failed on name: %s", strerror(errno));
317 return TSS2_TCTI_RC_GENERAL_FAILURE;
318 }
319 tmp = strndup (info_src->description, PATH_MAX);
320 if (tmp != NULL) {
321 info_dst->description = tmp;
322 } else {
323 LOG_ERROR("strndup failed on description: %s", strerror(errno));
324 free ((char*)info_dst->name);
325 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
326 goto out;
327 }
328 tmp = strndup (info_src->config_help, PATH_MAX);
329 if (tmp != NULL) {
330 info_dst->config_help = tmp;
331 } else {
332 LOG_ERROR("strndup failed on config_help: %s", strerror(errno));
333 free ((char*)info_dst->name);
334 free ((char*)info_dst->description);
335 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
336 goto out;
337 }
338 info_dst->version = info_src->version;
339 out:
340 return rc;
341 }
342
343 TSS2_RC
Tss2_TctiLdr_GetInfo(const char * name,TSS2_TCTI_INFO ** info)344 Tss2_TctiLdr_GetInfo (const char *name,
345 TSS2_TCTI_INFO **info)
346 {
347 TSS2_RC rc;
348 const TSS2_TCTI_INFO *info_lib = NULL;
349 TSS2_TCTI_INFO *info_tmp = NULL;
350 void *data = NULL;
351 char name_buf [PATH_MAX] = { 0, }, *name_ptr = NULL;
352
353 if (info == NULL) {
354 return TSS2_TCTI_RC_BAD_REFERENCE;
355 }
356 if (name != NULL) {
357 rc = tctildr_conf_parse (name, name_buf, NULL);
358 if (rc != TSS2_RC_SUCCESS)
359 return rc;
360 name_ptr = name_buf;
361 }
362 rc = tctildr_get_info (name_ptr, &info_lib, &data);
363 if (rc != TSS2_RC_SUCCESS)
364 return rc;
365 info_tmp = calloc (1, sizeof (*info_tmp));
366 if (info_tmp == NULL) {
367 LOG_ERROR("calloc failed: %s", strerror (errno));
368 rc = TSS2_TCTI_RC_GENERAL_FAILURE;
369 goto out;
370 }
371 rc = copy_info (info_lib, info_tmp);
372 if (rc != TSS2_RC_SUCCESS) {
373 free (info_tmp);
374 info_tmp = NULL;
375 goto out;
376 }
377 info_tmp->init = NULL;
378 out:
379 tctildr_finalize_data (&data);
380 *info = info_tmp;
381 return rc;
382 }
383
384 void
Tss2_TctiLdr_FreeInfo(TSS2_TCTI_INFO ** info)385 Tss2_TctiLdr_FreeInfo (TSS2_TCTI_INFO **info)
386 {
387 TSS2_TCTI_INFO *info_tmp;
388
389 if (info == NULL || *info == NULL) {
390 return;
391 }
392 info_tmp = *info;
393 if (info_tmp->name != NULL) {
394 free ((char*)info_tmp->name);
395 }
396 if (info_tmp->description != NULL) {
397 free ((char*)info_tmp->description);
398 }
399 if (info_tmp->config_help != NULL) {
400 free ((char*)info_tmp->config_help);
401 }
402 free (info_tmp);
403 *info = NULL;
404 }
405 TSS2_RC
Tss2_TctiLdr_Initialize_Ex(const char * name,const char * conf,TSS2_TCTI_CONTEXT ** tctiContext)406 Tss2_TctiLdr_Initialize_Ex (const char *name,
407 const char *conf,
408 TSS2_TCTI_CONTEXT **tctiContext)
409 {
410 TSS2_TCTILDR_CONTEXT *ldr_ctx = NULL;
411 TSS2_RC rc;
412 void *dl_handle = NULL;
413 const char *local_name = NULL, *local_conf = NULL;
414
415 if (tctiContext == NULL) {
416 return TSS2_TCTI_RC_BAD_VALUE;
417 }
418 *tctiContext = NULL;
419 /* Ignore 'name' and 'conf' if they're NULL or empty string */
420 if (name != NULL && strcmp (name, "")) {
421 local_name = name;
422 }
423 if (conf != NULL && strcmp (conf, "")) {
424 local_conf = conf;
425 }
426 rc = tctildr_get_tcti (local_name, local_conf, tctiContext, &dl_handle);
427 if (rc != TSS2_RC_SUCCESS) {
428 LOG_ERROR ("Failed to instantiate TCTI");
429 goto err;
430 }
431 ldr_ctx = calloc (1, sizeof (TSS2_TCTILDR_CONTEXT));
432 if (ldr_ctx == NULL) {
433 rc = TSS2_TCTI_RC_MEMORY;
434 goto err;
435 }
436 TSS2_TCTI_MAGIC (ldr_ctx) = TCTILDR_MAGIC;
437 TSS2_TCTI_VERSION (ldr_ctx) = TCTI_VERSION;
438 TSS2_TCTI_TRANSMIT (ldr_ctx) = tctildr_transmit;
439 TSS2_TCTI_RECEIVE (ldr_ctx) = tctildr_receive;
440 TSS2_TCTI_FINALIZE (ldr_ctx) = tctildr_finalize;
441 TSS2_TCTI_CANCEL (ldr_ctx) = tctildr_cancel;
442 TSS2_TCTI_GET_POLL_HANDLES (ldr_ctx) = tctildr_get_poll_handles;
443 TSS2_TCTI_SET_LOCALITY (ldr_ctx) = tctildr_set_locality;
444 TSS2_TCTI_MAKE_STICKY (ldr_ctx) = tctildr_make_sticky;
445 ldr_ctx->library_handle = dl_handle;
446 ldr_ctx->tcti = *tctiContext;
447 *tctiContext = (TSS2_TCTI_CONTEXT*)ldr_ctx;
448 return rc;
449 err:
450 if (*tctiContext != NULL) {
451 Tss2_Tcti_Finalize (*tctiContext);
452 free (*tctiContext);
453 *tctiContext = NULL;
454 }
455 tctildr_finalize_data (&dl_handle);
456 return rc;
457 }
458
459 TSS2_RC
Tss2_TctiLdr_Initialize(const char * nameConf,TSS2_TCTI_CONTEXT ** tctiContext)460 Tss2_TctiLdr_Initialize (const char *nameConf,
461 TSS2_TCTI_CONTEXT **tctiContext)
462 {
463 char name [PATH_MAX] = { 0, }, conf [PATH_MAX] = { 0, };
464 TSS2_RC rc;
465
466 if (nameConf == NULL) {
467 return Tss2_TctiLdr_Initialize_Ex (NULL, NULL, tctiContext);
468 }
469 rc = tctildr_conf_parse (nameConf, name, conf);
470 if (rc != TSS2_RC_SUCCESS)
471 return rc;
472 return Tss2_TctiLdr_Initialize_Ex (name, conf, tctiContext);
473 }
474