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