| /********************************************************************************/ |
| /* */ |
| /* TSS Configuration Properties */ |
| /* Written by Ken Goldman */ |
| /* IBM Thomas J. Watson Research Center */ |
| /* */ |
| /* (c) Copyright IBM Corporation 2015 - 2020. */ |
| /* */ |
| /* 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. */ |
| /********************************************************************************/ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdarg.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include <ibmtss/tss.h> |
| #include <ibmtss/tsstransmit.h> |
| #ifndef TPM_TSS_NOCRYPTO |
| #include <ibmtss/tsscrypto.h> |
| #endif |
| #include <ibmtss/tssprint.h> |
| |
| #include "tssproperties.h" |
| |
| /* For systems where there are no environment variables, GETENV returns NULL. This simulates the |
| situation when an environment variable is not set, causing the compiled in default to be used. */ |
| #ifndef TPM_TSS_NOENV |
| #define GETENV(x) getenv(x) |
| #else |
| #define GETENV(x) NULL |
| #endif |
| |
| /* local prototypes */ |
| |
| static TPM_RC TSS_SetTraceLevel(const char *value); |
| static TPM_RC TSS_SetDataDirectory(TSS_CONTEXT *tssContext, const char *value); |
| static TPM_RC TSS_SetCommandPort(TSS_CONTEXT *tssContext, const char *value); |
| static TPM_RC TSS_SetPlatformPort(TSS_CONTEXT *tssContext, const char *value); |
| static TPM_RC TSS_SetServerName(TSS_CONTEXT *tssContext, const char *value); |
| static TPM_RC TSS_SetServerType(TSS_CONTEXT *tssContext, const char *value); |
| static TPM_RC TSS_SetInterfaceType(TSS_CONTEXT *tssContext, const char *value); |
| static TPM_RC TSS_SetDevice(TSS_CONTEXT *tssContext, const char *value); |
| static TPM_RC TSS_SetEncryptSessions(TSS_CONTEXT *tssContext, const char *value); |
| |
| /* globals for the library */ |
| |
| /* tracing is global to avoid passing the context into every function call */ |
| int tssVerbose = TRUE; /* initial value so TSS_Properties_Init errors emit message */ |
| int tssVverbose = FALSE; |
| |
| /* This is a total hack to ensure that the global verbose flags are only set once. It's used by the |
| two entry points to the TSS, TSS_Create() and TSS_SetProperty() */ |
| |
| int tssFirstCall = TRUE; |
| |
| /* defaults for global settings */ |
| |
| #ifndef TPM_TRACE_LEVEL_DEFAULT |
| #define TPM_TRACE_LEVEL_DEFAULT "0" |
| #endif |
| |
| #ifndef TPM_COMMAND_PORT_DEFAULT |
| #define TPM_COMMAND_PORT_DEFAULT "2321" /* default for MS simulator */ |
| #endif |
| |
| #ifndef TPM_PLATFORM_PORT_DEFAULT |
| #define TPM_PLATFORM_PORT_DEFAULT "2322" /* default for MS simulator */ |
| #endif |
| |
| #ifndef TPM_SERVER_NAME_DEFAULT |
| #define TPM_SERVER_NAME_DEFAULT "localhost" /* default to local machine */ |
| #endif |
| |
| #ifndef TPM_SERVER_TYPE_DEFAULT |
| #define TPM_SERVER_TYPE_DEFAULT "mssim" /* default to MS simulator format */ |
| #endif |
| |
| #ifndef TPM_DATA_DIR_DEFAULT |
| #define TPM_DATA_DIR_DEFAULT "." /* default to current working directory */ |
| #endif |
| |
| #ifndef TPM_INTERFACE_TYPE_DEFAULT |
| #ifndef TPM_NOSOCKET |
| #define TPM_INTERFACE_TYPE_DEFAULT "socsim" /* default to MS simulator interface */ |
| #else |
| #define TPM_INTERFACE_TYPE_DEFAULT "dev" /* if no sockets, default to device driver */ |
| #endif |
| #endif |
| |
| #ifndef TPM_DEVICE_DEFAULT |
| #ifdef TPM_POSIX |
| #define TPM_DEVICE_DEFAULT "/dev/tpm0" /* default to Linux device driver */ |
| #endif |
| #ifdef TPM_WINDOWS |
| #define TPM_DEVICE_DEFAULT "tddl.dll" /* default to Windows TPM interface dll */ |
| #endif |
| #endif |
| |
| #ifndef TPM_ENCRYPT_SESSIONS_DEFAULT |
| #define TPM_ENCRYPT_SESSIONS_DEFAULT "1" |
| #endif |
| |
| /* TSS_GlobalProperties_Init() sets the global verbose trace flags at the first entry points to the |
| TSS */ |
| |
| TPM_RC TSS_GlobalProperties_Init(void) |
| { |
| TPM_RC rc = 0; |
| const char *value; |
| |
| /* trace level is global, tssContext can be null */ |
| if (rc == 0) { |
| value = GETENV("TPM_TRACE_LEVEL"); |
| rc = TSS_SetTraceLevel(value); |
| } |
| return rc; |
| } |
| |
| |
| /* TSS_Properties_Init() sets the initial TSS_CONTEXT properties based on either the environment |
| variables (if set) or the defaults (if not). |
| */ |
| |
| TPM_RC TSS_Properties_Init(TSS_CONTEXT *tssContext) |
| { |
| TPM_RC rc = 0; |
| const char *value; |
| |
| if (rc == 0) { |
| tssContext->tssAuthContext = NULL; |
| tssContext->tssFirstTransmit = TRUE; /* connection not opened */ |
| tssContext->tpm12Command = FALSE; |
| #ifdef TPM_WINDOWS |
| tssContext->sock_fd = INVALID_SOCKET; |
| #endif |
| #ifdef TPM_POSIX |
| #ifndef TPM_NOSOCKET |
| tssContext->sock_fd = -1; |
| #endif /* TPM_NOSOCKET */ |
| tssContext->dev_fd = -1; |
| #endif /* TPM_POSIX */ |
| |
| #ifdef TPM_SKIBOOT |
| tssContext->tpm_driver = NULL; |
| tssContext->tpm_device = NULL; |
| #endif /* TPM_SKIBOOT */ |
| |
| #ifndef TPM_TSS_NOCRYPTO |
| #ifndef TPM_TSS_NOFILE |
| tssContext->tssSessionEncKey = NULL; |
| tssContext->tssSessionDecKey = NULL; |
| #endif |
| #endif |
| } |
| /* for a minimal TSS with no file support */ |
| #ifdef TPM_TSS_NOFILE |
| { |
| size_t i; |
| for (i = 0 ; i < (sizeof(tssContext->sessions) / sizeof(TSS_SESSIONS)) ; i++) { |
| tssContext->sessions[i].sessionHandle = TPM_RH_NULL; |
| tssContext->sessions[i].sessionData = NULL; |
| tssContext->sessions[i].sessionDataLength = 0; |
| } |
| for (i = 0 ; i < (sizeof(tssContext->objectPublic) / sizeof(TSS_OBJECT_PUBLIC)) ; i++) { |
| tssContext->objectPublic[i].objectHandle = TPM_RH_NULL; |
| } |
| for (i = 0 ; i < (sizeof(tssContext->nvPublic) / sizeof(TSS_NVPUBLIC)) ; i++) { |
| tssContext->nvPublic[i].nvIndex = TPM_RH_NULL; |
| } |
| } |
| #endif |
| /* data directory */ |
| if (rc == 0) { |
| value = GETENV("TPM_DATA_DIR"); |
| rc = TSS_SetDataDirectory(tssContext, value); |
| } |
| /* flag whether session state should be encrypted */ |
| if (rc == 0) { |
| value = GETENV("TPM_ENCRYPT_SESSIONS"); |
| rc = TSS_SetEncryptSessions(tssContext, value); |
| } |
| /* TPM socket command port */ |
| if (rc == 0) { |
| value = GETENV("TPM_COMMAND_PORT"); |
| rc = TSS_SetCommandPort(tssContext, value); |
| } |
| /* TPM simulator socket platform port */ |
| if (rc == 0) { |
| value = GETENV("TPM_PLATFORM_PORT"); |
| rc = TSS_SetPlatformPort(tssContext, value); |
| } |
| /* TPM socket host name */ |
| if (rc == 0) { |
| value = GETENV("TPM_SERVER_NAME"); |
| rc = TSS_SetServerName(tssContext, value); |
| } |
| /* TPM socket server type */ |
| if (rc == 0) { |
| value = GETENV("TPM_SERVER_TYPE"); |
| rc = TSS_SetServerType(tssContext, value); |
| } |
| /* TPM interface type */ |
| if (rc == 0) { |
| value = GETENV("TPM_INTERFACE_TYPE"); |
| rc = TSS_SetInterfaceType(tssContext, value); |
| } |
| /* TPM device within the interface type */ |
| if (rc == 0) { |
| value = GETENV("TPM_DEVICE"); |
| rc = TSS_SetDevice(tssContext, value); |
| } |
| return rc; |
| } |
| |
| /* TSS_SetProperty() sets the property to the value. |
| |
| The format of the property and value the same as that of the environment variable. |
| |
| A NULL value sets the property to the default. |
| */ |
| |
| TPM_RC TSS_SetProperty(TSS_CONTEXT *tssContext, |
| int property, |
| const char *value) |
| { |
| TPM_RC rc = 0; |
| |
| /* at the first call to the TSS, initialize global variables */ |
| if (tssFirstCall) { |
| #ifndef TPM_TSS_NOCRYPTO |
| /* crypto module initializations */ |
| if (rc == 0) { |
| rc = TSS_Crypto_Init(); |
| } |
| #endif |
| if (rc == 0) { |
| rc = TSS_GlobalProperties_Init(); |
| } |
| tssFirstCall = FALSE; |
| } |
| if (rc == 0) { |
| switch (property) { |
| case TPM_TRACE_LEVEL: |
| rc = TSS_SetTraceLevel(value); |
| break; |
| case TPM_DATA_DIR: |
| rc = TSS_SetDataDirectory(tssContext, value); |
| break; |
| case TPM_COMMAND_PORT: |
| rc = TSS_SetCommandPort(tssContext, value); |
| break; |
| case TPM_PLATFORM_PORT: |
| rc = TSS_SetPlatformPort(tssContext, value); |
| break; |
| case TPM_SERVER_NAME: |
| rc = TSS_SetServerName(tssContext, value); |
| break; |
| case TPM_SERVER_TYPE: |
| rc = TSS_SetServerType(tssContext, value); |
| break; |
| case TPM_INTERFACE_TYPE: |
| rc = TSS_SetInterfaceType(tssContext, value); |
| break; |
| case TPM_DEVICE: |
| rc = TSS_SetDevice(tssContext, value); |
| break; |
| case TPM_ENCRYPT_SESSIONS: |
| rc = TSS_SetEncryptSessions(tssContext, value); |
| break; |
| default: |
| rc = TSS_RC_BAD_PROPERTY; |
| } |
| } |
| return rc; |
| } |
| |
| /* TSS_SetTraceLevel() sets the trace level. |
| |
| 0: no printing |
| 1: error printing |
| 2: trace printing |
| */ |
| |
| static TPM_RC TSS_SetTraceLevel(const char *value) |
| { |
| TPM_RC rc = 0; |
| int irc = 0; |
| int level; |
| |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_TRACE_LEVEL_DEFAULT; |
| } |
| } |
| #if !defined(__ULTRAVISOR__) && !defined(TPM_SKIBOOT) |
| if (rc == 0) { |
| irc = sscanf(value, "%u", &level); |
| if (irc != 1) { |
| if (tssVerbose) printf("TSS_SetTraceLevel: Error, value invalid\n"); |
| rc = TSS_RC_BAD_PROPERTY_VALUE; |
| } |
| } |
| /* disable tracing within the ultravisor and skiboot, which doesn't implement sscanf() anyway */ |
| #else |
| irc = irc; |
| level = 0; |
| #endif |
| if (rc == 0) { |
| switch (level) { |
| case 0: |
| tssVerbose = FALSE; |
| tssVverbose = FALSE; |
| break; |
| case 1: |
| tssVerbose = TRUE; |
| tssVverbose = FALSE; |
| break; |
| default: |
| tssVerbose = TRUE; |
| tssVverbose = TRUE; |
| break; |
| } |
| } |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetDataDirectory(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_DATA_DIR_DEFAULT; |
| } |
| } |
| if (rc == 0) { |
| tssContext->tssDataDirectory = value; |
| /* appended to this is 17 characters /cccnnnnnnnn.bin[nul], add a bit of margin for future |
| prefixes */ |
| if (strlen(value) > (TPM_DATA_DIR_PATH_LENGTH - 24)) { |
| if (tssVerbose) printf("TSS_SetDataDirectory: Error, value too long\n"); |
| rc = TSS_RC_BAD_PROPERTY_VALUE; |
| } |
| } |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetCommandPort(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| int irc = 0; |
| |
| /* close an open connection before changing property */ |
| if (rc == 0) { |
| rc = TSS_Close(tssContext); |
| } |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_COMMAND_PORT_DEFAULT; |
| } |
| } |
| #ifndef TPM_NOSOCKET |
| if (rc == 0) { |
| irc = sscanf(value, "%hu", &tssContext->tssCommandPort); |
| if (irc != 1) { |
| if (tssVerbose) printf("TSS_SetCommandPort: Error, value invalid\n"); |
| rc = TSS_RC_BAD_PROPERTY_VALUE; |
| } |
| } |
| #else |
| tssContext->tssCommandPort = 0; |
| irc = irc; |
| #endif /* TPM_NOSOCKET */ |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetPlatformPort(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| int irc = 0; |
| |
| /* close an open connection before changing property */ |
| if (rc == 0) { |
| rc = TSS_Close(tssContext); |
| } |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_PLATFORM_PORT_DEFAULT; |
| } |
| } |
| #ifndef TPM_NOSOCKET |
| if (rc == 0) { |
| irc = sscanf(value, "%hu", &tssContext->tssPlatformPort); |
| if (irc != 1) { |
| if (tssVerbose) printf("TSS_SetPlatformPort: Error, , value invalid\n"); |
| rc = TSS_RC_BAD_PROPERTY_VALUE; |
| } |
| } |
| #else |
| tssContext->tssPlatformPort = 0; |
| irc = irc; |
| #endif /* TPM_NOSOCKET */ |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetServerName(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| |
| /* close an open connection before changing property */ |
| if (rc == 0) { |
| rc = TSS_Close(tssContext); |
| } |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_SERVER_NAME_DEFAULT; |
| } |
| } |
| if (rc == 0) { |
| tssContext->tssServerName = value; |
| } |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetServerType(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| |
| /* close an open connection before changing property */ |
| if (rc == 0) { |
| rc = TSS_Close(tssContext); |
| } |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_SERVER_TYPE_DEFAULT; |
| } |
| } |
| if (rc == 0) { |
| tssContext->tssServerType = value; |
| } |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetInterfaceType(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| |
| /* close an open connection before changing property */ |
| if (rc == 0) { |
| rc = TSS_Close(tssContext); |
| } |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_INTERFACE_TYPE_DEFAULT; |
| } |
| } |
| if (rc == 0) { |
| tssContext->tssInterfaceType = value; |
| } |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetDevice(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| |
| /* close an open connection before changing property */ |
| if (rc == 0) { |
| rc = TSS_Close(tssContext); |
| } |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_DEVICE_DEFAULT; |
| } |
| } |
| if (rc == 0) { |
| tssContext->tssDevice = value; |
| } |
| return rc; |
| } |
| |
| static TPM_RC TSS_SetEncryptSessions(TSS_CONTEXT *tssContext, const char *value) |
| { |
| TPM_RC rc = 0; |
| int irc = 0; |
| |
| if (rc == 0) { |
| if (value == NULL) { |
| value = TPM_ENCRYPT_SESSIONS_DEFAULT; |
| } |
| } |
| #ifndef TPM_TSS_NOFILE |
| if (rc == 0) { |
| irc = sscanf(value, "%u", &tssContext->tssEncryptSessions); |
| if (irc != 1) { |
| if (tssVerbose) printf("TSS_SetEncryptSessions: Error, value invalid\n"); |
| rc = TSS_RC_BAD_PROPERTY_VALUE; |
| } |
| } |
| #else |
| tssContext->tssEncryptSessions = TRUE; |
| irc = irc; |
| #endif /* TPM_TSS_NOFILE */ |
| return rc; |
| } |