1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Description
36*5c591343SA. Cody Schuffelen // This file contains the entry point for the simulator.
37*5c591343SA. Cody Schuffelen
38*5c591343SA. Cody Schuffelen //** Includes, Defines, Data Definitions, and Function Prototypes
39*5c591343SA. Cody Schuffelen #include "TpmBuildSwitches.h"
40*5c591343SA. Cody Schuffelen
41*5c591343SA. Cody Schuffelen #include <stdlib.h>
42*5c591343SA. Cody Schuffelen #include <stdio.h>
43*5c591343SA. Cody Schuffelen #include <stdint.h>
44*5c591343SA. Cody Schuffelen #include <stdbool.h>
45*5c591343SA. Cody Schuffelen #include <ctype.h>
46*5c591343SA. Cody Schuffelen #include <string.h>
47*5c591343SA. Cody Schuffelen
48*5c591343SA. Cody Schuffelen #ifdef _WIN32
49*5c591343SA. Cody Schuffelen # pragma warning(push, 3)
50*5c591343SA. Cody Schuffelen # include <windows.h>
51*5c591343SA. Cody Schuffelen # include <winsock.h>
52*5c591343SA. Cody Schuffelen # pragma warning(pop)
53*5c591343SA. Cody Schuffelen #elif defined(__unix__) || __APPLE__
54*5c591343SA. Cody Schuffelen # define _strcmpi strcasecmp
55*5c591343SA. Cody Schuffelen typedef int SOCKET;
56*5c591343SA. Cody Schuffelen #else
57*5c591343SA. Cody Schuffelen # error "Unsupported platform."
58*5c591343SA. Cody Schuffelen #endif
59*5c591343SA. Cody Schuffelen
60*5c591343SA. Cody Schuffelen
61*5c591343SA. Cody Schuffelen #include "TpmTcpProtocol.h"
62*5c591343SA. Cody Schuffelen #include "Manufacture_fp.h"
63*5c591343SA. Cody Schuffelen #include "Platform_fp.h"
64*5c591343SA. Cody Schuffelen #include "Simulator_fp.h"
65*5c591343SA. Cody Schuffelen
66*5c591343SA. Cody Schuffelen #define PURPOSE \
67*5c591343SA. Cody Schuffelen "TPM 2.0 Reference Simulator.\n" \
68*5c591343SA. Cody Schuffelen "Copyright (c) Microsoft Corporation. All rights reserved."
69*5c591343SA. Cody Schuffelen
70*5c591343SA. Cody Schuffelen #define DEFAULT_TPM_PORT 2321
71*5c591343SA. Cody Schuffelen
72*5c591343SA. Cody Schuffelen // Information about command line arguments (does not include program name)
73*5c591343SA. Cody Schuffelen static uint32_t s_ArgsMask = 0; // Bit mask of unmatched command line args
74*5c591343SA. Cody Schuffelen static int s_Argc = 0;
75*5c591343SA. Cody Schuffelen static const char **s_Argv = NULL;
76*5c591343SA. Cody Schuffelen
77*5c591343SA. Cody Schuffelen
78*5c591343SA. Cody Schuffelen //** Functions
79*5c591343SA. Cody Schuffelen
80*5c591343SA. Cody Schuffelen #if DEBUG
81*5c591343SA. Cody Schuffelen //*** Assert()
82*5c591343SA. Cody Schuffelen // This function implements a run-time assertion.
83*5c591343SA. Cody Schuffelen // Computation of its parameters must not result in any side effects, as these
84*5c591343SA. Cody Schuffelen // computations will be stripped from the release builds.
Assert(bool cond,const char * msg)85*5c591343SA. Cody Schuffelen static void Assert (bool cond, const char* msg)
86*5c591343SA. Cody Schuffelen {
87*5c591343SA. Cody Schuffelen if (cond)
88*5c591343SA. Cody Schuffelen return;
89*5c591343SA. Cody Schuffelen fputs(msg, stderr);
90*5c591343SA. Cody Schuffelen exit(2);
91*5c591343SA. Cody Schuffelen }
92*5c591343SA. Cody Schuffelen #else
93*5c591343SA. Cody Schuffelen #define Assert(cond, msg)
94*5c591343SA. Cody Schuffelen #endif
95*5c591343SA. Cody Schuffelen
96*5c591343SA. Cody Schuffelen //*** Usage()
97*5c591343SA. Cody Schuffelen // This function prints the proper calling sequence for the simulator.
98*5c591343SA. Cody Schuffelen static void
Usage(const char * programName)99*5c591343SA. Cody Schuffelen Usage(
100*5c591343SA. Cody Schuffelen const char *programName
101*5c591343SA. Cody Schuffelen )
102*5c591343SA. Cody Schuffelen {
103*5c591343SA. Cody Schuffelen fprintf(stderr, "%s\n\n", PURPOSE);
104*5c591343SA. Cody Schuffelen fprintf(stderr, "Usage: %s [PortNum] [opts]\n\n"
105*5c591343SA. Cody Schuffelen "Starts the TPM server listening on TCP port PortNum (by default %d).\n\n"
106*5c591343SA. Cody Schuffelen "An option can be in the short form (one letter preceded with '-' or '/')\n"
107*5c591343SA. Cody Schuffelen "or in the full form (preceded with '--' or no option marker at all).\n"
108*5c591343SA. Cody Schuffelen "Possible options are:\n"
109*5c591343SA. Cody Schuffelen " -h (--help) or ? - print this message\n"
110*5c591343SA. Cody Schuffelen " -m (--manufacture) - forces NV state of the TPM simulator to be "
111*5c591343SA. Cody Schuffelen "(re)manufactured\n",
112*5c591343SA. Cody Schuffelen programName, DEFAULT_TPM_PORT);
113*5c591343SA. Cody Schuffelen exit(1);
114*5c591343SA. Cody Schuffelen }
115*5c591343SA. Cody Schuffelen
116*5c591343SA. Cody Schuffelen //*** CmdLineParser_Init()
117*5c591343SA. Cody Schuffelen // This function initializes command line option parser.
118*5c591343SA. Cody Schuffelen static bool
CmdLineParser_Init(int argc,char * argv[],int maxOpts)119*5c591343SA. Cody Schuffelen CmdLineParser_Init(
120*5c591343SA. Cody Schuffelen int argc,
121*5c591343SA. Cody Schuffelen char *argv[],
122*5c591343SA. Cody Schuffelen int maxOpts
123*5c591343SA. Cody Schuffelen )
124*5c591343SA. Cody Schuffelen {
125*5c591343SA. Cody Schuffelen if (argc == 1)
126*5c591343SA. Cody Schuffelen return false;
127*5c591343SA. Cody Schuffelen
128*5c591343SA. Cody Schuffelen if (maxOpts && (argc - 1) > maxOpts)
129*5c591343SA. Cody Schuffelen {
130*5c591343SA. Cody Schuffelen fprintf(stderr, "No more than %d options can be specified\n\n", maxOpts);
131*5c591343SA. Cody Schuffelen Usage(argv[0]);
132*5c591343SA. Cody Schuffelen }
133*5c591343SA. Cody Schuffelen
134*5c591343SA. Cody Schuffelen s_Argc = argc - 1;
135*5c591343SA. Cody Schuffelen s_Argv = (const char**)(argv + 1);
136*5c591343SA. Cody Schuffelen s_ArgsMask = (1 << s_Argc) - 1;
137*5c591343SA. Cody Schuffelen return true;
138*5c591343SA. Cody Schuffelen }
139*5c591343SA. Cody Schuffelen
140*5c591343SA. Cody Schuffelen //*** CmdLineParser_More()
141*5c591343SA. Cody Schuffelen // Returns true if there are unparsed options still.
142*5c591343SA. Cody Schuffelen static bool
CmdLineParser_More(void)143*5c591343SA. Cody Schuffelen CmdLineParser_More(
144*5c591343SA. Cody Schuffelen void
145*5c591343SA. Cody Schuffelen )
146*5c591343SA. Cody Schuffelen {
147*5c591343SA. Cody Schuffelen return s_ArgsMask != 0;
148*5c591343SA. Cody Schuffelen }
149*5c591343SA. Cody Schuffelen
150*5c591343SA. Cody Schuffelen //*** CmdLineParser_IsOpt()
151*5c591343SA. Cody Schuffelen // This function determines if the given command line parameter represents a valid
152*5c591343SA. Cody Schuffelen // option.
153*5c591343SA. Cody Schuffelen static bool
CmdLineParser_IsOpt(const char * opt,const char * optFull,const char * optShort,bool dashed)154*5c591343SA. Cody Schuffelen CmdLineParser_IsOpt(
155*5c591343SA. Cody Schuffelen const char* opt, // Command line parameter to check
156*5c591343SA. Cody Schuffelen const char* optFull, // Expected full name
157*5c591343SA. Cody Schuffelen const char* optShort, // Expected short (single letter) name
158*5c591343SA. Cody Schuffelen bool dashed // The parameter is preceded by a single dash
159*5c591343SA. Cody Schuffelen )
160*5c591343SA. Cody Schuffelen {
161*5c591343SA. Cody Schuffelen return 0 == strcmp(opt, optFull)
162*5c591343SA. Cody Schuffelen || (optShort && opt[0] == optShort[0] && opt[1] == 0)
163*5c591343SA. Cody Schuffelen || (dashed && opt[0] == '-' && 0 == strcmp(opt + 1, optFull));
164*5c591343SA. Cody Schuffelen }
165*5c591343SA. Cody Schuffelen
166*5c591343SA. Cody Schuffelen //*** CmdLineParser_IsOptPresent()
167*5c591343SA. Cody Schuffelen // This function determines if the given command line parameter represents a valid
168*5c591343SA. Cody Schuffelen // option.
169*5c591343SA. Cody Schuffelen static bool
CmdLineParser_IsOptPresent(const char * optFull,const char * optShort)170*5c591343SA. Cody Schuffelen CmdLineParser_IsOptPresent(
171*5c591343SA. Cody Schuffelen const char* optFull,
172*5c591343SA. Cody Schuffelen const char* optShort
173*5c591343SA. Cody Schuffelen )
174*5c591343SA. Cody Schuffelen {
175*5c591343SA. Cody Schuffelen int i;
176*5c591343SA. Cody Schuffelen int curArgBit;
177*5c591343SA. Cody Schuffelen Assert(s_Argv != NULL,
178*5c591343SA. Cody Schuffelen "InitCmdLineOptParser(argc, argv) has not been invoked\n");
179*5c591343SA. Cody Schuffelen Assert(optFull && optFull[0],
180*5c591343SA. Cody Schuffelen "Full form of a command line option must be present.\n"
181*5c591343SA. Cody Schuffelen "If only a short (single letter) form is supported, it must be"
182*5c591343SA. Cody Schuffelen "specified as the full one.\n");
183*5c591343SA. Cody Schuffelen Assert(!optShort || (optShort[0] && !optShort[1]),
184*5c591343SA. Cody Schuffelen "If a short form of an option is specified, it must consist "
185*5c591343SA. Cody Schuffelen "of a single letter only.\n");
186*5c591343SA. Cody Schuffelen
187*5c591343SA. Cody Schuffelen if (!CmdLineParser_More())
188*5c591343SA. Cody Schuffelen return false;
189*5c591343SA. Cody Schuffelen
190*5c591343SA. Cody Schuffelen for (i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1)
191*5c591343SA. Cody Schuffelen {
192*5c591343SA. Cody Schuffelen const char* opt = s_Argv[i];
193*5c591343SA. Cody Schuffelen if ( (s_ArgsMask & curArgBit) && opt
194*5c591343SA. Cody Schuffelen && ( 0 == strcmp(opt, optFull)
195*5c591343SA. Cody Schuffelen || ( (opt[0] == '/' || opt[0] == '-')
196*5c591343SA. Cody Schuffelen && CmdLineParser_IsOpt(opt + 1, optFull, optShort,
197*5c591343SA. Cody Schuffelen opt[0] == '-'))))
198*5c591343SA. Cody Schuffelen {
199*5c591343SA. Cody Schuffelen s_ArgsMask ^= curArgBit;
200*5c591343SA. Cody Schuffelen return true;
201*5c591343SA. Cody Schuffelen }
202*5c591343SA. Cody Schuffelen }
203*5c591343SA. Cody Schuffelen return false;
204*5c591343SA. Cody Schuffelen }
205*5c591343SA. Cody Schuffelen
206*5c591343SA. Cody Schuffelen //*** CmdLineParser_Done()
207*5c591343SA. Cody Schuffelen // This function notifies the parser that no more options are needed.
208*5c591343SA. Cody Schuffelen static void
CmdLineParser_Done(const char * programName)209*5c591343SA. Cody Schuffelen CmdLineParser_Done(
210*5c591343SA. Cody Schuffelen const char *programName
211*5c591343SA. Cody Schuffelen )
212*5c591343SA. Cody Schuffelen {
213*5c591343SA. Cody Schuffelen char delim = ':';
214*5c591343SA. Cody Schuffelen int i;
215*5c591343SA. Cody Schuffelen int curArgBit;
216*5c591343SA. Cody Schuffelen
217*5c591343SA. Cody Schuffelen if (!CmdLineParser_More())
218*5c591343SA. Cody Schuffelen return;
219*5c591343SA. Cody Schuffelen
220*5c591343SA. Cody Schuffelen fprintf(stderr, "Command line contains unknown option%s",
221*5c591343SA. Cody Schuffelen s_ArgsMask & (s_ArgsMask - 1) ? "s" : "");
222*5c591343SA. Cody Schuffelen for (i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1)
223*5c591343SA. Cody Schuffelen {
224*5c591343SA. Cody Schuffelen if (s_ArgsMask & curArgBit)
225*5c591343SA. Cody Schuffelen {
226*5c591343SA. Cody Schuffelen fprintf(stderr, "%c %s", delim, s_Argv[i]);
227*5c591343SA. Cody Schuffelen delim = ',';
228*5c591343SA. Cody Schuffelen }
229*5c591343SA. Cody Schuffelen }
230*5c591343SA. Cody Schuffelen fprintf(stderr, "\n\n");
231*5c591343SA. Cody Schuffelen Usage(programName);
232*5c591343SA. Cody Schuffelen }
233*5c591343SA. Cody Schuffelen
234*5c591343SA. Cody Schuffelen //*** main()
235*5c591343SA. Cody Schuffelen // This is the main entry point for the simulator.
236*5c591343SA. Cody Schuffelen // It registers the interface and starts listening for clients
237*5c591343SA. Cody Schuffelen int
main(int argc,char * argv[])238*5c591343SA. Cody Schuffelen main(
239*5c591343SA. Cody Schuffelen int argc,
240*5c591343SA. Cody Schuffelen char *argv[]
241*5c591343SA. Cody Schuffelen )
242*5c591343SA. Cody Schuffelen {
243*5c591343SA. Cody Schuffelen bool manufacture = false;
244*5c591343SA. Cody Schuffelen int PortNum = DEFAULT_TPM_PORT;
245*5c591343SA. Cody Schuffelen
246*5c591343SA. Cody Schuffelen // Parse command line options
247*5c591343SA. Cody Schuffelen
248*5c591343SA. Cody Schuffelen if (CmdLineParser_Init(argc, argv, 2))
249*5c591343SA. Cody Schuffelen {
250*5c591343SA. Cody Schuffelen if ( CmdLineParser_IsOptPresent("?", "?")
251*5c591343SA. Cody Schuffelen || CmdLineParser_IsOptPresent("help", "h"))
252*5c591343SA. Cody Schuffelen {
253*5c591343SA. Cody Schuffelen Usage(argv[0]);
254*5c591343SA. Cody Schuffelen }
255*5c591343SA. Cody Schuffelen if (CmdLineParser_IsOptPresent("manufacture", "m"))
256*5c591343SA. Cody Schuffelen {
257*5c591343SA. Cody Schuffelen manufacture = true;
258*5c591343SA. Cody Schuffelen }
259*5c591343SA. Cody Schuffelen if (CmdLineParser_More())
260*5c591343SA. Cody Schuffelen {
261*5c591343SA. Cody Schuffelen int i;
262*5c591343SA. Cody Schuffelen for (i = 0; i < s_Argc; ++i)
263*5c591343SA. Cody Schuffelen {
264*5c591343SA. Cody Schuffelen char *nptr = NULL;
265*5c591343SA. Cody Schuffelen int portNum = (int)strtol(s_Argv[i], &nptr, 0);
266*5c591343SA. Cody Schuffelen if (s_Argv[i] != nptr)
267*5c591343SA. Cody Schuffelen {
268*5c591343SA. Cody Schuffelen // A numeric option is found
269*5c591343SA. Cody Schuffelen if(!*nptr && portNum > 0 && portNum < 65535)
270*5c591343SA. Cody Schuffelen {
271*5c591343SA. Cody Schuffelen PortNum = portNum;
272*5c591343SA. Cody Schuffelen s_ArgsMask ^= 1 << i;
273*5c591343SA. Cody Schuffelen break;
274*5c591343SA. Cody Schuffelen }
275*5c591343SA. Cody Schuffelen fprintf(stderr, "Invalid numeric option %s\n\n", s_Argv[i]);
276*5c591343SA. Cody Schuffelen Usage(argv[0]);
277*5c591343SA. Cody Schuffelen }
278*5c591343SA. Cody Schuffelen }
279*5c591343SA. Cody Schuffelen }
280*5c591343SA. Cody Schuffelen CmdLineParser_Done(argv[0]);
281*5c591343SA. Cody Schuffelen }
282*5c591343SA. Cody Schuffelen printf("LIBRARY_COMPATIBILITY_CHECK is %s\n",
283*5c591343SA. Cody Schuffelen (LIBRARY_COMPATIBILITY_CHECK ? "ON" : "OFF"));
284*5c591343SA. Cody Schuffelen // Enable NV memory
285*5c591343SA. Cody Schuffelen _plat__NVEnable(NULL);
286*5c591343SA. Cody Schuffelen
287*5c591343SA. Cody Schuffelen if (manufacture || _plat__NVNeedsManufacture())
288*5c591343SA. Cody Schuffelen {
289*5c591343SA. Cody Schuffelen printf("Manufacturing NV state...\n");
290*5c591343SA. Cody Schuffelen if(TPM_Manufacture(1) != 0)
291*5c591343SA. Cody Schuffelen {
292*5c591343SA. Cody Schuffelen // if the manufacture didn't work, then make sure that the NV file doesn't
293*5c591343SA. Cody Schuffelen // survive. This prevents manufacturing failures from being ignored the
294*5c591343SA. Cody Schuffelen // next time the code is run.
295*5c591343SA. Cody Schuffelen _plat__NVDisable(1);
296*5c591343SA. Cody Schuffelen exit(1);
297*5c591343SA. Cody Schuffelen }
298*5c591343SA. Cody Schuffelen // Coverage test - repeated manufacturing attempt
299*5c591343SA. Cody Schuffelen if(TPM_Manufacture(0) != 1)
300*5c591343SA. Cody Schuffelen {
301*5c591343SA. Cody Schuffelen exit(2);
302*5c591343SA. Cody Schuffelen }
303*5c591343SA. Cody Schuffelen // Coverage test - re-manufacturing
304*5c591343SA. Cody Schuffelen TPM_TearDown();
305*5c591343SA. Cody Schuffelen if(TPM_Manufacture(1) != 0)
306*5c591343SA. Cody Schuffelen {
307*5c591343SA. Cody Schuffelen exit(3);
308*5c591343SA. Cody Schuffelen }
309*5c591343SA. Cody Schuffelen }
310*5c591343SA. Cody Schuffelen // Disable NV memory
311*5c591343SA. Cody Schuffelen _plat__NVDisable(0);
312*5c591343SA. Cody Schuffelen
313*5c591343SA. Cody Schuffelen StartTcpServer(PortNum);
314*5c591343SA. Cody Schuffelen return EXIT_SUCCESS;
315*5c591343SA. Cody Schuffelen }
316*5c591343SA. Cody Schuffelen
317