blob: 0aca528b26b8d22d8c53f9844ea774aa5d16fbbc [file] [log] [blame]
/* Microsoft Reference Implementation for TPM 2.0
*
* The copyright in this software is being made available under the BSD License,
* included below. This software may be subject to other third party and
* contributor rights, including patent rights, and no such rights are granted
* under this license.
*
* Copyright (c) Microsoft Corporation
*
* All rights reserved.
*
* BSD License
*
* 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.
*
* 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.
*/
//** Description
// This file contains the entry point for the simulator.
//** Includes, Defines, Data Definitions, and Function Prototypes
#include "TpmBuildSwitches.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#ifdef _MSC_VER
# pragma warning(push, 3)
# include <windows.h>
# include <winsock.h>
# pragma warning(pop)
#elif defined(__unix__)
# define _strcmpi strcasecmp
typedef int SOCKET;
#else
# error "Unsupported platform."
#endif
#include "TpmTcpProtocol.h"
#include "Manufacture_fp.h"
#include "Platform_fp.h"
#include "Simulator_fp.h"
#define PURPOSE \
"TPM 2.0 Reference Simulator.\n" \
"Copyright (c) Microsoft Corporation. All rights reserved."
#define DEFAULT_TPM_PORT 2321
// Information about command line arguments (does not include program name)
static uint32_t s_ArgsMask = 0; // Bit mask of unmatched command line args
static int s_Argc = 0;
static const char **s_Argv = NULL;
//** Functions
#if DEBUG
//*** Assert()
// This function implements a run-time assertion.
// Computation of its parameters must not result in any side effects, as these
// computations will be stripped from the release builds.
static void Assert (bool cond, const char* msg)
{
if (cond)
return;
fputs(msg, stderr);
exit(2);
}
#else
#define Assert(cond, msg)
#endif
//*** Usage()
// This function prints the proper calling sequence for the simulator.
static void
Usage(
const char *programName
)
{
fprintf(stderr, "%s\n\n", PURPOSE);
fprintf(stderr, "Usage: %s [PortNum] [opts]\n\n"
"Starts the TPM server listening on TCP port PortNum (by default %d).\n\n"
"An option can be in the short form (one letter preceded with '-' or '/')\n"
"or in the full form (preceded with '--' or no option marker at all).\n"
"Possible options are:\n"
" -h (--help) or ? - print this message\n"
" -m (--manufacture) - forces NV state of the TPM simulator to be "
"(re)manufactured\n",
programName, DEFAULT_TPM_PORT);
exit(1);
}
//*** CmdLineParser_Init()
// This function initializes command line option parser.
static bool
CmdLineParser_Init(
int argc,
char *argv[],
int maxOpts
)
{
if (argc == 1)
return false;
if (maxOpts && (argc - 1) > maxOpts)
{
fprintf(stderr, "No more than %d options can be specified\n\n", maxOpts);
Usage(argv[0]);
}
s_Argc = argc - 1;
s_Argv = (const char**)(argv + 1);
s_ArgsMask = (1 << s_Argc) - 1;
return true;
}
//*** CmdLineParser_More()
// Returns true if there are unparsed options still.
static bool
CmdLineParser_More(
void
)
{
return s_ArgsMask != 0;
}
//*** CmdLineParser_IsOpt()
// This function determines if the given command line parameter represents a valid
// option.
static bool
CmdLineParser_IsOpt(
const char* opt, // Command line parameter to check
const char* optFull, // Expected full name
const char* optShort, // Expected short (single letter) name
bool dashed // The parameter is preceded by a single dash
)
{
return 0 == strcmp(opt, optFull)
|| (optShort && opt[0] == optShort[0] && opt[1] == 0)
|| (dashed && opt[0] == '-' && 0 == strcmp(opt + 1, optFull));
}
//*** CmdLineParser_IsOptPresent()
// This function determines if the given command line parameter represents a valid
// option.
static bool
CmdLineParser_IsOptPresent(
const char* optFull,
const char* optShort
)
{
int i;
int curArgBit;
Assert(s_Argv != NULL,
"InitCmdLineOptParser(argc, argv) has not been invoked\n");
Assert(optFull && optFull[0],
"Full form of a command line option must be present.\n"
"If only a short (single letter) form is supported, it must be"
"specified as the full one.\n");
Assert(!optShort || (optShort[0] && !optShort[1]),
"If a short form of an option is specified, it must consist "
"of a single letter only.\n");
if (!CmdLineParser_More())
return false;
for (i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1)
{
const char* opt = s_Argv[i];
if ( (s_ArgsMask & curArgBit) && opt
&& ( 0 == strcmp(opt, optFull)
|| ( (opt[0] == '/' || opt[0] == '-')
&& CmdLineParser_IsOpt(opt + 1, optFull, optShort,
opt[0] == '-'))))
{
s_ArgsMask ^= curArgBit;
return true;
}
}
return false;
}
//*** CmdLineParser_Done()
// This function notifies the parser that no more options are needed.
static void
CmdLineParser_Done(
const char *programName
)
{
char delim = ':';
int i;
int curArgBit;
if (!CmdLineParser_More())
return;
fprintf(stderr, "Command line contains unknown option%s",
s_ArgsMask & (s_ArgsMask - 1) ? "s" : "");
for (i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1)
{
if (s_ArgsMask & curArgBit)
{
fprintf(stderr, "%c %s", delim, s_Argv[i]);
delim = ',';
}
}
fprintf(stderr, "\n\n");
Usage(programName);
}
//*** main()
// This is the main entry point for the simulator.
// It registers the interface and starts listening for clients
int
main(
int argc,
char *argv[]
)
{
bool manufacture = false;
int PortNum = DEFAULT_TPM_PORT;
// Parse command line options
if (CmdLineParser_Init(argc, argv, 2))
{
if ( CmdLineParser_IsOptPresent("?", "?")
|| CmdLineParser_IsOptPresent("help", "h"))
{
Usage(argv[0]);
}
if (CmdLineParser_IsOptPresent("manufacture", "m"))
{
manufacture = true;
}
if (CmdLineParser_More())
{
int i;
for (i = 0; i < s_Argc; ++i)
{
char *nptr = NULL;
int portNum = (int)strtol(s_Argv[i], &nptr, 0);
if (s_Argv[i] != nptr)
{
// A numeric option is found
if(!*nptr && portNum > 0 && portNum < 65535)
{
PortNum = portNum;
s_ArgsMask ^= 1 << i;
break;
}
fprintf(stderr, "Invalid numeric option %s\n\n", s_Argv[i]);
Usage(argv[0]);
}
}
}
CmdLineParser_Done(argv[0]);
}
printf("LIBRARY_COMPATIBILITY_CHECK is %s\n",
(LIBRARY_COMPATIBILITY_CHECK ? "ON" : "OFF"));
// Enable NV memory
_plat__NVEnable(NULL);
if (manufacture || _plat__NVNeedsManufacture())
{
printf("Manufacturing NV state...\n");
if(TPM_Manufacture(1) != 0)
{
// if the manufacture didn't work, then make sure that the NV file doesn't
// survive. This prevents manufacturing failures from being ignored the
// next time the code is run.
_plat__NVDisable(1);
exit(1);
}
// Coverage test - repeated manufacturing attempt
if(TPM_Manufacture(0) != 1)
{
exit(2);
}
// Coverage test - re-manufacturing
TPM_TearDown();
if(TPM_Manufacture(1) != 0)
{
exit(3);
}
}
// Disable NV memory
_plat__NVDisable(0);
StartTcpServer(PortNum);
return EXIT_SUCCESS;
}