blob: d80841c256793058c8620fab27fe4b1f6dc5b92f [file] [log] [blame]
/********************************************************************************/
/* */
/* 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;
}