xref: /aosp_15_r20/external/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmds.c (revision 5c591343844d1f9da7da26467c4bf7efc8a7a413)
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