• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2015 - 2018 Intel Corporation
4  * All rights reserved.
5  */
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <inttypes.h>
12 #include <limits.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #ifndef _WIN32
18 #include <sys/time.h>
19 #include <unistd.h>
20 #endif
21 
22 #include "tss2_mu.h"
23 #include "tss2_tcti_mssim.h"
24 
25 #include "tcti-mssim.h"
26 #include "tcti-common.h"
27 #include "util/key-value-parse.h"
28 #define LOGMODULE tcti
29 #include "util/log.h"
30 
31 /*
32  * This function wraps the "up-cast" of the opaque TCTI context type to the
33  * type for the mssim TCTI context. The only safeguard we have to ensure this
34  * operation is possible is the magic number in the mssim TCTI context.
35  * If passed a NULL context, or the magic number check fails, this function
36  * will return NULL.
37  */
38 TSS2_TCTI_MSSIM_CONTEXT*
tcti_mssim_context_cast(TSS2_TCTI_CONTEXT * tcti_ctx)39 tcti_mssim_context_cast (TSS2_TCTI_CONTEXT *tcti_ctx)
40 {
41     if (tcti_ctx != NULL && TSS2_TCTI_MAGIC (tcti_ctx) == TCTI_MSSIM_MAGIC) {
42         return (TSS2_TCTI_MSSIM_CONTEXT*)tcti_ctx;
43     }
44     return NULL;
45 }
46 /*
47  * This function down-casts the mssim TCTI context to the common context
48  * defined in the tcti-common module.
49  */
50 TSS2_TCTI_COMMON_CONTEXT*
tcti_mssim_down_cast(TSS2_TCTI_MSSIM_CONTEXT * tcti_mssim)51 tcti_mssim_down_cast (TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim)
52 {
53     if (tcti_mssim == NULL) {
54         return NULL;
55     }
56     return &tcti_mssim->common;
57 }
58 /*
59  * This function is for sending one of the MS_SIM_* platform commands to the
60  * Microsoft TPM2 simulator. These are sent over the platform socket.
61  */
tcti_platform_command(TSS2_TCTI_CONTEXT * tctiContext,UINT32 cmd)62 TSS2_RC tcti_platform_command (
63     TSS2_TCTI_CONTEXT *tctiContext,
64     UINT32 cmd)
65 {
66     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = tcti_mssim_context_cast (tctiContext);
67     uint8_t buf [sizeof (cmd)] = { 0 };
68     UINT32 rsp = 0;
69     TSS2_RC rc = TSS2_RC_SUCCESS;
70     int ret;
71     ssize_t read_ret;
72 
73     if (tcti_mssim == NULL) {
74         return TSS2_TCTI_RC_BAD_CONTEXT;
75     }
76     rc = Tss2_MU_UINT32_Marshal (cmd, buf, sizeof (cmd), NULL);
77     if (rc != TSS2_RC_SUCCESS) {
78         LOG_ERROR ("Failed to marshal platform command %" PRIu32 ", rc: 0x%"
79                    PRIx32, cmd, rc);
80         return rc;
81     }
82 
83     LOGBLOB_DEBUG(buf, sizeof (cmd), "Sending %zu bytes to socket %" PRIu32
84                   ":", sizeof (cmd), tcti_mssim->platform_sock);
85     ret = write_all (tcti_mssim->platform_sock, buf, sizeof (cmd));
86     if (ret < (ssize_t) sizeof (cmd)) {
87         LOG_ERROR("Failed to send platform command %d with error: %d",
88                   cmd, ret);
89         return TSS2_TCTI_RC_IO_ERROR;
90     }
91 
92 #ifdef _WIN32
93     read_ret = recv (tcti_mssim->platform_sock, (char *) buf, sizeof (buf), 0);
94     if (read_ret < (ssize_t) sizeof (buf)) {
95         LOG_ERROR ("Failed to get response to platform command, errno %d: %s",
96                    WSAGetLastError(), strerror (WSAGetLastError()));
97         return TSS2_TCTI_RC_IO_ERROR;
98     }
99 #else
100     read_ret = read(tcti_mssim->platform_sock, buf, sizeof (buf));
101     if (read_ret < (ssize_t) sizeof (buf)) {
102         LOG_ERROR ("Failed to get response to platform command, errno %d: %s",
103                    errno, strerror (errno));
104         return TSS2_TCTI_RC_IO_ERROR;
105     }
106 #endif
107     LOGBLOB_DEBUG (buf, sizeof (buf), "Received %zu bytes from socket 0x%"
108                    PRIx32 ":", read_ret, tcti_mssim->platform_sock);
109     rc = Tss2_MU_UINT32_Unmarshal (buf, sizeof (rsp), NULL, &rsp);
110     if (rc != TSS2_RC_SUCCESS) {
111         LOG_ERROR ("Failed to unmarshal response to platform command. rc: 0x%"
112                    PRIx32, rc);
113         return rc;
114     }
115     if (rsp != 0) {
116         LOG_INFO ("Platform command failed with error: %" PRIu32, rsp);
117         return TSS2_TCTI_RC_IO_ERROR;
118     }
119     return rc;
120 }
121 /*
122  * This function sends the special TPM_SESSION_END message over the provided
123  * socket.
124  */
125 TSS2_RC
send_sim_session_end(SOCKET sock)126 send_sim_session_end (
127     SOCKET sock)
128 {
129     uint8_t buf [4] = { 0, };
130     TSS2_RC rc;
131 
132     rc = Tss2_MU_UINT32_Marshal (TPM_SESSION_END, buf, sizeof (buf), NULL);
133     if (rc == TSS2_RC_SUCCESS) {
134         return rc;
135     }
136     return socket_xmit_buf (sock, buf, sizeof (buf));
137 }
138 
139 /*
140  * This function is used to send the simulator a sort of command message
141  * that tells it we're about to send it a TPM command. This requires that
142  * we first send it a 4 byte code that's defined by the simulator. Then
143  * another byte identifying the locality and finally the size of the TPM
144  * command buffer that we're about to send. After these 9 bytes are sent
145  * the simulator will accept a TPM command buffer.
146  */
147 #define SIM_CMD_SIZE (sizeof (UINT32) + sizeof (UINT8) + sizeof (UINT32))
148 TSS2_RC
send_sim_cmd_setup(TSS2_TCTI_MSSIM_CONTEXT * tcti_mssim,UINT32 size)149 send_sim_cmd_setup (
150     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim,
151     UINT32 size)
152 {
153     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
154     uint8_t buf [SIM_CMD_SIZE] = { 0 };
155     size_t offset = 0;
156     TSS2_RC rc;
157 
158     rc = Tss2_MU_UINT32_Marshal (MS_SIM_TPM_SEND_COMMAND,
159                                  buf,
160                                  sizeof (buf),
161                                  &offset);
162     if (rc != TSS2_RC_SUCCESS) {
163         return rc;
164     }
165 
166     rc = Tss2_MU_UINT8_Marshal (tcti_common->locality,
167                                 buf,
168                                 sizeof (buf),
169                                 &offset);
170     if (rc != TSS2_RC_SUCCESS) {
171         return rc;
172     }
173 
174     rc = Tss2_MU_UINT32_Marshal (size, buf, sizeof (buf), &offset);
175     if (rc != TSS2_RC_SUCCESS) {
176         return rc;
177     }
178 
179     return socket_xmit_buf (tcti_mssim->tpm_sock, buf, sizeof (buf));
180 }
181 
182 TSS2_RC
tcti_mssim_transmit(TSS2_TCTI_CONTEXT * tcti_ctx,size_t size,const uint8_t * cmd_buf)183 tcti_mssim_transmit (
184     TSS2_TCTI_CONTEXT *tcti_ctx,
185     size_t size,
186     const uint8_t *cmd_buf)
187 {
188     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = tcti_mssim_context_cast (tcti_ctx);
189     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
190     tpm_header_t header;
191     TSS2_RC rc;
192 
193     if (tcti_mssim == NULL) {
194         return TSS2_TCTI_RC_BAD_CONTEXT;
195     }
196     rc = tcti_common_transmit_checks (tcti_common, cmd_buf);
197     if (rc != TSS2_RC_SUCCESS) {
198         return rc;
199     }
200     rc = header_unmarshal (cmd_buf, &header);
201     if (rc != TSS2_RC_SUCCESS) {
202         return rc;
203     }
204     if (header.size != size) {
205         LOG_ERROR ("Buffer size parameter: %zu, and TPM2 command header size "
206                    "field: %" PRIu32 " disagree.", size, header.size);
207         return TSS2_TCTI_RC_BAD_VALUE;
208     }
209 
210     LOG_DEBUG ("Sending command with TPM_CC 0x%" PRIx32 " and size %" PRIu32,
211                header.code, header.size);
212     rc = send_sim_cmd_setup (tcti_mssim, header.size);
213     if (rc != TSS2_RC_SUCCESS) {
214         return rc;
215     }
216     rc = socket_xmit_buf (tcti_mssim->tpm_sock, cmd_buf, size);
217     if (rc != TSS2_RC_SUCCESS) {
218         return rc;
219     }
220 
221     tcti_common->state = TCTI_STATE_RECEIVE;
222 
223     return rc;
224 }
225 
226 TSS2_RC
tcti_mssim_cancel(TSS2_TCTI_CONTEXT * tctiContext)227 tcti_mssim_cancel (
228     TSS2_TCTI_CONTEXT *tctiContext)
229 {
230     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = tcti_mssim_context_cast (tctiContext);
231     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
232     TSS2_RC rc;
233 
234     if (tcti_mssim == NULL) {
235         return TSS2_TCTI_RC_BAD_CONTEXT;
236     }
237     rc = tcti_common_cancel_checks (tcti_common);
238     if (rc != TSS2_RC_SUCCESS) {
239         return rc;
240     }
241     rc = tcti_platform_command (tctiContext, MS_SIM_CANCEL_ON);
242     if (rc != TSS2_RC_SUCCESS) {
243         return rc;
244     }
245 
246     tcti_common->state = TCTI_STATE_TRANSMIT;
247     tcti_mssim->cancel = 1;
248 
249     return rc;
250 }
251 
252 TSS2_RC
tcti_mssim_set_locality(TSS2_TCTI_CONTEXT * tctiContext,uint8_t locality)253 tcti_mssim_set_locality (
254     TSS2_TCTI_CONTEXT *tctiContext,
255     uint8_t locality)
256 {
257     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = tcti_mssim_context_cast (tctiContext);
258     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
259     TSS2_RC rc;
260 
261     if (tcti_mssim == NULL) {
262         return TSS2_TCTI_RC_BAD_CONTEXT;
263     }
264     rc = tcti_common_set_locality_checks (tcti_common);
265     if (rc != TSS2_RC_SUCCESS) {
266         return rc;
267     }
268 
269     tcti_common->locality = locality;
270     return TSS2_RC_SUCCESS;
271 }
272 
273 TSS2_RC
tcti_mssim_get_poll_handles(TSS2_TCTI_CONTEXT * tctiContext,TSS2_TCTI_POLL_HANDLE * handles,size_t * num_handles)274 tcti_mssim_get_poll_handles (
275     TSS2_TCTI_CONTEXT *tctiContext,
276     TSS2_TCTI_POLL_HANDLE *handles,
277     size_t *num_handles)
278 {
279     (void)(tctiContext);
280     (void)(handles);
281     (void)(num_handles);
282     return TSS2_TCTI_RC_NOT_IMPLEMENTED;
283 }
284 
285 void
tcti_mssim_finalize(TSS2_TCTI_CONTEXT * tctiContext)286 tcti_mssim_finalize(
287     TSS2_TCTI_CONTEXT *tctiContext)
288 {
289     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = tcti_mssim_context_cast (tctiContext);
290 
291     if (tcti_mssim == NULL) {
292         return;
293     }
294     send_sim_session_end (tcti_mssim->platform_sock);
295     send_sim_session_end (tcti_mssim->tpm_sock);
296     socket_close (&tcti_mssim->platform_sock);
297     socket_close (&tcti_mssim->tpm_sock);
298 }
299 
300 TSS2_RC
tcti_mssim_receive(TSS2_TCTI_CONTEXT * tctiContext,size_t * response_size,unsigned char * response_buffer,int32_t timeout)301 tcti_mssim_receive (
302     TSS2_TCTI_CONTEXT *tctiContext,
303     size_t *response_size,
304     unsigned char *response_buffer,
305     int32_t timeout)
306 {
307 #ifdef TEST_FAPI_ASYNC
308     /* Used for simulating a timeout. */
309     static int wait = 0;
310 #endif
311     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = tcti_mssim_context_cast (tctiContext);
312     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
313     TSS2_RC rc;
314     UINT32 trash;
315     int ret;
316 
317     if (tcti_mssim == NULL) {
318         return TSS2_TCTI_RC_BAD_CONTEXT;
319     }
320     rc = tcti_common_receive_checks (tcti_common, response_size);
321     if (rc != TSS2_RC_SUCCESS) {
322         return rc;
323     }
324 
325     if (timeout != TSS2_TCTI_TIMEOUT_BLOCK) {
326         LOG_TRACE("Asynchronous I/O not actually implemented.");
327 #ifdef TEST_FAPI_ASYNC
328         if (wait < 1) {
329             LOG_TRACE("Simulating Async by requesting another invocation.");
330             wait += 1;
331             return TSS2_TCTI_RC_TRY_AGAIN;
332         } else {
333             LOG_TRACE("Sending the actual result.");
334             wait = 0;
335         }
336 #endif /* TEST_FAPI_ASYNC */
337     }
338 
339     if (tcti_common->header.size == 0) {
340         /* Receive the size of the response. */
341         uint8_t size_buf [sizeof (UINT32)];
342         ret = socket_recv_buf (tcti_mssim->tpm_sock, size_buf, sizeof (UINT32));
343         if (ret != sizeof (UINT32)) {
344             rc = TSS2_TCTI_RC_IO_ERROR;
345             goto out;
346         }
347 
348         rc = Tss2_MU_UINT32_Unmarshal (size_buf,
349                                        sizeof (size_buf),
350                                        0,
351                                        &tcti_common->header.size);
352         if (rc != TSS2_RC_SUCCESS) {
353             LOG_WARNING ("Failed to unmarshal size from tpm2 simulator "
354                          "protocol: 0x%" PRIu32, rc);
355             goto out;
356         }
357 
358         LOG_DEBUG ("response size: %" PRIu32, tcti_common->header.size);
359     }
360 
361     if (response_buffer == NULL) {
362         *response_size = tcti_common->header.size;
363         return TSS2_RC_SUCCESS;
364     }
365 
366     if (*response_size < tcti_common->header.size) {
367         *response_size = tcti_common->header.size;
368         return TSS2_TCTI_RC_INSUFFICIENT_BUFFER;
369     }
370     *response_size = tcti_common->header.size;
371 
372     /* Receive the TPM response. */
373     LOG_DEBUG ("Reading response of size %" PRIu32, tcti_common->header.size);
374     ret = socket_recv_buf (tcti_mssim->tpm_sock,
375                            (unsigned char *)response_buffer,
376                            tcti_common->header.size);
377     if (ret < (ssize_t)tcti_common->header.size) {
378         rc = TSS2_TCTI_RC_IO_ERROR;
379         goto out;
380     }
381     LOGBLOB_DEBUG(response_buffer, tcti_common->header.size,
382                   "Response buffer received:");
383 
384     /* Receive the appended four bytes of 0's */
385     ret = socket_recv_buf (tcti_mssim->tpm_sock,
386                            (unsigned char *)&trash,
387                            4);
388     if (ret != 4) {
389         rc = TSS2_TCTI_RC_IO_ERROR;
390         goto out;
391     }
392 
393     if (tcti_mssim->cancel) {
394         rc = tcti_platform_command (tctiContext, MS_SIM_CANCEL_OFF);
395         tcti_mssim->cancel = 0;
396     }
397     /*
398      * Executing code beyond this point transitions the state machine to
399      * TRANSMIT. Another call to this function will not be possible until
400      * another command is sent to the TPM.
401      */
402 out:
403     tcti_common->header.size = 0;
404     tcti_common->state = TCTI_STATE_TRANSMIT;
405 
406     return rc;
407 }
408 
409 /**
410  * This function sends the Microsoft simulator the MS_SIM_POWER_ON and
411  * MS_SIM_NV_ON commands using the platform command mechanism. Without
412  * these the simulator will respond with zero sized buffer which causes
413  * the TSS to freak out. Sending this command more than once is harmless,
414  * so it's advisable to call this function as part of the TCTI context
415  * initialization just to be sure.
416  *
417  * NOTE: The caller will still need to call Tss2_Sys_Startup. If they
418  * don't, an error will be returned from each call till they do but
419  * the error will at least be meaningful (TPM2_RC_INITIALIZE).
420  */
421 static TSS2_RC
simulator_setup(TSS2_TCTI_CONTEXT * tctiContext)422 simulator_setup (
423     TSS2_TCTI_CONTEXT *tctiContext)
424 {
425     TSS2_RC rc;
426 
427     LOG_TRACE ("Initializing TCTI context 0x%" PRIxPTR,
428                (uintptr_t)tctiContext);
429     rc = tcti_platform_command (tctiContext, MS_SIM_POWER_ON);
430     if (rc != TSS2_RC_SUCCESS) {
431         LOG_WARNING ("Failed to send MS_SIM_POWER_ON platform command.");
432         return rc;
433     }
434 
435     rc = tcti_platform_command (tctiContext, MS_SIM_NV_ON);
436     if (rc != TSS2_RC_SUCCESS) {
437         LOG_WARNING ("Failed to send MS_SIM_NV_ON platform command.");
438     }
439 
440     return rc;
441 }
442 
443 /*
444  * This is a utility function to extract a TCP port number from a string.
445  * The string must be 6 characters long. If the supplied string contains an
446  * invalid port number then 0 is returned.
447  */
448 static uint16_t
string_to_port(char port_str[6])449 string_to_port (char port_str[6])
450 {
451     uint32_t port = 0;
452 
453     if (sscanf (port_str, "%" SCNu32, &port) == EOF || port > UINT16_MAX) {
454         return 0;
455     }
456     return port;
457 }
458 /*
459  * This function is a callback conforming to the KeyValueFunc prototype. It
460  * is called by the key-value-parse module for each key / value pair extracted
461  * from the configuration string. Its sole purpose is to identify valid keys
462  * from the conf string and to store their corresponding values in the
463  * mssim_conf_t structure which is passed through the 'user_data' parameter.
464  */
465 TSS2_RC
mssim_kv_callback(const key_value_t * key_value,void * user_data)466 mssim_kv_callback (const key_value_t *key_value,
467                    void *user_data)
468 {
469     mssim_conf_t *mssim_conf = (mssim_conf_t*)user_data;
470 
471     LOG_TRACE ("key_value: 0x%" PRIxPTR " and user_data: 0x%" PRIxPTR,
472                (uintptr_t)key_value, (uintptr_t)user_data);
473     if (key_value == NULL || user_data == NULL) {
474         LOG_WARNING ("%s passed NULL parameter", __func__);
475         return TSS2_TCTI_RC_GENERAL_FAILURE;
476     }
477     LOG_DEBUG ("key: %s / value: %s\n", key_value->key, key_value->value);
478     if (strcmp (key_value->key, "host") == 0) {
479         mssim_conf->host = key_value->value;
480         return TSS2_RC_SUCCESS;
481     } else if (strcmp (key_value->key, "port") == 0) {
482         mssim_conf->port = string_to_port (key_value->value);
483         if (mssim_conf->port == 0) {
484             return TSS2_TCTI_RC_BAD_VALUE;
485         }
486         return TSS2_RC_SUCCESS;
487     } else {
488         return TSS2_TCTI_RC_BAD_VALUE;
489     }
490 }
491 void
tcti_mssim_init_context_data(TSS2_TCTI_COMMON_CONTEXT * tcti_common)492 tcti_mssim_init_context_data (
493     TSS2_TCTI_COMMON_CONTEXT *tcti_common)
494 {
495     TSS2_TCTI_MAGIC (tcti_common) = TCTI_MSSIM_MAGIC;
496     TSS2_TCTI_VERSION (tcti_common) = TCTI_VERSION;
497     TSS2_TCTI_TRANSMIT (tcti_common) = tcti_mssim_transmit;
498     TSS2_TCTI_RECEIVE (tcti_common) = tcti_mssim_receive;
499     TSS2_TCTI_FINALIZE (tcti_common) = tcti_mssim_finalize;
500     TSS2_TCTI_CANCEL (tcti_common) = tcti_mssim_cancel;
501     TSS2_TCTI_GET_POLL_HANDLES (tcti_common) = tcti_mssim_get_poll_handles;
502     TSS2_TCTI_SET_LOCALITY (tcti_common) = tcti_mssim_set_locality;
503     TSS2_TCTI_MAKE_STICKY (tcti_common) = tcti_make_sticky_not_implemented;
504     tcti_common->state = TCTI_STATE_TRANSMIT;
505     tcti_common->locality = 0;
506     memset (&tcti_common->header, 0, sizeof (tcti_common->header));
507 }
508 /*
509  * This is an implementation of the standard TCTI initialization function for
510  * this module.
511  */
512 TSS2_RC
Tss2_Tcti_Mssim_Init(TSS2_TCTI_CONTEXT * tctiContext,size_t * size,const char * conf)513 Tss2_Tcti_Mssim_Init (
514     TSS2_TCTI_CONTEXT *tctiContext,
515     size_t *size,
516     const char *conf)
517 {
518     TSS2_TCTI_MSSIM_CONTEXT *tcti_mssim = (TSS2_TCTI_MSSIM_CONTEXT*)tctiContext;
519     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_mssim_down_cast (tcti_mssim);
520     TSS2_RC rc;
521     char *conf_copy = NULL;
522     mssim_conf_t mssim_conf = MSSIM_CONF_DEFAULT_INIT;
523 
524     if (conf == NULL) {
525         LOG_TRACE ("tctiContext: 0x%" PRIxPTR ", size: 0x%" PRIxPTR ""
526                    " default configuration will be used.",
527                    (uintptr_t)tctiContext, (uintptr_t)size);
528     } else {
529         LOG_TRACE ("tctiContext: 0x%" PRIxPTR ", size: 0x%" PRIxPTR ", conf: %s",
530                    (uintptr_t)tctiContext, (uintptr_t)size, conf);
531     }
532     if (size == NULL) {
533         return TSS2_TCTI_RC_BAD_VALUE;
534     }
535     if (tctiContext == NULL) {
536         *size = sizeof (TSS2_TCTI_MSSIM_CONTEXT);
537         return TSS2_RC_SUCCESS;
538     }
539 
540     if (conf != NULL) {
541         LOG_TRACE ("conf is not NULL");
542         if (strlen (conf) > TCTI_MSSIM_CONF_MAX) {
543             LOG_WARNING ("Provided conf string exceeds maximum of %u",
544                          TCTI_MSSIM_CONF_MAX);
545             return TSS2_TCTI_RC_BAD_VALUE;
546         }
547         conf_copy = strdup (conf);
548         if (conf_copy == NULL) {
549             LOG_ERROR ("Failed to allocate buffer: %s", strerror (errno));
550             rc = TSS2_TCTI_RC_GENERAL_FAILURE;
551             goto fail_out;
552         }
553         LOG_DEBUG ("Dup'd conf string to: 0x%" PRIxPTR,
554                    (uintptr_t)conf_copy);
555         rc = parse_key_value_string (conf_copy,
556                                      mssim_kv_callback,
557                                      &mssim_conf);
558         if (rc != TSS2_RC_SUCCESS) {
559             goto fail_out;
560         }
561     }
562     LOG_DEBUG ("Initializing mssim TCTI with host: %s, port: %" PRIu16,
563                mssim_conf.host, mssim_conf.port);
564 
565     tcti_mssim->tpm_sock = -1;
566     tcti_mssim->platform_sock = -1;
567 
568     rc = socket_connect (mssim_conf.host,
569                          mssim_conf.port,
570                          &tcti_mssim->tpm_sock);
571     if (rc != TSS2_RC_SUCCESS) {
572         goto fail_out;
573     }
574 
575     rc = socket_connect (mssim_conf.host,
576                          mssim_conf.port + 1,
577                          &tcti_mssim->platform_sock);
578     if (rc != TSS2_RC_SUCCESS) {
579         goto fail_out;
580     }
581 
582     tcti_mssim_init_context_data (tcti_common);
583     rc = simulator_setup (tctiContext);
584     if (rc != TSS2_RC_SUCCESS) {
585         goto fail_out;
586     }
587 
588     if (conf_copy != NULL) {
589         free (conf_copy);
590     }
591     return TSS2_RC_SUCCESS;
592 
593 fail_out:
594     if (conf_copy != NULL) {
595         free (conf_copy);
596     }
597     socket_close (&tcti_mssim->tpm_sock);
598     socket_close (&tcti_mssim->platform_sock);
599 
600     return rc;
601 }
602 
603 /* public info structure */
604 const TSS2_TCTI_INFO tss2_tcti_info = {
605     .version = TCTI_VERSION,
606     .name = "tcti-socket",
607     .description = "TCTI module for communication with the Microsoft TPM2 Simulator.",
608     .config_help = "Key / value string in the form \"host=localhost,port=2321\".",
609     .init = Tss2_Tcti_Mssim_Init,
610 };
611 
612 const TSS2_TCTI_INFO*
Tss2_Tcti_Info(void)613 Tss2_Tcti_Info (void)
614 {
615     return &tss2_tcti_info;
616 }
617