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