blob: 7163791ffc1c23ed4febec2f1c17fdb3cad1743c [file] [log] [blame]
Philip Tricca21fa3212018-02-19 06:43:56 -08001/*
2 * Copyright (c) 2015 - 2018 Intel Corporation
Philip Triccaa003d762017-10-17 13:25:42 -07003 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
Philip Tricca21fa3212018-02-19 06:43:56 -080026 */
Will Arthur54e04e42015-07-15 11:29:25 -040027
Philip Tricca77683c72017-12-04 16:05:52 -080028#include <inttypes.h>
29#include <limits.h>
Will Arthur54e04e42015-07-15 11:29:25 -040030#include <stdio.h>
Philip Triccaa003d762017-10-17 13:25:42 -070031#include <stdlib.h>
Armin Kusterace89dd2017-04-01 14:49:06 -070032#include <sys/time.h>
Andreas Fuchs43a0d762017-11-30 15:41:05 +010033#include <inttypes.h>
Will Arthur54e04e42015-07-15 11:29:25 -040034
Philip Tricca77683c72017-12-04 16:05:52 -080035#include <uriparser/Uri.h>
36
Tadeusz Strukb21f9f92017-10-09 13:51:19 -070037#include "sapi/tss2_mu.h"
Philip Triccadd3b03c2017-03-05 11:38:08 -080038#include "tcti/tcti_socket.h"
Philip Triccac3dedc22016-01-15 13:47:22 -080039#include "sysapi_util.h"
Philip Tricca473aebe2017-10-17 13:04:17 -070040#include "tcti.h"
Philip Tricca330d3c72017-07-02 13:49:32 -070041#include "sockets.h"
Tadeusz Struk8203a372017-06-26 15:15:18 -070042#include "tss2_endian.h"
Andreas Fuchs43a0d762017-11-30 15:41:05 +010043#define LOGMODULE tcti
44#include "log/log.h"
Will Arthur54e04e42015-07-15 11:29:25 -040045
Philip Triccac21dbf32018-03-03 09:07:48 -080046#define TCTI_SOCKET_DEFAULT_CONF "tcp://127.0.0.1:2321"
47#define TCTI_SOCKET_DEFAULT_PORT 2321
48
Philip Tricca76ba6002018-02-21 10:52:52 -080049static TSS2_RC xmit_buf (
Philip Triccaa003d762017-10-17 13:25:42 -070050 SOCKET sock,
Philip Tricca76ba6002018-02-21 10:52:52 -080051 const void *buf,
52 size_t size)
Philip Tricca4ee284b2016-03-30 17:40:39 -070053{
Philip Triccadff26862018-02-19 15:27:18 -080054 int ret;
Philip Tricca4ee284b2016-03-30 17:40:39 -070055
Philip Tricca76ba6002018-02-21 10:52:52 -080056 LOGBLOB_DEBUG (buf, size, "Writing %zu bytes to socket %d:", size, sock);
57 ret = write_all (sock, buf, size);
58 if (ret < size) {
Philip Triccadff26862018-02-19 15:27:18 -080059 LOG_ERROR("Failed to write to fd %d: %d", sock, WSAGetLastError ());
60 return TSS2_TCTI_RC_IO_ERROR;
Philip Triccaa003d762017-10-17 13:25:42 -070061 }
Philip Triccadff26862018-02-19 15:27:18 -080062 return TSS2_RC_SUCCESS;
Philip Tricca4ee284b2016-03-30 17:40:39 -070063}
64
Philip Triccabdc69452018-02-21 12:45:33 -080065TSS2_RC send_sim_session_end (
66 SOCKET sock)
Will Arthur54e04e42015-07-15 11:29:25 -040067{
Philip Triccabdc69452018-02-21 12:45:33 -080068 uint8_t buf [4] = { 0, };
69 TSS2_RC rc;
Philip Triccadfa41a52016-07-20 17:43:57 -070070
Philip Triccabdc69452018-02-21 12:45:33 -080071 rc = Tss2_MU_UINT32_Marshal (TPM_SESSION_END, buf, sizeof (buf), NULL);
72 if (rc == TSS2_RC_SUCCESS) {
73 return rc;
Will Arthur54e04e42015-07-15 11:29:25 -040074 }
Philip Triccabdc69452018-02-21 12:45:33 -080075 return xmit_buf (sock, buf, sizeof (buf));
Will Arthur54e04e42015-07-15 11:29:25 -040076}
77
Philip Tricca72fba0b2018-02-21 14:14:32 -080078/*
79 * Utility to function to parse the first 10 bytes of a buffer and populate
80 * the 'header' structure with the results. The provided buffer is assumed to
81 * be at least 10 bytes long.
82 */
83TSS2_RC parse_header (
Philip Triccaddf42b22018-02-21 15:37:23 -080084 const uint8_t *buf,
Philip Tricca72fba0b2018-02-21 14:14:32 -080085 tpm_header_t *header)
86{
87 TSS2_RC rc;
88 size_t offset = 0;
89
90 LOG_TRACE ("Parsing header from buffer: 0x%" PRIxPTR, (uintptr_t)buf);
91 rc = Tss2_MU_TPM2_ST_Unmarshal (buf,
92 TPM_HEADER_SIZE,
93 &offset,
94 &header->tag);
95 if (rc != TSS2_RC_SUCCESS) {
96 LOG_ERROR ("Failed to unmarshal tag.");
97 return rc;
98 }
99 rc = Tss2_MU_UINT32_Unmarshal (buf,
100 TPM_HEADER_SIZE,
101 &offset,
102 &header->size);
103 if (rc != TSS2_RC_SUCCESS) {
104 LOG_ERROR ("Failed to unmarshal command size.");
105 return rc;
106 }
107 rc = Tss2_MU_UINT32_Unmarshal (buf,
108 TPM_HEADER_SIZE,
109 &offset,
110 &header->code);
111 if (rc != TSS2_RC_SUCCESS) {
112 LOG_ERROR ("Failed to unmarshal command code.");
113 }
114 return rc;
115}
116
Philip Triccad42e7232018-02-21 14:59:49 -0800117/*
118 * This fucntion is used to send the simulator a sort of command message
119 * that tells it we're about to send it a TPM command. This requires that
120 * we first send it a 4 byte code that's defined by the simulator. Then
121 * another byte identifying the locality and finally the size of the TPM
122 * command buffer that we're about to send. After these 9 bytes are sent
123 * the simulator will accept a TPM command buffer.
124 */
Philip Tricca3a382922018-02-21 16:14:15 -0800125#define SIM_CMD_SIZE (sizeof (UINT32) + sizeof (UINT8) + sizeof (UINT32))
Philip Triccad42e7232018-02-21 14:59:49 -0800126TSS2_RC send_sim_cmd_setup (
127 TSS2_TCTI_CONTEXT_INTEL *tcti_intel,
128 UINT32 size)
129{
Philip Tricca3a382922018-02-21 16:14:15 -0800130 uint8_t buf [SIM_CMD_SIZE] = { 0 };
131 size_t offset = 0;
Philip Triccad42e7232018-02-21 14:59:49 -0800132 TSS2_RC rc;
133
Philip Triccad42e7232018-02-21 14:59:49 -0800134 rc = Tss2_MU_UINT32_Marshal (MS_SIM_TPM_SEND_COMMAND,
135 buf,
Philip Tricca3a382922018-02-21 16:14:15 -0800136 sizeof (buf),
137 &offset);
Philip Triccad42e7232018-02-21 14:59:49 -0800138 if (rc != TSS2_RC_SUCCESS) {
139 return rc;
140 }
141
Philip Tricca3a382922018-02-21 16:14:15 -0800142 rc = Tss2_MU_UINT8_Marshal (tcti_intel->status.locality,
143 buf,
144 sizeof (buf),
145 &offset);
Philip Triccad42e7232018-02-21 14:59:49 -0800146 if (rc != TSS2_RC_SUCCESS) {
147 return rc;
148 }
149
Philip Tricca3a382922018-02-21 16:14:15 -0800150 rc = Tss2_MU_UINT32_Marshal (size, buf, sizeof (buf), &offset);
Philip Triccad42e7232018-02-21 14:59:49 -0800151 if (rc != TSS2_RC_SUCCESS) {
152 return rc;
153 }
Philip Tricca3a382922018-02-21 16:14:15 -0800154
Philip Triccad42e7232018-02-21 14:59:49 -0800155 return xmit_buf (tcti_intel->tpmSock, buf, sizeof (buf));
156}
157
Philip Triccaaca82c92018-02-21 15:47:40 -0800158TSS2_RC tcti_socket_transmit (
159 TSS2_TCTI_CONTEXT *tcti_ctx,
160 size_t size,
161 const uint8_t *cmd_buf)
Will Arthur54e04e42015-07-15 11:29:25 -0400162{
Philip Triccaaca82c92018-02-21 15:47:40 -0800163 tpm_header_t header = { 0 };
164 TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tcti_ctx);
165 TSS2_RC rc;
Philip Triccadfa41a52016-07-20 17:43:57 -0700166
Philip Triccaaca82c92018-02-21 15:47:40 -0800167 rc = tcti_send_checks (tcti_ctx, cmd_buf);
168 if (rc != TSS2_RC_SUCCESS) {
169 return rc;
wcarthureedecd62015-11-20 16:59:45 -0500170 }
Philip Triccaaca82c92018-02-21 15:47:40 -0800171 rc = parse_header (cmd_buf, &header);
172 if (rc != TSS2_RC_SUCCESS) {
173 return rc;
Andreas Fuchsf8a66622017-11-29 14:27:25 +0100174 }
Philip Triccaaca82c92018-02-21 15:47:40 -0800175 if (header.size != size) {
Philip Tricca72fba0b2018-02-21 14:14:32 -0800176 LOG_ERROR ("Buffer size parameter: %zu, and TPM2 command header size "
Philip Triccaaca82c92018-02-21 15:47:40 -0800177 "field: %" PRIu32 " disagree.", size, header.size);
Philip Tricca72fba0b2018-02-21 14:14:32 -0800178 return TSS2_TCTI_RC_BAD_VALUE;
179 }
Will Arthur54e04e42015-07-15 11:29:25 -0400180
Philip Triccaaca82c92018-02-21 15:47:40 -0800181 LOG_DEBUG ("Sending command with TPM_CC 0x%" PRIx32 " and size %" PRIu32,
182 header.code, header.size);
183 rc = send_sim_cmd_setup (tcti_intel, header.size);
184 if (rc != TSS2_RC_SUCCESS) {
185 return rc;
Philip Triccaa003d762017-10-17 13:25:42 -0700186 }
Philip Triccaaca82c92018-02-21 15:47:40 -0800187 rc = xmit_buf (tcti_intel->tpmSock, cmd_buf, size);
188 if (rc != TSS2_RC_SUCCESS) {
189 return rc;
Philip Triccaa003d762017-10-17 13:25:42 -0700190 }
Will Arthur54e04e42015-07-15 11:29:25 -0400191
Philip Triccaa003d762017-10-17 13:25:42 -0700192 tcti_intel->previousStage = TCTI_STAGE_SEND_COMMAND;
Philip Triccaaca82c92018-02-21 15:47:40 -0800193 tcti_intel->status.commandSent = 1;
Philip Triccaa003d762017-10-17 13:25:42 -0700194 tcti_intel->status.tagReceived = 0;
195 tcti_intel->status.responseSizeReceived = 0;
196 tcti_intel->status.protocolResponseSizeReceived = 0;
wcarthureedecd62015-11-20 16:59:45 -0500197
Philip Triccaaca82c92018-02-21 15:47:40 -0800198 return rc;
Will Arthur54e04e42015-07-15 11:29:25 -0400199}
200
201TSS2_RC SocketCancel(
202 TSS2_TCTI_CONTEXT *tctiContext
203 )
204{
Philip Tricca24f555c2017-10-13 17:51:53 -0700205 TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
Philip Tricca3f1828c2017-10-18 18:44:13 -0700206 TSS2_RC rc;
Will Arthur54e04e42015-07-15 11:29:25 -0400207
Philip Tricca3f1828c2017-10-18 18:44:13 -0700208 rc = tcti_common_checks (tctiContext);
209 if (rc != TSS2_RC_SUCCESS) {
210 return rc;
Philip Triccaa003d762017-10-17 13:25:42 -0700211 } else if (tcti_intel->status.commandSent != 1) {
212 return TSS2_TCTI_RC_BAD_SEQUENCE;
213 } else {
214 return PlatformCommand (tctiContext, MS_SIM_CANCEL_ON);
Will Arthur54e04e42015-07-15 11:29:25 -0400215 }
Will Arthur54e04e42015-07-15 11:29:25 -0400216}
217
218TSS2_RC SocketSetLocality(
Philip Triccaa003d762017-10-17 13:25:42 -0700219 TSS2_TCTI_CONTEXT *tctiContext,
220 uint8_t locality
Will Arthur54e04e42015-07-15 11:29:25 -0400221 )
222{
Philip Tricca24f555c2017-10-13 17:51:53 -0700223 TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
Philip Tricca3f1828c2017-10-18 18:44:13 -0700224 TSS2_RC rc;
Will Arthur54e04e42015-07-15 11:29:25 -0400225
Philip Tricca3f1828c2017-10-18 18:44:13 -0700226 rc = tcti_common_checks (tctiContext);
227 if (rc != TSS2_RC_SUCCESS) {
228 return rc;
Will Arthur54e04e42015-07-15 11:29:25 -0400229 }
Philip Tricca3f1828c2017-10-18 18:44:13 -0700230 if (tcti_intel->status.commandSent == 1) {
231 return TSS2_TCTI_RC_BAD_SEQUENCE;
232 }
233
234 tcti_intel->status.locality = locality;
Will Arthur54e04e42015-07-15 11:29:25 -0400235
Philip Triccaa003d762017-10-17 13:25:42 -0700236 return TSS2_RC_SUCCESS;
Will Arthur54e04e42015-07-15 11:29:25 -0400237}
238
Philip Tricca5917fbf2017-06-29 08:24:09 -0700239TSS2_RC SocketGetPollHandles(
Philip Triccaa003d762017-10-17 13:25:42 -0700240 TSS2_TCTI_CONTEXT *tctiContext,
Philip Tricca5917fbf2017-06-29 08:24:09 -0700241 TSS2_TCTI_POLL_HANDLE *handles,
Philip Triccaa003d762017-10-17 13:25:42 -0700242 size_t *num_handles)
Philip Tricca5917fbf2017-06-29 08:24:09 -0700243{
244 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
245}
246
wcarthur35aa5392016-03-22 16:52:44 -0400247void SocketFinalize(
Philip Triccaa003d762017-10-17 13:25:42 -0700248 TSS2_TCTI_CONTEXT *tctiContext
Will Arthur54e04e42015-07-15 11:29:25 -0400249 )
250{
Philip Tricca24f555c2017-10-13 17:51:53 -0700251 TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
Philip Tricca3f1828c2017-10-18 18:44:13 -0700252 TSS2_RC rc;
Philip Tricca24f555c2017-10-13 17:51:53 -0700253
Philip Tricca3f1828c2017-10-18 18:44:13 -0700254 rc = tcti_common_checks (tctiContext);
255 if (rc != TSS2_RC_SUCCESS) {
Philip Triccaa003d762017-10-17 13:25:42 -0700256 return;
wcarthurf979e352015-11-24 17:34:44 -0500257 }
Philip Triccaa003d762017-10-17 13:25:42 -0700258
Philip Triccabdc69452018-02-21 12:45:33 -0800259 send_sim_session_end (tcti_intel->otherSock);
260 send_sim_session_end (tcti_intel->tpmSock);
Philip Triccaa003d762017-10-17 13:25:42 -0700261
Philip Tricca01b9a1e2018-03-04 21:47:58 -0800262 socket_close (&tcti_intel->otherSock);
263 socket_close (&tcti_intel->tpmSock);
Will Arthur54e04e42015-07-15 11:29:25 -0400264}
265
Will Arthur54e04e42015-07-15 11:29:25 -0400266TSS2_RC SocketReceiveTpmResponse(
Philip Triccaa003d762017-10-17 13:25:42 -0700267 TSS2_TCTI_CONTEXT *tctiContext,
268 size_t *response_size,
269 unsigned char *response_buffer,
270 int32_t timeout
Will Arthur54e04e42015-07-15 11:29:25 -0400271 )
272{
Philip Tricca24f555c2017-10-13 17:51:53 -0700273 TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
Will Arthur54e04e42015-07-15 11:29:25 -0400274 UINT32 trash;
Will Arthur54e04e42015-07-15 11:29:25 -0400275 TSS2_RC rval = TSS2_RC_SUCCESS;
276 fd_set readFds;
277 struct timeval tv, *tvPtr;
278 int32_t timeoutMsecs = timeout % 1000;
279 int iResult;
wcarthura05cdcc2015-12-04 18:07:16 -0500280 unsigned char responseSizeDelta = 0;
wcarthureedecd62015-11-20 16:59:45 -0500281
Philip Triccaa003d762017-10-17 13:25:42 -0700282 rval = tcti_receive_checks (tctiContext, response_size, response_buffer);
283 if (rval != TSS2_RC_SUCCESS) {
wcarthureedecd62015-11-20 16:59:45 -0500284 goto retSocketReceiveTpmResponse;
Philip Triccadfa41a52016-07-20 17:43:57 -0700285 }
286
Philip Triccaa003d762017-10-17 13:25:42 -0700287 if (timeout == TSS2_TCTI_TIMEOUT_BLOCK) {
288 tvPtr = 0;
289 } else {
wcarthur74a92a42015-12-07 16:02:12 -0500290 tv.tv_sec = timeout / 1000;
291 tv.tv_usec = timeoutMsecs * 1000;
292 tvPtr = &tv;
Will Arthur54e04e42015-07-15 11:29:25 -0400293 }
294
Philip Triccaa003d762017-10-17 13:25:42 -0700295 FD_ZERO (&readFds);
296 FD_SET (tcti_intel->tpmSock, &readFds);
Will Arthur54e04e42015-07-15 11:29:25 -0400297
Philip Triccaa003d762017-10-17 13:25:42 -0700298 iResult = select (tcti_intel->tpmSock + 1, &readFds, 0, 0, tvPtr);
299 if (iResult == 0) {
Andreas Fuchs43a0d762017-11-30 15:41:05 +0100300 LOG_ERROR("select failed due to timeout, socket #: 0x%x",
Philip Triccaa003d762017-10-17 13:25:42 -0700301 tcti_intel->tpmSock);
wcarthur74a92a42015-12-07 16:02:12 -0500302 rval = TSS2_TCTI_RC_TRY_AGAIN;
303 goto retSocketReceiveTpmResponse;
Philip Triccaa003d762017-10-17 13:25:42 -0700304 } else if (iResult == SOCKET_ERROR) {
Andreas Fuchs43a0d762017-11-30 15:41:05 +0100305 LOG_ERROR("select failed with socket error: %d",
Philip Triccaa003d762017-10-17 13:25:42 -0700306 WSAGetLastError ());
wcarthur74a92a42015-12-07 16:02:12 -0500307 rval = TSS2_TCTI_RC_IO_ERROR;
308 goto retSocketReceiveTpmResponse;
Philip Triccaa003d762017-10-17 13:25:42 -0700309 } else if (iResult != 1) {
Andreas Fuchs43a0d762017-11-30 15:41:05 +0100310 LOG_ERROR("select failed, read the wrong # of bytes: %d",
Philip Triccaa003d762017-10-17 13:25:42 -0700311 iResult);
wcarthur74a92a42015-12-07 16:02:12 -0500312 rval = TSS2_TCTI_RC_IO_ERROR;
313 goto retSocketReceiveTpmResponse;
314 }
Will Arthur54e04e42015-07-15 11:29:25 -0400315
Philip Triccaa003d762017-10-17 13:25:42 -0700316 if (tcti_intel->status.protocolResponseSizeReceived != 1) {
317 /* Receive the size of the response. */
Philip Tricca77042de2018-03-05 15:14:04 -0800318 iResult = socket_recv_buf (tcti_intel->tpmSock,
319 (unsigned char *)&tcti_intel->responseSize,
320 4);
321 if (iResult != 4) {
322 rval = TSS2_TCTI_RC_IO_ERROR;
wcarthureedecd62015-11-20 16:59:45 -0500323 goto retSocketReceiveTpmResponse;
Philip Triccaa003d762017-10-17 13:25:42 -0700324 }
wcarthureedecd62015-11-20 16:59:45 -0500325
Philip Triccaa003d762017-10-17 13:25:42 -0700326 tcti_intel->responseSize = BE_TO_HOST_32 (tcti_intel->responseSize);
Philip Tricca77042de2018-03-05 15:14:04 -0800327 LOG_DEBUG ("response size: %" PRIu32, tcti_intel->responseSize);
Philip Tricca24f555c2017-10-13 17:51:53 -0700328 tcti_intel->status.protocolResponseSizeReceived = 1;
Will Arthur54e04e42015-07-15 11:29:25 -0400329 }
330
Philip Triccaa003d762017-10-17 13:25:42 -0700331 if (response_buffer == NULL) {
Philip Tricca24f555c2017-10-13 17:51:53 -0700332 *response_size = tcti_intel->responseSize;
333 tcti_intel->status.protocolResponseSizeReceived = 1;
wcarthur74a92a42015-12-07 16:02:12 -0500334 goto retSocketReceiveTpmResponse;
335 }
336
Philip Triccaa003d762017-10-17 13:25:42 -0700337 if (*response_size < tcti_intel->responseSize) {
Philip Tricca24f555c2017-10-13 17:51:53 -0700338 *response_size = tcti_intel->responseSize;
Philip Triccadfa41a52016-07-20 17:43:57 -0700339 rval = TSS2_TCTI_RC_INSUFFICIENT_BUFFER;
wcarthur74a92a42015-12-07 16:02:12 -0500340
Philip Triccaa003d762017-10-17 13:25:42 -0700341 /* If possible, receive tag from TPM. */
Andreas Fuchsbe5899d2017-11-13 17:14:36 +0100342 if (*response_size >= sizeof (TPM2_ST) &&
Philip Triccaa003d762017-10-17 13:25:42 -0700343 tcti_intel->status.tagReceived == 0)
Will Arthur54e04e42015-07-15 11:29:25 -0400344 {
Philip Tricca77042de2018-03-05 15:14:04 -0800345 iResult = socket_recv_buf (tcti_intel->tpmSock,
346 (unsigned char *)&tcti_intel->tag,
347 2);
348 if (iResult < 2) {
349 rval = TSS2_TCTI_RC_IO_ERROR;
wcarthura05cdcc2015-12-04 18:07:16 -0500350 goto retSocketReceiveTpmResponse;
Philip Triccaa003d762017-10-17 13:25:42 -0700351 } else {
Philip Tricca24f555c2017-10-13 17:51:53 -0700352 tcti_intel->status.tagReceived = 1;
wcarthura05cdcc2015-12-04 18:07:16 -0500353 }
Will Arthur54e04e42015-07-15 11:29:25 -0400354 }
wcarthura05cdcc2015-12-04 18:07:16 -0500355
Philip Triccaa003d762017-10-17 13:25:42 -0700356 /* If possible, receive response size from TPM */
Andreas Fuchsbe5899d2017-11-13 17:14:36 +0100357 if (*response_size >= (sizeof (TPM2_ST) + sizeof (TPM2_RC)) &&
Philip Triccaa003d762017-10-17 13:25:42 -0700358 tcti_intel->status.responseSizeReceived == 0)
wcarthur74a92a42015-12-07 16:02:12 -0500359 {
Philip Tricca77042de2018-03-05 15:14:04 -0800360 iResult = socket_recv_buf (tcti_intel->tpmSock,
361 (unsigned char *)&tcti_intel->responseSize,
362 4);
363 if (iResult != 4) {
364 rval = TSS2_TCTI_RC_IO_ERROR;
wcarthureedecd62015-11-20 16:59:45 -0500365 goto retSocketReceiveTpmResponse;
Philip Triccaa003d762017-10-17 13:25:42 -0700366 } else {
Philip Tricca24f555c2017-10-13 17:51:53 -0700367 tcti_intel->responseSize = BE_TO_HOST_32 (tcti_intel->responseSize);
368 tcti_intel->status.responseSizeReceived = 1;
wcarthur74a92a42015-12-07 16:02:12 -0500369 }
370 }
Philip Triccaa003d762017-10-17 13:25:42 -0700371 } else {
Andreas Fuchs43a0d762017-11-30 15:41:05 +0100372 if (tcti_intel->responseSize > 0)
Will-nuce0d3ec22015-12-09 15:09:49 -0500373 {
Andreas Fuchs43a0d762017-11-30 15:41:05 +0100374 LOG_DEBUG("Response Received: ");
375 LOG_DEBUG("from socket #0x%x:",
Philip Triccaa003d762017-10-17 13:25:42 -0700376 tcti_intel->tpmSock);
Will-nuce0d3ec22015-12-09 15:09:49 -0500377 }
Philip Triccadfa41a52016-07-20 17:43:57 -0700378
Philip Triccaa003d762017-10-17 13:25:42 -0700379 if (tcti_intel->status.tagReceived == 1) {
Andreas Fuchsbe5899d2017-11-13 17:14:36 +0100380 *(TPM2_ST *)response_buffer = tcti_intel->tag;
381 responseSizeDelta += sizeof (TPM2_ST);
382 response_buffer += sizeof (TPM2_ST);
wcarthur74a92a42015-12-07 16:02:12 -0500383 }
384
Philip Triccaa003d762017-10-17 13:25:42 -0700385 if (tcti_intel->status.responseSizeReceived == 1) {
Andreas Fuchsbe5899d2017-11-13 17:14:36 +0100386 *(TPM2_RC *)response_buffer = HOST_TO_BE_32 (tcti_intel->responseSize);
387 responseSizeDelta += sizeof (TPM2_RC);
388 response_buffer += sizeof (TPM2_RC);
wcarthur74a92a42015-12-07 16:02:12 -0500389 }
390
Philip Triccaa003d762017-10-17 13:25:42 -0700391 /* Receive the TPM response. */
Philip Tricca77042de2018-03-05 15:14:04 -0800392 iResult = socket_recv_buf (tcti_intel->tpmSock,
393 (unsigned char *)response_buffer,
394 tcti_intel->responseSize - responseSizeDelta);
395 if (iResult < 0) {
396 rval = TSS2_TCTI_RC_IO_ERROR;
wcarthur74a92a42015-12-07 16:02:12 -0500397 goto retSocketReceiveTpmResponse;
Philip Triccaa003d762017-10-17 13:25:42 -0700398 }
Andreas Fuchs43a0d762017-11-30 15:41:05 +0100399 LOGBLOB_DEBUG(response_buffer, tcti_intel->responseSize,
400 "Received response buffer=");
wcarthur0651af22015-11-25 15:01:22 -0500401
Philip Triccaa003d762017-10-17 13:25:42 -0700402 /* Receive the appended four bytes of 0's */
Philip Tricca77042de2018-03-05 15:14:04 -0800403 iResult = socket_recv_buf (tcti_intel->tpmSock,
404 (unsigned char *)&trash,
405 4);
406 if (iResult != 4) {
407 rval = TSS2_TCTI_RC_IO_ERROR;
wcarthur74a92a42015-12-07 16:02:12 -0500408 goto retSocketReceiveTpmResponse;
Philip Triccaa003d762017-10-17 13:25:42 -0700409 }
Will Arthur54e04e42015-07-15 11:29:25 -0400410 }
411
Philip Triccaa003d762017-10-17 13:25:42 -0700412 if (tcti_intel->responseSize < *response_size) {
Philip Tricca24f555c2017-10-13 17:51:53 -0700413 *response_size = tcti_intel->responseSize;
Will Arthur54e04e42015-07-15 11:29:25 -0400414 }
Philip Triccadfa41a52016-07-20 17:43:57 -0700415
Philip Tricca24f555c2017-10-13 17:51:53 -0700416 tcti_intel->status.commandSent = 0;
Will Arthur54e04e42015-07-15 11:29:25 -0400417
Philip Triccaa003d762017-10-17 13:25:42 -0700418 /* Turn cancel off. */
419 if (rval == TSS2_RC_SUCCESS) {
420 rval = PlatformCommand (tctiContext, MS_SIM_CANCEL_OFF);
421 } else {
422 /* Ignore return value so earlier error code is preserved. */
423 PlatformCommand (tctiContext, MS_SIM_CANCEL_OFF);
wcarthur2efe2912015-11-16 11:19:42 -0500424 }
Will Arthur54e04e42015-07-15 11:29:25 -0400425
Will Arthur54e04e42015-07-15 11:29:25 -0400426retSocketReceiveTpmResponse:
Philip Triccaa003d762017-10-17 13:25:42 -0700427 if (rval == TSS2_RC_SUCCESS && response_buffer != NULL) {
Philip Tricca24f555c2017-10-13 17:51:53 -0700428 tcti_intel->previousStage = TCTI_STAGE_RECEIVE_RESPONSE;
wcarthureedecd62015-11-20 16:59:45 -0500429 }
Philip Triccadfa41a52016-07-20 17:43:57 -0700430
Will Arthur54e04e42015-07-15 11:29:25 -0400431 return rval;
432}
433
Philip Tricca40e926d2016-09-22 20:37:28 -0700434/**
435 * This function sends the Microsoft simulator the MS_SIM_POWER_ON and
436 * MS_SIM_NV_ON commands using the PlatformCommand mechanism. Without
437 * these the simulator will respond with zero sized buffer which causes
438 * the TSS to freak out. Sending this command more than once is harmelss
439 * so it's advisable to call this function as part of the TCTI context
440 * initialization just to be sure.
441 *
442 * NOTE: The caller will still need to call Tss2_Sys_Startup. If they
443 * don't, an error will be returned from each call till they do but
Andreas Fuchsbe5899d2017-11-13 17:14:36 +0100444 * the error will at least be meaningful (TPM2_RC_INITIALIZE).
Philip Tricca40e926d2016-09-22 20:37:28 -0700445 */
Philip Triccadc4ff842018-03-04 21:59:48 -0800446static TSS2_RC
447simulator_setup (
448 TSS2_TCTI_CONTEXT *tctiContext)
Philip Tricca40e926d2016-09-22 20:37:28 -0700449{
Philip Tricca40e926d2016-09-22 20:37:28 -0700450 TSS2_RC rval;
451
Philip Triccadc4ff842018-03-04 21:59:48 -0800452 LOG_TRACE ("Initializing TCTI context 0x%" PRIxPTR,
453 (uintptr_t)tctiContext);
Philip Triccaa003d762017-10-17 13:25:42 -0700454 rval = PlatformCommand (tctiContext ,MS_SIM_POWER_ON);
455 if (rval != TSS2_RC_SUCCESS) {
Philip Triccadc4ff842018-03-04 21:59:48 -0800456 LOG_WARNING ("Failed to send MS_SIM_POWER_ON platform command.");
Philip Tricca40e926d2016-09-22 20:37:28 -0700457 return rval;
458 }
Philip Triccaa003d762017-10-17 13:25:42 -0700459
460 rval = PlatformCommand (tctiContext, MS_SIM_NV_ON);
461 if (rval != TSS2_RC_SUCCESS) {
Philip Triccadc4ff842018-03-04 21:59:48 -0800462 LOG_WARNING ("Failed to send MS_SIM_NV_ON platform command.");
Philip Triccaa003d762017-10-17 13:25:42 -0700463 }
Philip Tricca40e926d2016-09-22 20:37:28 -0700464
465 return rval;
466}
467
Philip Tricca77683c72017-12-04 16:05:52 -0800468/*
469 * This is a utility function to extract a TCP port number from a string.
470 * The string must be 6 characters long. If the supplied string contains an
471 * invalid port number then 0 is returned.
472 */
473static uint16_t
474string_to_port (char port_str[6])
475{
476 uint32_t port = 0;
477
478 if (sscanf (port_str, "%" SCNu32, &port) == EOF || port > UINT16_MAX) {
479 return 0;
480 }
481 return port;
482}
Philip Triccac21dbf32018-03-03 09:07:48 -0800483/*
484 * This function extracts the hostname and port part of the provided conf
485 * string (which is really just a URI). The hostname parameter is an output
486 * buffer that must be large enough to hold the hostname. HOST_NAME_MAX is
487 * probably a good size. The 'port' parameter is an output parameter where
488 * we store the port from the URI after we convert it to a uint16.
489 * If the URI does not contain a port number then the contents of the 'port'
490 * parameter will not be changed.
491 * This function returns TSS2_RC_SUCCESS when the 'hostname' and 'port' have
492 * been populated successfully. On failure it will return
493 * TSS2_TCTI_RC_BAD_VALUE to indicate that the provided conf string contains
494 * values that we can't parse or are invalid.
495 */
496TSS2_RC
497conf_str_to_host_port (
498 const char *conf,
499 char *hostname,
500 uint16_t *port)
Philip Tricca77683c72017-12-04 16:05:52 -0800501{
Philip Tricca77683c72017-12-04 16:05:52 -0800502 UriParserStateA state;
503 UriUriA uri;
Philip Tricca77683c72017-12-04 16:05:52 -0800504 /* maximum 5 digits in uint16_t + 1 for \0 */
Philip Triccac21dbf32018-03-03 09:07:48 -0800505 char port_str[6] = { 0 };
506 size_t range;
507 TSS2_RC rc = TSS2_RC_SUCCESS;
Philip Tricca77683c72017-12-04 16:05:52 -0800508
509 state.uri = &uri;
Philip Triccac21dbf32018-03-03 09:07:48 -0800510 if (uriParseUriA (&state, conf) != URI_SUCCESS) {
511 LOG_WARNING ("Failed to parse provided conf string: %s", conf);
Philip Tricca77683c72017-12-04 16:05:52 -0800512 rc = TSS2_TCTI_RC_BAD_VALUE;
513 goto out;
514 }
515
516 /* extract host & domain name / fqdn */
517 range = uri.hostText.afterLast - uri.hostText.first;
518 if (range > HOST_NAME_MAX) {
Philip Triccac21dbf32018-03-03 09:07:48 -0800519 LOG_WARNING ("Provided conf string has hostname that exceeds "
520 "HOST_NAME_MAX.");
Philip Tricca77683c72017-12-04 16:05:52 -0800521 rc = TSS2_TCTI_RC_BAD_VALUE;
522 goto out;
523 }
524 strncpy (hostname, uri.hostText.first, range);
Philip Tricca77683c72017-12-04 16:05:52 -0800525
526 /* extract port number */
527 range = uri.portText.afterLast - uri.portText.first;
Philip Triccac21dbf32018-03-03 09:07:48 -0800528 if (range > 5) {
529 LOG_WARNING ("conf string contains invalid port.");
530 rc = TSS2_TCTI_RC_BAD_VALUE;
531 goto out;
Philip Tricca77683c72017-12-04 16:05:52 -0800532 } else if (range == 0) {
Philip Triccac21dbf32018-03-03 09:07:48 -0800533 LOG_INFO ("conf string does not contain a port.");
534 goto out;
535 }
536
537 strncpy (port_str, uri.portText.first, range);
538 *port = string_to_port (port_str);
539 if (*port == 0) {
540 LOG_WARNING ("Provided conf string contains invalid port: 0");
Philip Tricca77683c72017-12-04 16:05:52 -0800541 rc = TSS2_TCTI_RC_BAD_VALUE;
542 goto out;
543 }
Philip Tricca77683c72017-12-04 16:05:52 -0800544out:
545 uriFreeUriMembersA (&uri);
546 return rc;
547}
548
Philip Triccac21dbf32018-03-03 09:07:48 -0800549void
550tcti_socket_init_context_data (
551 TSS2_TCTI_CONTEXT *tcti_ctx)
552{
553 TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tcti_ctx);
554
555 TSS2_TCTI_MAGIC (tcti_ctx) = TCTI_MAGIC;
556 TSS2_TCTI_VERSION (tcti_ctx) = TCTI_VERSION;
557 TSS2_TCTI_TRANSMIT (tcti_ctx) = tcti_socket_transmit;
558 TSS2_TCTI_RECEIVE (tcti_ctx) = SocketReceiveTpmResponse;
559 TSS2_TCTI_FINALIZE (tcti_ctx) = SocketFinalize;
560 TSS2_TCTI_CANCEL (tcti_ctx) = SocketCancel;
561 TSS2_TCTI_GET_POLL_HANDLES (tcti_ctx) = SocketGetPollHandles;
562 TSS2_TCTI_SET_LOCALITY (tcti_ctx) = SocketSetLocality;
563 TSS2_TCTI_MAKE_STICKY (tcti_ctx) = tcti_make_sticky_not_implemented;
564 tcti_intel->status.locality = 3;
565 tcti_intel->status.commandSent = 0;
566 tcti_intel->status.tagReceived = 0;
567 tcti_intel->status.responseSizeReceived = 0;
568 tcti_intel->status.protocolResponseSizeReceived = 0;
569 tcti_intel->currentTctiContext = 0;
570 tcti_intel->previousStage = TCTI_STAGE_INITIALIZE;
571}
572/*
573 * This is an implementation of the standard TCTI initialization function for
574 * this module.
575 */
576TSS2_RC
577Tss2_Tcti_Socket_Init (
578 TSS2_TCTI_CONTEXT *tctiContext,
579 size_t *size,
580 const char *conf)
581{
582 TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
583 TSS2_RC rc;
Philip Tricca2bec2a82018-03-04 21:27:30 -0800584 SOCKET *tpmSock, *otherSock = NULL;
Philip Triccac21dbf32018-03-03 09:07:48 -0800585 const char *uri_str = conf != NULL ? conf : TCTI_SOCKET_DEFAULT_CONF;
586 char hostname[HOST_NAME_MAX + 1] = { 0 };
587 uint16_t port = TCTI_SOCKET_DEFAULT_PORT;
588
589 if (tctiContext == NULL && size == NULL) {
590 return TSS2_TCTI_RC_BAD_VALUE;
591 } else if( tctiContext == NULL ) {
592 *size = sizeof (TSS2_TCTI_CONTEXT_INTEL);
593 return TSS2_RC_SUCCESS;
594 } else if( conf == NULL ) {
595 return TSS2_TCTI_RC_BAD_VALUE;
596 }
597
598 rc = conf_str_to_host_port (uri_str, hostname, &port);
599 if (rc != TSS2_RC_SUCCESS) {
600 return rc;
601 }
602
Philip Tricca2bec2a82018-03-04 21:27:30 -0800603 tpmSock = &tcti_intel->tpmSock;
604 otherSock = &tcti_intel->otherSock;
605
606 rc = socket_connect (hostname, port, tpmSock);
Philip Triccac21dbf32018-03-03 09:07:48 -0800607 if (rc != TSS2_RC_SUCCESS) {
Philip Tricca2bec2a82018-03-04 21:27:30 -0800608 return rc;
609 }
610
611 rc = socket_connect (hostname, port + 1, otherSock);
612 if (rc != TSS2_RC_SUCCESS) {
613 goto fail_out;
Philip Triccac21dbf32018-03-03 09:07:48 -0800614 }
615
Philip Triccadc4ff842018-03-04 21:59:48 -0800616 rc = simulator_setup (tctiContext);
Philip Triccac21dbf32018-03-03 09:07:48 -0800617 if (rc != TSS2_RC_SUCCESS) {
Philip Tricca2bec2a82018-03-04 21:27:30 -0800618 goto fail_out;
Philip Triccac21dbf32018-03-03 09:07:48 -0800619 }
620
621 tcti_socket_init_context_data (tctiContext);
Philip Tricca2bec2a82018-03-04 21:27:30 -0800622
623 return TSS2_RC_SUCCESS;
624
625fail_out:
Philip Tricca01b9a1e2018-03-04 21:47:58 -0800626 socket_close (tpmSock);
627 socket_close (otherSock);
Philip Tricca2bec2a82018-03-04 21:27:30 -0800628
629 return TSS2_TCTI_RC_IO_ERROR;
Philip Triccac21dbf32018-03-03 09:07:48 -0800630}
631
Philip Tricca77683c72017-12-04 16:05:52 -0800632/* public info structure */
633const static TSS2_TCTI_INFO tss2_tcti_info = {
Philip Triccadc11b4f2018-02-23 18:21:48 -0800634 .version = {
635 .magic = TCTI_MAGIC,
636 .version = TCTI_VERSION,
637 },
Philip Tricca77683c72017-12-04 16:05:52 -0800638 .name = "tcti-socket",
639 .description = "TCTI module for communication with the Microsoft TPM2 Simulator.",
Philip Tricca7362c442018-01-08 18:22:36 -0800640 .config_help = "Connection URI in the form tcp://ip_address[:port]. " \
641 "Default is: TCTI_SOCKET_DEFAULT.",
Philip Tricca77683c72017-12-04 16:05:52 -0800642 .init = Tss2_Tcti_Socket_Init,
643};
644
645const TSS2_TCTI_INFO*
646Tss2_Tcti_Info (void)
647{
648 return &tss2_tcti_info;
649}