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