aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tpmproxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tpmproxy.c')
-rw-r--r--roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tpmproxy.c972
1 files changed, 972 insertions, 0 deletions
diff --git a/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tpmproxy.c b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tpmproxy.c
new file mode 100644
index 000000000..740c926fa
--- /dev/null
+++ b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/tpmproxy.c
@@ -0,0 +1,972 @@
+/********************************************************************************/
+/* */
+/* Windows 10 TPM Proxy */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* */
+/* (c) Copyright IBM Corporation 2006 - 2019. */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following conditions are */
+/* met: */
+/* */
+/* Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the following disclaimer. */
+/* */
+/* Redistributions in binary form must reproduce the above copyright */
+/* notice, this list of conditions and the following disclaimer in the */
+/* documentation and/or other materials provided with the distribution. */
+/* */
+/* Neither the names of the IBM Corporation nor the names of its */
+/* contributors may be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
+/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
+/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
+/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
+/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
+/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
+/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
+/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
+/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/********************************************************************************/
+
+
+/*
+ Use this proxy when using the TSS command line utilities on Windows. It keeps the connection to
+ the Windows TPM device driver open. This prevents its resource manager from flushing resources
+ after each utiity exits.
+
+ The server type (mssim or raw) should agree with the TSS configuration. mssim wrapes the packets
+ in the MS simulator bytes. raw does not.
+
+ The proxy is unnecessary when using a compiled application.
+
+ Link with:
+
+ tbs.lib
+ ws2_32.lib
+*/
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+
+#include <windows.h>
+#include <specstrings.h>
+
+#include <tbs.h>
+
+#define LOAD32(buffer,offset) ( ntohl(*(uint32_t *)&(buffer)[(offset)]) )
+
+#ifndef SSIZE_MAX
+#define SSIZE_MAX INT_MAX
+#endif
+
+/* standard TCG definitions */
+
+typedef unsigned long TSS_RESULT;
+typedef unsigned char BYTE;
+typedef unsigned short TPM_TAG;
+
+/* local constants */
+
+#define ERROR_CODE -1
+#define DEFAULT_PORT 2321
+#define PACKET_SIZE 4096
+#define TRACE_SIZE (PACKET_SIZE * 4)
+
+#define SERVER_TYPE_MSSIM 0
+#define SERVER_TYPE_RAW 1
+#define TPM_SEND_COMMAND 8 /* simulator command preamble */
+
+/* local prototypes */
+
+void printUsage(void);
+long getArgs(short *port,
+ int *verbose,
+ char **logFileName,
+ int argc,
+ char **argv);
+void logAll(const char *message, unsigned long length, const unsigned char* buff);
+
+TSS_RESULT socketInit(SOCKET *sock_fd, short port);
+TSS_RESULT socketConnect(SOCKET *accept_fd,
+ SOCKET sock_fd,
+ short port);
+TSS_RESULT socketRead(SOCKET accept_fd,
+ char *buffer,
+ uint32_t *bufferLength,
+ size_t bufferSize);
+TSS_RESULT socketReadBytes(SOCKET accept_fd,
+ char *buffer,
+ size_t nbytes);
+TSS_RESULT socketWrite(SOCKET accept_fd,
+ const char *buffer,
+ size_t buffer_length);
+TSS_RESULT socketDisconnect(SOCKET accept_fd);
+
+void TPM_HandleWsaStartupError(const char *prefix,
+ int irc);
+void TPM_HandleWsaError(const char *prefix);
+void TPM_GetWsaStartupError(int status,
+ const char **error_string);
+void TPM_GetWsaError(const char **error_string);
+
+void TPM_GetTBSError(const char *prefix,
+ TBS_RESULT rc);
+void CheckTPMError(const char *prefix,
+ unsigned char *response);
+
+/* global variable for trace logging */
+
+int verbose; /* verbose debug tracing */
+char *logFilename; /* trace log file name */
+char logMsg[TRACE_SIZE]; /* since it's big, put it here rather than on the stack */
+
+/* global socket server format type */
+
+int serverType = SERVER_TYPE_MSSIM; /* default MS simulator format */
+
+#define false 0
+#define true 1
+
+int main(int argc, char** argv)
+{
+ TBS_RESULT rc = 0;
+ TBS_RESULT rc1 = 0;
+ time_t start_time;
+ int contextOpened = false;
+ SOCKET sock_fd; /* server socket */
+ SOCKET accept_fd; /* server accept socket for a packet */
+ int socketOpened = FALSE;
+
+ TBS_HCONTEXT hContext = 0;
+ TBS_CONTEXT_PARAMS2 contextParams;
+
+ /* TPM command and response */
+ BYTE command[PACKET_SIZE];
+ uint32_t commandLength;
+ BYTE response[PACKET_SIZE];
+ uint32_t responseLength;
+
+ /* command line arguments */
+ short port; /* TCPIP server port */
+
+ /* command line argument defaults */
+ port = DEFAULT_PORT;
+ logFilename = NULL;
+ verbose = FALSE;
+
+ /* initialization */
+ setvbuf(stdout, 0, _IONBF, 0); /* output may be going through pipe */
+ start_time = time(NULL);
+
+ /* get command line arguments */
+ if (rc == 0) {
+ rc = getArgs(&port, &verbose, &logFilename,
+ argc, argv);
+ }
+ /* open HW TPM device driver */
+ if (rc == 0) {
+ if (verbose) printf("tpmproxy: start at %s", ctime(&start_time));
+ if (verbose) printf("tpmproxy: server type %s\n",
+ (serverType == SERVER_TYPE_MSSIM) ? "MS simulator" : "raw");
+ contextParams.version = TBS_CONTEXT_VERSION_TWO;
+ contextParams.includeTpm12 = 0;
+ contextParams.includeTpm20 = 1;
+ rc = Tbsi_Context_Create((TBS_CONTEXT_PARAMS *)&contextParams,
+ &hContext);
+
+ if (verbose) printf("tpmproxy: Tbsi_Context_Create rc %08x\n", rc);
+ if (rc == 0) {
+ contextOpened = true;
+ }
+ else {
+ TPM_GetTBSError("Tbsi_Context_Create ", rc);
+ }
+ }
+ /* open / initialize server socket */
+ if (rc == 0) {
+ if (verbose) printf("Opening socket at port %hu\n", port);
+ rc = socketInit(&sock_fd, port);
+ if (rc != 0) {
+ printf("tpmproxy: socket open failed\n");
+ }
+ else {
+ socketOpened = TRUE;
+ }
+ }
+ /* main loop */
+ while (rc == 0) {
+ /* connect to the client application */
+ if (rc == 0) {
+ if (verbose) printf("Connecting on socket %hu\n", port);
+ rc = socketConnect(&accept_fd, sock_fd, port);
+ }
+ /* read a command from client */
+ if (rc == 0) {
+ rc = socketRead(accept_fd,
+ (char *)command, /* windows wants signed */
+ &commandLength,
+ sizeof(command));
+ logAll("Command", commandLength, command);
+ }
+ /* send command to TPM and receive response */
+ if (rc == 0) {
+ responseLength = sizeof(response);
+ rc = Tbsip_Submit_Command(hContext,
+ TBS_COMMAND_LOCALITY_ZERO,
+ TBS_COMMAND_PRIORITY_NORMAL,
+ command,
+ commandLength,
+ response,
+ &responseLength);
+ if (rc != 0) {
+ TPM_GetTBSError("Tbsi_Context_Create ", rc);
+ }
+ }
+ /* send response to client */
+ if (rc == 0) {
+ logAll("Response", responseLength, response);
+ rc = socketWrite(accept_fd,
+ (char *)response, /* windows wants signed char */
+ responseLength);
+ }
+ /* disconnect from client */
+ if (rc == 0) {
+ rc = socketDisconnect(accept_fd);
+ }
+ }
+ /* close socket */
+ if (socketOpened) {
+ socketDisconnect(sock_fd);
+ }
+ /* close TPM */
+ if (contextOpened) {
+ rc1 = Tbsip_Context_Close(hContext);
+ if (verbose) printf("tpmproxy:Tbsip_Context_Close rc1 %08x\n", rc1);
+ if (rc == 0) {
+ rc = rc1;
+ }
+ }
+ if (verbose) printf("tpmproxy: exit rc %08x\n", rc);
+ return rc;
+}
+
+/*
+ All the socket code is basically a cut and paste from the TPM 1.2 tpm_io.c
+*/
+
+TSS_RESULT socketInit(SOCKET *sock_fd, short port)
+{
+ TSS_RESULT rc = 0;
+ int irc;
+ struct sockaddr_in serv_addr;
+ int opt;
+ WSADATA wsaData;
+
+ /* initiate use of the Windows Sockets DLL 2.0 */
+ if (rc == 0) {
+ if ((irc = WSAStartup(0x202,&wsaData)) != 0) { /* if not successful */
+ printf("socketInit: Error, WSAStartup()\n");
+ TPM_HandleWsaStartupError("socketInit:", irc);
+ rc = ERROR_CODE;
+ }
+ }
+ /* create a tcpip protocol socket */
+ if (rc == 0) {
+ /* if (verbose) printf(" socketInit: Port %hu\n", port); */
+ *sock_fd = socket(AF_INET, SOCK_STREAM, 0); /* tcpip socket */
+ if (*sock_fd == INVALID_SOCKET) {
+ printf("socketInit: Error, server socket()\n");
+ TPM_HandleWsaError("socketInit:");
+ rc = ERROR_CODE;
+ }
+ }
+ if (rc == 0) {
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET; /* Internet socket */
+ serv_addr.sin_port = htons(port); /* host to network byte order for short */
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* host to network byte order for long */
+ opt = 1;
+ /* Set SO_REUSEADDR before calling bind() for servers that bind to a fixed port number. */
+ /* For boolean values, opt must be an int, but the setsockopt prototype is IMHO wrong.
+ It should take void *, but uses char *. Hence the type cast. */
+ irc = setsockopt(*sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
+ if (irc == SOCKET_ERROR) {
+ printf("socketInit: Error, server setsockopt()\n");
+ TPM_HandleWsaError("socketInit:");
+ closesocket(*sock_fd);
+ rc = ERROR_CODE;
+ }
+ }
+ /* bind the (local) server port name to the socket */
+ if (rc == 0) {
+ irc = bind(*sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
+ if (irc == SOCKET_ERROR) {
+ printf("socketInit: Error, server bind()\n");
+ printf("socketInit: Is SW TPM listening on this port?\n");
+ TPM_HandleWsaError("socketInit:");
+ closesocket(*sock_fd);
+ rc = ERROR_CODE;
+ }
+ }
+ /* listen for a connection to the socket */
+ if (rc == 0) {
+ irc = listen(*sock_fd, SOMAXCONN);
+ if (irc == SOCKET_ERROR) {
+ printf("socketInit: Error, server listen()\n");
+ TPM_HandleWsaError("socketInit:");
+ closesocket(*sock_fd);
+ rc = ERROR_CODE;
+ }
+ }
+ if (rc != 0) {
+ WSACleanup();
+ }
+ return rc;
+}
+
+TSS_RESULT socketConnect(SOCKET *accept_fd,
+ SOCKET sock_fd,
+ short port)
+{
+ TSS_RESULT rc = 0;
+ int cli_len;
+ struct sockaddr_in cli_addr; /* Internet version of sockaddr */
+
+ /* accept a connection */
+ if (rc == 0) {
+ cli_len = sizeof(cli_addr);
+ /* block until connection from client */
+ /* printf(" socketConnect: Waiting for connection on port %hu ...\n", port); */
+ *accept_fd = accept(sock_fd, (struct sockaddr *)&cli_addr, &cli_len);
+ if (*accept_fd == SOCKET_ERROR) {
+ printf("socketConnect: Error, accept()\n");
+ TPM_HandleWsaError("socketConnect: ");
+ closesocket(sock_fd);
+ WSACleanup();
+ rc = ERROR_CODE;
+ }
+ }
+ return rc;
+}
+
+/* socketRead() reads a TPM command packet from the host
+
+ Puts the result in 'buffer' up to 'bufferSize' bytes.
+
+ On success, the number of bytes in the buffer is equal to 'bufferLength' bytes
+
+ This function is intended to be platform independent.
+*/
+
+TSS_RESULT socketRead(SOCKET accept_fd, /* read/write file descriptor */
+ char *buffer, /* output: command stream */
+ uint32_t *bufferLength, /* output: command stream length */
+ size_t bufferSize) /* input: max size of output buffer */
+{
+ TSS_RESULT rc = 0;
+ uint32_t headerSize; /* minimum required bytes in command through paramSize */
+ uint32_t paramSize; /* from command stream */
+ uint32_t commandTypeNbo; /* MS simulator format preamble */
+ uint32_t commandType; /* MS simulator format preamble */
+ uint8_t locality; /* MS simulator format preamble */
+ uint32_t lengthNbo; /* MS simulator format preamble */
+
+ /* if the MS simulator packet format */
+ if (serverType == SERVER_TYPE_MSSIM) {
+ /* read and check the command */
+ if (rc == 0) {
+ rc = socketReadBytes(accept_fd, (char *)&commandTypeNbo, sizeof(uint32_t));
+ }
+ if (rc == 0) {
+ commandType = LOAD32(&commandTypeNbo, 0);
+ if (commandType != TPM_SEND_COMMAND) {
+ printf("socketRead: Error, -mssim preamble is %08x not %08x\n",
+ commandType,TPM_SEND_COMMAND);
+ rc = ERROR_CODE;
+ }
+ }
+ /* read and discard the locality */
+ if (rc == 0) {
+ rc = socketReadBytes(accept_fd, &locality, sizeof(uint8_t));
+ }
+ /* read and discard the redundant length */
+ if (rc == 0) {
+ rc = socketReadBytes(accept_fd, (char *)&lengthNbo, sizeof(uint32_t));
+ }
+ }
+ /* check that the buffer can at least fit the command through the paramSize */
+ if (rc == 0) {
+ headerSize = sizeof(TPM_TAG) + sizeof(uint32_t);
+ if (bufferSize < headerSize) {
+ printf("socketRead: Error, buffer size %u less than minimum %u\n",
+ bufferSize, headerSize);
+ rc = ERROR_CODE;
+ }
+ }
+ /* read the command through the paramSize from the socket stream */
+ if (rc == 0) {
+ rc = socketReadBytes(accept_fd, buffer, headerSize);
+ }
+ if (rc == 0) {
+ /* extract the paramSize value, last field in header */
+ paramSize = LOAD32(buffer, headerSize - sizeof(uint32_t));
+ *bufferLength = headerSize + paramSize - (sizeof(TPM_TAG) + sizeof(uint32_t));
+ if (bufferSize < *bufferLength) {
+ printf("socketRead: Error, buffer size %u is less than required %u\n",
+ bufferSize, *bufferLength);
+ rc = ERROR_CODE;
+ }
+ }
+ /* read the rest of the command (already read tag and paramSize) */
+ if (rc == 0) {
+ rc = socketReadBytes(accept_fd,
+ buffer + headerSize,
+ paramSize - (sizeof(TPM_TAG) + sizeof(uint32_t)));
+ }
+ return rc;
+}
+
+/* socketReadBytes() reads nbytes from accept_fd and puts them in buffer.
+
+ The buffer has already been checked for sufficient size.
+*/
+
+TSS_RESULT socketReadBytes(SOCKET accept_fd, /* read/write file descriptor */
+ char *buffer,
+ size_t nbytes)
+{
+ TSS_RESULT rc = 0;
+ int nread = 0;
+ size_t nleft = nbytes;
+
+ /* read() is unspecified with nbytes too large */
+ if (rc == 0) {
+ if (nleft > SSIZE_MAX) {
+ rc = ERROR_CODE;
+ }
+ }
+ while ((rc == 0) && (nleft > 0)) {
+ nread = recv(accept_fd, buffer, nleft, 0);
+ if ((nread == SOCKET_ERROR) ||
+ (nread < 0)) { /* error */
+ printf("socketReadBytes: Error, read() error\n");
+ TPM_HandleWsaError("socketReadBytes:");
+ socketDisconnect(accept_fd);
+ rc = ERROR_CODE;
+ }
+ else if (nread > 0) {
+ nleft -= nread;
+ buffer += nread;
+ }
+ else if (nread == 0) { /* EOF */
+ printf("socketReadBytes: Error, read EOF, read %u bytes\n", nbytes - nleft);
+ rc = ERROR_CODE;
+ }
+ }
+ return rc;
+}
+
+/* socketWrite() writes buffer_length bytes from buffer to accept_fd.
+
+ In mmssim mode, it prepends the size and appends the acknowledgement.
+ */
+
+TSS_RESULT socketWrite(SOCKET accept_fd, /* read/write file descriptor */
+ const char *buffer,
+ size_t buffer_length)
+{
+ TSS_RESULT rc = 0;
+ int nwritten = 0;
+
+ /* write() is unspecified with buffer_length too large */
+ if (rc == 0) {
+ if (buffer_length > SSIZE_MAX) {
+ rc = ERROR_CODE;
+ }
+ }
+ /* if the MS simulator packet format */
+ if (serverType == SERVER_TYPE_MSSIM) {
+ /* prepend the leading size */
+ if (rc == 0) {
+ uint32_t bufferLengthNbo = htonl(buffer_length);
+ send(accept_fd, (const char *)&bufferLengthNbo, sizeof(uint32_t), 0);
+ }
+ }
+ /* test that connection is open to write */
+ if (rc == 0) {
+ if (accept_fd == SOCKET_ERROR) {
+ printf("socketWrite: Error, connection not open, fd %d\n",
+ accept_fd);
+ rc = ERROR_CODE;
+ }
+ }
+ while ((rc == 0) && (buffer_length > 0)) {
+ nwritten = send(accept_fd, buffer, buffer_length, 0);
+ if ((nwritten == SOCKET_ERROR) ||
+ (nwritten < 0)) {
+ printf("socketWrite: Error, send()\n");
+ TPM_HandleWsaError("socketWrite:"); /* report the error */
+ socketDisconnect(accept_fd);
+ rc = ERROR_CODE;
+ }
+ else {
+ buffer_length -= nwritten;
+ buffer += nwritten;
+ }
+ }
+ /* if the MS simulator packet format */
+ if (serverType == SERVER_TYPE_MSSIM) {
+ /* append the trailing acknowledgement */
+ if (rc == 0) {
+ uint32_t acknowledgement = 0;
+ send(accept_fd, (const char *)&acknowledgement, sizeof(uint32_t), 0);
+ }
+ }
+ return rc;
+}
+
+/* socketDisconnect() breaks the connection between the TPM server and the host client
+
+ This is the Windows platform dependent socket version.
+*/
+
+TSS_RESULT socketDisconnect(SOCKET accept_fd)
+{
+ TSS_RESULT rc = 0;
+ int irc;
+
+ /* close the connection to the client */
+ if (verbose) printf("Closing socket\n");
+ if (rc == 0) {
+ irc = closesocket(accept_fd);
+ accept_fd = SOCKET_ERROR; /* mark the connection closed */
+ if (irc == SOCKET_ERROR) {
+ printf("socketDisconnect: Error, closesocket()\n");
+ rc = ERROR_CODE;
+ }
+ }
+ return rc;
+}
+
+void TPM_HandleWsaStartupError(const char *prefix,
+ int irc)
+{
+ const char *error_string;
+
+ TPM_GetWsaStartupError(irc, &error_string);
+ printf("%s %s\n", prefix, error_string);
+ return;
+}
+
+void TPM_HandleWsaError(const char *prefix)
+{
+ const char *error_string;
+
+ TPM_GetWsaError(&error_string);
+ printf("%s %s\n", prefix, error_string);
+ return;
+}
+
+void TPM_GetWsaStartupError(int status,
+ const char **error_string)
+{
+ /* convert WSAStartup status to more useful text. Copy the text to error_string */
+
+ switch(status) {
+ case WSASYSNOTREADY:
+ *error_string = "WSAStartup error: WSASYSNOTREADY underlying network subsystem not ready for "
+ "network communication";
+ break;
+ case WSAVERNOTSUPPORTED:
+ *error_string = "WSAStartup error: WSAVERNOTSUPPORTED version requested not provided by WinSock "
+ "implementation";
+ break;
+ case WSAEINPROGRESS:
+ *error_string = "WSAStartup error: WSAEINPROGRESS blocking WinSock 1.1 operation in progress";
+ break;
+ case WSAEPROCLIM:
+ *error_string = "WSAStartup error: WSAEPROCLIM Limit on number of tasks supported by WinSock "
+ "implementation has been reached";
+ break;
+ case WSAEFAULT:
+ *error_string = "WSAStartup error: WSAEFAULT lpWSAData is not a valid pointer";
+ break;
+ default:
+ *error_string = "WSAStartup error: return code unknown";
+ break;
+ }
+ return;
+}
+
+void TPM_GetWsaError(const char **error_string)
+{
+ /* Use WSAGetLastError, and convert the resulting number
+ to more useful text. Copy the text to error_string */
+
+ int error;
+
+ error = WSAGetLastError();
+ switch(error) {
+
+ case WSANOTINITIALISED :
+ *error_string = "A successful WSAStartup must occur before using this function";
+ break;
+ case WSAENETDOWN :
+ *error_string = "The network subsystem or the associated service provider has failed";
+ break;
+ case WSAEAFNOSUPPORT :
+ *error_string = "The specified address family is not supported";
+ break;
+ case WSAEINPROGRESS :
+ *error_string = "A blocking Windows Sockets 1.1 call is in progress, "
+ "or the service provider is still processing a callback function";
+ break;
+ case WSAEMFILE:
+ *error_string = "No more socket descriptors are available";
+ break;
+ case WSAENOBUFS:
+ *error_string = "No buffer space is available";
+ break;
+ case WSAEPROTONOSUPPORT:
+ *error_string = "The specified protocol is not supported";
+ break;
+ case WSAEPROTOTYPE:
+ *error_string = "The specified protocol is the wrong type for this socket";
+ break;
+ case WSAESOCKTNOSUPPORT :
+ *error_string = "The specified socket type is not supported in this address family";
+ break;
+ case WSAEFAULT:
+ *error_string = "A parameter is too small, bad format, or bad value";
+ break;
+ case WSAEINVAL:
+ *error_string = "The socket has not been bound with bind, or listen not called";
+ break;
+ case WSAENETRESET:
+ *error_string = "The connection has been broken due to the remote host resetting";
+ break;
+ case WSAENOPROTOOPT:
+ *error_string = "The option is unknown or unsupported for the specified provider";
+ break;
+ case WSAENOTCONN:
+ *error_string = "Connection has been reset when SO_KEEPALIVE is set";
+ break;
+ case WSAENOTSOCK:
+ *error_string = "The descriptor is not a socket";
+ break;
+ case WSAEADDRINUSE:
+ *error_string = "The specified address is already in use";
+ break;
+ case WSAEISCONN:
+ *error_string = "The socket is already connected";
+ break;
+ case WSAEOPNOTSUPP:
+ *error_string = "The referenced socket is not of a type that supports the operation";
+ break;
+ case WSAEINTR:
+ *error_string = "The (blocking) call was canceled through WSACancelBlockingCall";
+ case WSAEWOULDBLOCK:
+ *error_string = "The socket is marked as nonblocking and no connections are present to be accepted";
+ break;
+ case WSAESHUTDOWN:
+ *error_string = "The socket has been shut down; it is not possible to recv or send on a socket "
+ "after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH";
+ break;
+ case WSAEMSGSIZE:
+ *error_string = "The message was too large to fit into the specified buffer and was truncated";
+ break;
+ case WSAECONNABORTED:
+ *error_string = "The virtual circuit was terminated due to a time-out or other failure. "
+ "The application should close the socket as it is no longer usable";
+ break;
+ case WSAETIMEDOUT:
+ *error_string = "The connection has been dropped because of a network failure or because "
+ "the peer system failed to respond";
+ break;
+ case WSAECONNRESET:
+ *error_string = "The virtual circuit was reset by the remote side executing a hard or abortive close. "
+ "The application should close the socket as it is no longer usable. On a UDP datagram "
+ "socket this error would indicate that a previous send operation resulted in an ICMP "
+ "Port Unreachable message";
+ break;
+ case WSAEACCES:
+ *error_string = "The requested address is a broadcast address, but the appropriate flag was not set";
+ break;
+ case WSAEHOSTUNREACH:
+ *error_string = "The remote host cannot be reached from this host at this time";
+ break;
+
+ default:
+ *error_string = "unknown error type\n";
+ break;
+ }
+ return;
+}
+
+void TPM_GetTBSError(const char *prefix,
+ TBS_RESULT rc)
+{
+ const char *error_string;
+
+ switch (rc) {
+
+ /* error codes from the TBS html docs */
+ case TBS_SUCCESS:
+ error_string = "The function succeeded.";
+ break;
+ case TBS_E_INTERNAL_ERROR:
+ error_string = "An internal software error occurred.";
+ break;
+ case TBS_E_BAD_PARAMETER:
+ error_string = "One or more parameter values are not valid.";
+ break;
+ case TBS_E_INVALID_OUTPUT_POINTER:
+ error_string = "A specified output pointer is bad.";
+ break;
+ case TBS_E_INVALID_CONTEXT:
+ error_string = "The specified context handle does not refer to a valid context.";
+ break;
+ case TBS_E_INSUFFICIENT_BUFFER:
+ error_string = "The specified output buffer is too small.";
+ break;
+ case TBS_E_IOERROR:
+ error_string = "An error occurred while communicating with the TPM.";
+ break;
+ case TBS_E_INVALID_CONTEXT_PARAM:
+ error_string = "A context parameter that is not valid was passed when attempting to create a "
+ "TBS context.";
+ break;
+ case TBS_E_SERVICE_NOT_RUNNING:
+ error_string = "The TBS service is not running and could not be started.";
+ break;
+ case TBS_E_TOO_MANY_TBS_CONTEXTS:
+ error_string = "A new context could not be created because there are too many open contexts.";
+ break;
+ case TBS_E_TOO_MANY_RESOURCES:
+ error_string = "A new virtual resource could not be created because there are too many open "
+ "virtual resources.";
+ break;
+ case TBS_E_SERVICE_START_PENDING:
+ error_string = "The TBS service has been started but is not yet running.";
+ break;
+ case TBS_E_PPI_NOT_SUPPORTED:
+ error_string = "The physical presence interface is not supported.";
+ break;
+ case TBS_E_COMMAND_CANCELED:
+ error_string = "The command was canceled.";
+ break;
+ case TBS_E_BUFFER_TOO_LARGE:
+ error_string = "The input or output buffer is too large.";
+ break;
+ case TBS_E_TPM_NOT_FOUND:
+ error_string = "A compatible Trusted Platform Module (TPM) Security Device cannot be found "
+ "on this computer.";
+ break;
+ case TBS_E_SERVICE_DISABLED:
+ error_string = "The TBS service has been disabled.";
+ break;
+ case TBS_E_NO_EVENT_LOG:
+ error_string = "The TBS event log is not available.";
+ break;
+ case TBS_E_ACCESS_DENIED:
+ error_string = "The caller does not have the appropriate rights to perform the requested operation.";
+ break;
+ case TBS_E_PROVISIONING_NOT_ALLOWED:
+ error_string = "The TPM provisioning action is not allowed by the specified flags.";
+ break;
+ case TBS_E_PPI_FUNCTION_UNSUPPORTED:
+ error_string = "The Physical Presence Interface of this firmware does not support the "
+ "requested method.";
+ break;
+ case TBS_E_OWNERAUTH_NOT_FOUND:
+ error_string = "The requested TPM OwnerAuth value was not found.";
+ break;
+
+ /* a few error codes from WinError.h */
+ case TPM_E_COMMAND_BLOCKED:
+ error_string = "The command was blocked.";
+ break;
+
+ default:
+ error_string = "unknown error type\n";
+ break;
+
+
+ }
+ printf("%s %s\n", prefix, error_string);
+ return;
+}
+
+void CheckTPMError(const char *prefix,
+ unsigned char *response)
+{
+ const char *error_string;
+ uint32_t tpmError = htonl(*(uint32_t *)(response+6));
+
+ if (tpmError != 0) {
+
+ switch (tpmError) {
+ /* a few error codes from WinError.h */
+ case TPM_E_COMMAND_BLOCKED:
+ error_string = "The command was blocked.";
+ break;
+ default:
+ error_string = "unknown error type\n";
+ printf("TPM error %08x\n", tpmError);
+ break;
+ }
+ printf("%s %s\n", prefix, error_string);
+ }
+ return;
+}
+
+/* logging, tracing */
+
+void logAll(const char *message, unsigned long length, const unsigned char* buff)
+{
+ unsigned long i;
+ size_t nextChar = 0;
+ FILE *logFile; /* trace log file descriptor */
+
+ /* construct the log message, keep appending to the character string */
+ if (buff != NULL) {
+ nextChar += sprintf(logMsg + nextChar, "%s length %lu\n ", message, length);
+ for (i = 0 ; i < length ; i++) {
+ if (i && !( i % 16 )) {
+ nextChar += sprintf(logMsg + nextChar, "\n ");
+ }
+ nextChar += sprintf(logMsg + nextChar, "%.2X ",buff[i]);
+ }
+ nextChar += sprintf(logMsg + nextChar, "\n");
+ }
+ else {
+ nextChar += sprintf(logMsg + nextChar, "%s null\n", message);
+ }
+ if (verbose) printf("%s", logMsg);
+ if (logFilename != NULL) {
+ /* Open the log file if specified. It's a hack to keep opening and closing the file for
+ each append, but it's easier that trying to catch a signal to close the file. Windows
+ evidently doesn't automatically close the file when the program exits. */
+ logFile = fopen(logFilename, "a");
+ if (logFile == NULL) {
+ printf("Error, opening %s for write failed, %s\n",
+ logFilename, strerror(errno));
+ }
+ /* if success, print and close */
+ else {
+ fprintf(logFile, "%s", logMsg);
+ fclose(logFile);
+ }
+ }
+ return;
+}
+
+/* parse the command line arguments */
+
+long getArgs(short *port,
+ int *verbose,
+ char **logFilename,
+ int argc,
+ char **argv)
+{
+ long rc = 0;
+ int irc;
+ int i;
+ FILE *logFile; /* trace log file descriptor */
+
+ /* get the command line arguments */
+ for (i=1 ; (i<argc) && (rc == 0) ; i++) {
+ if ((strcmp(argv[i],"-p") == 0) ||
+ (strcmp(argv[i],"--port") == 0)) {
+ i++;
+ if (i < argc) {
+ irc = sscanf(argv[i], "%hu", port);
+ if (irc != 1) {
+ printf("-p --port (socket port) illegal value %s\n", argv[i]);
+ rc = ERROR_CODE;
+ }
+ } else {
+ printf("-p --port (socket port) needs a value\n");
+ rc = ERROR_CODE;
+ }
+ }
+ else if (strcmp(argv[i],"-raw") == 0) {
+ serverType = SERVER_TYPE_RAW;
+ }
+ else if (strcmp(argv[i],"-mssim") == 0) {
+ serverType = SERVER_TYPE_MSSIM;
+ }
+ else if (strcmp(argv[i],"-h") == 0) {
+ printUsage();
+ rc = ERROR_CODE;
+ }
+ else if ((strcmp(argv[i],"-v") == 0) ||
+ (strcmp(argv[i],"--verbose") == 0)) {
+ *verbose = TRUE;
+ }
+ else if ((strcmp(argv[i],"-l") == 0) ||
+ (strcmp(argv[i],"--log") == 0)) {
+ i++;
+ if (i < argc) {
+ if (strlen(argv[i]) < FILENAME_MAX) {
+ *logFilename = argv[i];
+ }
+ else {
+ printf("-l --log (log file name) too long\n");
+ rc = ERROR_CODE;
+ }
+ }
+ else {
+ printf("-l --log option (log file name) needs a value\n");
+ rc = ERROR_CODE;
+ }
+ }
+ else {
+ printf("\n%s is not a valid option\n",argv[i]);
+ printUsage();
+ rc = ERROR_CODE;
+ }
+ }
+ /* erase old contents of log file */
+ if ((rc == 0) && (*logFilename != NULL)) {
+ logFile = fopen(*logFilename, "w");
+ if (logFile == NULL) {
+ printf("Cannot open log file %s\n", *logFilename);
+ rc = ERROR_CODE;
+ }
+ else {
+ fclose(logFile);
+ }
+ }
+ return rc;
+}
+
+void printUsage()
+{
+ printf("\n");
+ printf("tpmproxy\n");
+ printf("\n");
+ printf("Pass through connecting a TCPIP port to a hardware TPM\n");
+ printf("\n");
+ printf("\t--port,-p <n> TCPIP server port (default 2321)\n");
+ printf("\t-mssim use MS TPM 2.0 socket simulator packet format (default)\n");
+ printf("\t\twith TSS env variable TPM_SERVER_TYPE=mssim (default)\n");
+ printf("\t-raw use TPM 2.0 packet format\n");
+ printf("\t\twith TSS env variable TPM_SERVER_TYPE=raw\n");
+ printf("\t--verbose,-v verbose mode (default false)\n");
+ printf("\t--log,-l log transactions into given file (default none)\n");
+ printf("\t \n");
+ return;
+}