Coverage Report

Created: 2026-05-30 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ibmswtpm2/src/TcpServerPosix.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*    Socket Interface to a TPM Simulator           */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: TcpServerPosix.c 1332 2018-09-07 14:20:51Z kgoldman $  */
7
/*                    */
8
/*  Licenses and Notices              */
9
/*                    */
10
/*  1. Copyright Licenses:              */
11
/*                    */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
15
/*    derivative works, distribute, display and perform the Source Code and */
16
/*    derivative works thereof, and to grant others the rights granted herein.  */
17
/*                    */
18
/*  - The TCG grants to the user of the other parts of the specification  */
19
/*    (other than the Source Code) the rights to reproduce, distribute,   */
20
/*    display, and perform the specification solely for the purpose of    */
21
/*    developing products based on such documents.        */
22
/*                    */
23
/*  2. Source Code Distribution Conditions:         */
24
/*                    */
25
/*  - Redistributions of Source Code must retain the above copyright licenses,  */
26
/*    this list of conditions and the following disclaimers.      */
27
/*                    */
28
/*  - Redistributions in binary form must reproduce the above copyright   */
29
/*    licenses, this list of conditions and the following disclaimers in the  */
30
/*    documentation and/or other materials provided with the distribution.  */
31
/*                    */
32
/*  3. Disclaimers:               */
33
/*                    */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
39
/*  information on specification licensing rights available through TCG   */
40
/*  membership agreements.              */
41
/*                    */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
47
/*                    */
48
/*  - Without limitation, TCG and its members and licensors disclaim all  */
49
/*    liability, including liability for infringement of any proprietary  */
50
/*    rights, relating to use of information in this specification and to the */
51
/*    implementation of this specification, and TCG disclaims all liability for */
52
/*    cost of procurement of substitute goods or services, lost profits, loss   */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
55
/*    arising in any way out of use or reliance upon this specification or any  */
56
/*    information herein.             */
57
/*                    */
58
/*  (c) Copyright IBM Corp. and others, 2012-2018       */
59
/*                    */
60
/********************************************************************************/
61
62
// D.3  TcpServer.c
63
// D.3.1. Description
64
// This file contains the socket interface to a TPM simulator.
65
// D.3.2. Includes, Locals, Defines and Function Prototypes
66
67
#include <stdio.h>
68
/* FIXME need Posix TCP socket code */
69
#include <unistd.h>
70
#include <sys/types.h>
71
#include <sys/socket.h>
72
#include <netinet/in.h>
73
#include <pthread.h>
74
75
#include "string.h"
76
#include <stdlib.h>
77
#include <stdint.h>
78
#include <errno.h>
79
80
#include "Implementation.h" /* kgold */
81
#include "TpmTcpProtocol.h"
82
#include "TcpServerPosix_fp.h"
83
#include "Simulator_fp.h"
84
85
0
#define IPVER(len) ((len) == sizeof(struct sockaddr_in6) ? 6 :    \
86
0
        ((len) == sizeof(struct sockaddr_in) ? 4 : 0))
87
88
#ifndef __IGNORE_STATE__
89
static UINT32 ServerVersion = 1;
90
20.2k
#define MAX_BUFFER 1048576
91
char InputBuffer[MAX_BUFFER];       //The input data buffer for the simulator.
92
char OutputBuffer[MAX_BUFFER];      //The output data buffer for the simulator.
93
94
struct {
95
    UINT32      largestCommandSize;
96
    UINT32      largestCommand;
97
    UINT32      largestResponseSize;
98
    UINT32      largestResponse;
99
} CommandResponseSizes = {0};
100
101
#endif // __IGNORE_STATE___
102
103
// D.3.3. Functions
104
// D.3.3.1. CreateSocket()
105
// This function creates a socket listening on PortNumber.
106
107
static int
108
CreateSocket(
109
       int                  PortNumber,
110
       SOCKET              *listenSocket,
111
       socklen_t           *addr_len,
112
       int                  domain  // AF_INET or AF_INET6
113
       )
114
0
{
115
0
    struct    sockaddr_storage MyAddress;
116
0
    int     opt;
117
    
118
0
    int res;
119
    
120
    // create listening socket
121
0
    *listenSocket = socket(domain, SOCK_STREAM, 0);
122
0
    if(*listenSocket == -1)
123
0
  {
124
0
            printf("Warning: Cannot create server listen %s socket\nWarning is %d %s\n",
125
0
                   domain == AF_INET6 ? "IPv6" :
126
0
                   (domain == AF_INET) ? "IPv4" : "?", errno, strerror(errno));
127
0
      printf("Ignore the IPv6 warning if the platform doesn't support IPv6\n");
128
0
      return -1;
129
0
  }
130
    
131
    // bind the listening socket to the specified port, any address (0s)
132
0
    memset((char *)&MyAddress, 0, sizeof(MyAddress));
133
134
0
    MyAddress.ss_family = domain;
135
0
    switch (domain) {
136
0
      case AF_INET:
137
0
        ((struct sockaddr_in *)&MyAddress)->sin_port =
138
0
            htons((short) PortNumber);
139
0
  *addr_len = sizeof(struct sockaddr_in);
140
0
        break;
141
0
      case AF_INET6:
142
0
        ((struct sockaddr_in6 *)&MyAddress)->sin6_port =
143
0
            htons((short) PortNumber);
144
0
  *addr_len = sizeof(struct sockaddr_in6);
145
146
0
        opt = 1;
147
        // Set IPPROTO_IPV6 so that it's just for IPv6 and not both IPv4/IPv6.
148
0
        res = setsockopt(*listenSocket, IPPROTO_IPV6, IPV6_V6ONLY, &opt,
149
0
       sizeof(opt));
150
0
        if (res != 0) {
151
0
      printf("setsockopt IPV6_V6ONLY error. Error is %d %s\n",
152
0
       errno, strerror(errno));
153
0
      return -1;
154
0
        }
155
0
        break;
156
0
      default:
157
0
        printf("Address family %d not supported\n", domain);
158
0
        return -1;
159
0
    }
160
161
0
    opt = 1;
162
    /* Set SO_REUSEADDR before calling bind() for servers that bind to a fixed port number. */
163
0
    res = setsockopt(*listenSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
164
0
    if (res != 0) {
165
0
  printf("setsockopt error. Error is %d %s\n", errno, strerror(errno));
166
0
  return -1;
167
0
    }
168
169
0
    res= bind(*listenSocket,(struct sockaddr*) &MyAddress, *addr_len);
170
0
    if(res != 0)
171
0
  {
172
0
            close(*listenSocket);
173
0
      *listenSocket = -1;
174
0
      printf("Bind error.  Error is  %d %s\n", errno, strerror(errno));
175
0
      return -1;
176
0
  }
177
    
178
    // listen/wait for server connections
179
0
    res= listen(*listenSocket,3);
180
0
    if(res != 0)
181
0
  {
182
0
      close(*listenSocket);
183
0
      *listenSocket = -1;
184
0
            printf("Listen error.  Error is %d %s\n", errno, strerror(errno));
185
0
      return -1;
186
0
  }
187
    
188
0
    return 0;
189
0
}
190
191
// D.3.3.2. PlatformServer()
192
// This function processes incoming platform requests.
193
194
BOOL
195
PlatformServer(
196
         SOCKET           s
197
         )
198
0
{
199
0
    BOOL                 ok = TRUE;
200
    // UINT32               length = 0; kgold - unused
201
0
    UINT32               Command;
202
    
203
0
    for(;;)
204
0
  {
205
0
      ok = ReadBytes(s, (char*) &Command, 4);
206
      // client disconnected (or other error).  We stop processing this client
207
      // and return to our caller who can stop the server or listen for another
208
      // connection.
209
0
      if(!ok) return TRUE;
210
0
      Command = ntohl(Command);
211
0
      switch(Command)
212
0
    {
213
0
      case TPM_SIGNAL_POWER_ON:
214
0
        _rpc__Signal_PowerOn(FALSE);
215
0
        break;
216
        
217
0
      case TPM_SIGNAL_POWER_OFF:
218
0
        _rpc__Signal_PowerOff();
219
0
        break;
220
        
221
0
      case TPM_SIGNAL_RESET:
222
0
        _rpc__Signal_PowerOn(TRUE);
223
0
        break;
224
        
225
0
      case TPM_SIGNAL_PHYS_PRES_ON:
226
0
        _rpc__Signal_PhysicalPresenceOn();
227
0
        break;
228
        
229
0
      case TPM_SIGNAL_PHYS_PRES_OFF:
230
0
        _rpc__Signal_PhysicalPresenceOff();
231
0
        break;
232
        
233
0
      case TPM_SIGNAL_CANCEL_ON:
234
0
        _rpc__Signal_CancelOn();
235
0
        break;
236
        
237
0
      case TPM_SIGNAL_CANCEL_OFF:
238
0
        _rpc__Signal_CancelOff();
239
0
        break;
240
        
241
0
      case TPM_SIGNAL_NV_ON:
242
0
        _rpc__Signal_NvOn();
243
0
        break;
244
        
245
0
      case TPM_SIGNAL_NV_OFF:
246
0
        _rpc__Signal_NvOff();
247
0
        break;
248
        
249
0
      case TPM_SESSION_END:
250
        // Client signaled end-of-session
251
0
        return TRUE;
252
        
253
0
      case TPM_STOP:
254
        // Client requested the simulator to exit
255
0
        return FALSE;
256
        
257
0
      case TPM_TEST_FAILURE_MODE:
258
0
        _rpc__ForceFailureMode();
259
0
        break;
260
        
261
0
      case TPM_GET_COMMAND_RESPONSE_SIZES:
262
0
        ok = WriteVarBytes(s, (char *)&CommandResponseSizes,
263
0
               sizeof(CommandResponseSizes));
264
0
        memset(&CommandResponseSizes, 0, sizeof(CommandResponseSizes));
265
0
        if(!ok)
266
0
      return TRUE;
267
0
        break;
268
        
269
0
      default:
270
0
        printf("Unrecognized platform interface command %08x\n", Command);
271
0
        WriteUINT32(s, 1);
272
0
        return TRUE;
273
0
    }
274
0
      WriteUINT32(s,0);
275
0
  }
276
0
    return FALSE;
277
0
}
278
279
// D.3.3.3. PlatformSvcRoutine()
280
// This function is called to set up the socket interfaces to listen for commands.
281
282
int
283
PlatformSvcRoutine(
284
       void *port
285
       )
286
0
{
287
0
    int                  PortNumber = *(int *)port;
288
289
0
    SOCKET               listenSocket[2], maxListenSocket, serverSocket;
290
0
    struct               sockaddr_storage HerAddress;
291
0
    fd_set               sockSet;
292
0
    int                  res, i;
293
0
    int                  nSock = 0;
294
0
    socklen_t            length[2];
295
0
    BOOL                 continueServing;
296
297
0
    if (CreateSocket(PortNumber, &listenSocket[nSock], &length[nSock],
298
0
         AF_INET) == 0) {
299
0
        nSock++;
300
301
0
    }
302
0
    if (CreateSocket(PortNumber, &listenSocket[nSock], &length[nSock],
303
0
         AF_INET6) == 0) {
304
0
        nSock++;
305
0
    }
306
0
    if (nSock == 0) {
307
0
  printf("Create platform service socket fail\n");
308
0
  return -1;
309
0
    }
310
311
0
    maxListenSocket = listenSocket[0];
312
0
    if ((nSock == 2) && (listenSocket[1] > maxListenSocket)) {
313
0
        maxListenSocket = listenSocket[1];
314
0
    }
315
   
316
    // Loop accepting connections one-by-one until we are killed or asked to stop
317
    // Note the platform service is single-threaded so we don't listen for a new
318
    // connection until the prior connection drops.
319
0
    do {
320
0
        printf("Platform server listening on port %d\n", PortNumber);
321
322
  // Select both IPv4 and IPv6 sockets or whatever is available
323
0
  FD_ZERO(&sockSet);
324
0
  FD_SET(listenSocket[0], &sockSet);
325
0
  if (nSock == 2)
326
0
      FD_SET(listenSocket[1], &sockSet);
327
0
  do {
328
0
      res = select(maxListenSocket + 1, &sockSet, NULL, NULL, NULL);
329
0
  }
330
0
  while ((res == -1) && (errno == EINTR));
331
0
  if (res == -1) {
332
0
      printf("Platform server select error.  Error is %d %s\n",
333
0
       errno, strerror(errno));
334
0
      return -1;
335
0
  }
336
337
0
  for (i = 0; i < nSock; i++) {
338
0
      int ipver = IPVER(length[i]);
339
340
0
      if (!FD_ISSET(listenSocket[i], &sockSet))
341
0
    {
342
0
        continue;
343
0
    }
344
      // blocking accept
345
0
      serverSocket = accept(listenSocket[i],
346
0
          (struct sockaddr*) &HerAddress,
347
0
          &length[i]);
348
0
      if(serverSocket < 0)
349
0
    {
350
0
        printf("Platform server IPv%d Accept error.  Error is %d %s\n",
351
0
         ipver, errno, strerror(errno));
352
0
        return -1;
353
0
    };
354
0
      printf("Platform IPv%d client accepted\n", ipver);
355
      
356
      // normal behavior on client disconnection is to wait for a new
357
      // client to connect
358
0
      continueServing = PlatformServer(serverSocket);
359
0
      close(serverSocket);
360
0
      serverSocket = -1;
361
0
  }
362
0
    }
363
0
    while(continueServing);
364
    
365
0
    return 0;
366
0
}
367
368
// D.3.3.4. PlatformSignalService()
369
370
// This function starts a new thread waiting for platform signals. Platform signals are processed
371
// one at a time in the order in which they are received.
372
373
int
374
PlatformSignalService(
375
          int              *PortNumberPlatform
376
          )
377
0
{
378
0
    unsigned long       thread;
379
0
    int                 irc = 0;
380
0
    pthread_t           *pthread = (pthread_t *)&thread;
381
382
0
    irc = pthread_create(pthread,
383
0
                         NULL,
384
0
                         (void * (*)(void *))PlatformSvcRoutine,      /* thread entry function */
385
0
                         (void *)PortNumberPlatform);           /* thread function parameters */
386
0
    if (irc != 0) {
387
0
  printf("Thread Creation failed\n");
388
0
  return -1;
389
0
    }
390
0
    return 0;
391
392
393
#if 0
394
    int                  ThreadId;
395
    HANDLE               hPlatformSvc;
396
    // Create service thread for platform signals
397
    hPlatformSvc = CreateThread(NULL, 0,
398
        (LPTHREAD_START_ROUTINE)PlatformSvcRoutine,
399
        (LPVOID) (INT_PTR) port, 0, (LPDWORD)&ThreadId);
400
    if(hPlatformSvc == NULL)
401
  {
402
      printf("Thread Creation failed\n");
403
      return -1;
404
  }
405
    
406
    return 0;
407
408
409
#endif
410
0
}
411
412
// D.3.3.5. RegularCommandService()
413
// This funciton services regular commands.
414
415
int
416
RegularCommandService(
417
          int              *PortNumber
418
          )
419
0
{
420
0
    SOCKET               listenSocket[2], maxListenSocket;
421
0
    SOCKET               serverSocket;
422
0
    struct               sockaddr_storage HerAddress;
423
0
    fd_set               sockSet;
424
0
    int                  res, i;
425
0
    int                  nSock = 0;
426
0
    socklen_t            length[2];
427
0
    BOOL    continueServing;
428
    
429
0
    if (CreateSocket(*PortNumber, &listenSocket[nSock], &length[nSock],
430
0
         AF_INET) == 0) {
431
0
        nSock++;
432
433
0
    }
434
0
    if (CreateSocket(*PortNumber, &listenSocket[nSock], &length[nSock],
435
0
         AF_INET6) == 0) {
436
0
        nSock++;
437
0
    }
438
0
    if (nSock == 0) {
439
0
        printf("Create TPM command service socket fail\n");
440
0
        return -1;
441
0
    }
442
0
    maxListenSocket = listenSocket[0];
443
0
    if (nSock == 2 && listenSocket[1] > maxListenSocket) {
444
0
        maxListenSocket = listenSocket[1];
445
0
    }
446
    
447
    // Loop accepting connections one-by-one until we are killed or asked to stop
448
    // Note the TPM command service is single-threaded so we don't listen for
449
    // a new connection until the prior connection drops.
450
0
    do
451
0
  {
452
0
      printf("TPM command server listening on port %d\n", *PortNumber);
453
454
      // Select both IPv4 and IPv6 sockets or whatever is available
455
0
      FD_ZERO(&sockSet);
456
0
      FD_SET(listenSocket[0], &sockSet);
457
0
      if (nSock == 2)
458
0
    FD_SET(listenSocket[1], &sockSet);
459
0
      do {
460
0
          res = select(maxListenSocket + 1, &sockSet, NULL, NULL, NULL);
461
0
      } while ((res == -1) && (errno == EINTR));
462
0
      if (res == -1) {                                      
463
0
          printf("TPM command server select error.  Error is %d %s\n", errno,
464
0
           strerror(errno));                             
465
0
          return -1;                                        
466
0
      }                                                     
467
468
0
      for (i = 0; i < nSock; i++) {
469
0
          int ipver = IPVER(length[i]);
470
471
0
          if (!FD_ISSET(listenSocket[i], &sockSet))
472
0
              continue;
473
          // blocking accept
474
0
    serverSocket = accept(listenSocket[i],
475
0
              (struct sockaddr*) &HerAddress,
476
0
              &length[i]);
477
0
    if(serverSocket < 0)
478
0
        {
479
0
      printf("TPM server IPv%d Accept error.  Error is %d %s\n",
480
0
             ipver, errno, strerror(errno));
481
0
      return -1;
482
0
        };
483
0
          printf("Command IPv%d client accepted\n", ipver);
484
      
485
          // normal behavior on client disconnection is to wait for a new
486
          // client to connect
487
0
          continueServing = TpmServer(serverSocket);
488
0
          close(serverSocket);
489
0
          serverSocket = -1;
490
0
      }
491
0
  }
492
0
    while(continueServing);
493
    
494
0
    return 0;
495
0
}
496
497
// D.3.3.6. StartTcpServer()
498
499
// Main entry-point to the TCP server.  The server listens on port specified. Note that there is no
500
// way to specify the network interface in this implementation.
501
502
int
503
StartTcpServer(
504
         int              *PortNumber,
505
         int              *PortNumberPlatform
506
         )
507
0
{
508
0
    int                  res;
509
    
510
    // Start Platform Signal Processing Service
511
0
    res = PlatformSignalService(PortNumberPlatform);
512
0
    if (res != 0)
513
0
  {
514
0
      printf("PlatformSignalService failed\n");
515
0
      return res;
516
0
  }
517
    
518
    // Start Regular/DRTM TPM command service
519
0
    res = RegularCommandService(PortNumber);
520
0
    if (res != 0)
521
0
  {
522
0
      printf("RegularCommandService failed\n");
523
0
      return res;
524
0
  }
525
    
526
0
    return 0;
527
0
}
528
529
// D.3.3.7. ReadBytes()
530
// This function reads the indicated number of bytes (NumBytes) into buffer from the indicated
531
// socket.
532
533
BOOL
534
ReadBytes(
535
    SOCKET           s,
536
    char            *buffer,
537
    int              NumBytes
538
    )
539
46.7k
{
540
46.7k
    int                  res;
541
46.7k
    int                  numGot = 0;
542
    
543
89.5k
    while(numGot<NumBytes)
544
42.9k
  {
545
42.9k
      res = read(s, buffer+numGot, NumBytes-numGot);
546
42.9k
      if(res <= 0)
547
196
    {
548
196
        printf("read() error.  Error is %d %s\n", errno, strerror(errno));
549
196
        return FALSE;
550
196
    }
551
42.7k
      if(res==0)
552
0
    {
553
0
        return FALSE;
554
0
    }
555
42.7k
      numGot+=res;
556
42.7k
  }
557
46.5k
    return TRUE;
558
46.7k
}
559
560
// D.3.3.8. WriteBytes()
561
// This function will send the indicated number of bytes (NumBytes) to the indicated socket
562
563
BOOL
564
WriteBytes(
565
     SOCKET           s,
566
     char            *buffer,
567
     int              NumBytes
568
     )
569
0
{
570
0
    int                  res;
571
0
    int                  numSent = 0;
572
0
    while(numSent<NumBytes)
573
0
  {
574
0
      res = write(s, buffer+numSent, NumBytes-numSent);
575
0
      if(res == 0)
576
0
    {
577
0
        printf("write() error. Error is %d %s\n",  errno, strerror(errno));
578
0
        return FALSE;
579
0
    }
580
0
      numSent+=res;
581
0
  }
582
0
    return TRUE;
583
0
}
584
585
// D.3.3.9. WriteUINT32()
586
// Send 4 bytes containing hton(1)
587
588
BOOL
589
WriteUINT32(
590
      SOCKET           s,
591
      UINT32           val
592
      )
593
0
{
594
0
    UINT32 netVal = htonl(val);
595
0
    return WriteBytes(s, (char*) &netVal, 4);
596
0
}
597
598
// D.3.3.10.  ReadVarBytes()
599
// Get a UINT32-length-prepended binary array.  Note that the 4-byte length is in network byte
600
// order (big-endian).
601
602
BOOL
603
ReadVarBytes(
604
       SOCKET           s,
605
       char            *buffer,
606
       UINT32          *BytesReceived,
607
       int              MaxLen
608
       )
609
10.4k
{
610
10.4k
    int                  length;
611
10.4k
    BOOL                 res;
612
    
613
10.4k
    res = ReadBytes(s, (char*) &length, 4);
614
10.4k
    if(!res) return res;
615
10.4k
    length = ntohl(length);
616
10.4k
    *BytesReceived = length;
617
10.4k
    if(length>MaxLen)
618
4
  {
619
4
      printf("Buffer too big.  Client says %d\n", length);
620
4
      return FALSE;
621
4
  }
622
10.4k
    if(length==0) return TRUE;
623
9.74k
    res = ReadBytes(s, buffer, length);
624
9.74k
    if(!res) return res;
625
9.71k
    return TRUE;
626
9.74k
}
627
628
// D.3.3.11.  WriteVarBytes()
629
// Send a UINT32-length-prepended binary array.  Note that the 4-byte length is in network byte
630
// order (big-endian).
631
632
BOOL
633
WriteVarBytes(
634
        SOCKET           s,
635
        char            *buffer,
636
        int              BytesToSend
637
        )
638
0
{
639
0
    UINT32               netLength = htonl(BytesToSend);
640
0
    BOOL res;
641
    
642
0
    res = WriteBytes(s, (char*) &netLength, 4);
643
0
    if(!res) return res;
644
0
    res = WriteBytes(s, buffer, BytesToSend);
645
0
    if(!res) return res;
646
0
    return TRUE;
647
0
}
648
649
// D.3.3.12.  TpmServer()
650
// Processing incoming TPM command requests using the protocol / interface defined above.
651
652
BOOL
653
TpmServer(
654
    SOCKET           s
655
    )
656
254
{
657
254
    UINT32               length;
658
254
    UINT32               Command;
659
254
    BYTE                 locality;
660
254
    BOOL                 ok;
661
254
    int                  result;
662
254
    int                  clientVersion;
663
254
    _IN_BUFFER           InBuffer;
664
254
    _OUT_BUFFER          OutBuffer;
665
    
666
254
    for(;;)
667
16.3k
  {
668
16.3k
      ok = ReadBytes(s, (char*) &Command, 4);
669
      // client disconnected (or other error).  We stop processing this client
670
      // and return to our caller who can stop the server or listen for another
671
      // connection.
672
16.3k
      if(!ok)
673
130
    return TRUE;
674
16.2k
      Command = ntohl(Command);
675
16.2k
      switch(Command)
676
16.2k
    {
677
3.05k
      case TPM_SIGNAL_HASH_START:
678
3.05k
        _rpc__Signal_Hash_Start();
679
3.05k
        break;
680
        
681
2.34k
      case TPM_SIGNAL_HASH_END:
682
2.34k
        _rpc__Signal_HashEnd();
683
2.34k
        break;
684
        
685
606
      case TPM_SIGNAL_HASH_DATA:
686
606
        ok = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER);
687
606
        if(!ok) return TRUE;
688
602
        InBuffer.Buffer = (BYTE*) InputBuffer;
689
602
        InBuffer.BufferSize = length;
690
602
        _rpc__Signal_Hash_Data(InBuffer);
691
602
        break;
692
        
693
9.84k
      case TPM_SEND_COMMAND:
694
9.84k
        ok = ReadBytes(s, (char*) &locality, 1);
695
9.84k
        if(!ok)
696
8
      return TRUE;
697
        
698
9.84k
        ok = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER);
699
9.84k
        if(!ok)
700
58
      return TRUE;
701
9.78k
        InBuffer.Buffer = (BYTE*) InputBuffer;
702
9.78k
        InBuffer.BufferSize = length;
703
9.78k
        OutBuffer.BufferSize = MAX_BUFFER;
704
9.78k
        OutBuffer.Buffer = (_OUTPUT_BUFFER) OutputBuffer;
705
        // record the number of bytes in the command if it is the largest
706
        // we have seen so far.
707
9.78k
        if(InBuffer.BufferSize > CommandResponseSizes.largestCommandSize)
708
5
      {
709
5
          CommandResponseSizes.largestCommandSize = InBuffer.BufferSize;
710
5
          memcpy(&CommandResponseSizes.largestCommand,
711
5
           &InputBuffer[6], sizeof(UINT32));
712
5
      }
713
        
714
9.78k
        _rpc__Send_Command(locality, InBuffer, &OutBuffer);
715
        // record the number of bytes in the response if it is the largest
716
        // we have seen so far.
717
9.78k
        if(OutBuffer.BufferSize > CommandResponseSizes.largestResponseSize)
718
1
      {
719
1
          CommandResponseSizes.largestResponseSize
720
1
        = OutBuffer.BufferSize;
721
1
          memcpy(&CommandResponseSizes.largestResponse,
722
1
           &OutputBuffer[6], sizeof(UINT32));
723
1
      }
724
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
725
        ok = WriteVarBytes(s,
726
               (char*) OutBuffer.Buffer,
727
               OutBuffer.BufferSize);
728
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
729
9.78k
        if(!ok)
730
0
      return TRUE;
731
9.78k
        break;
732
        
733
9.78k
      case TPM_REMOTE_HANDSHAKE:
734
177
        ok = ReadBytes(s, (char*)&clientVersion, 4);
735
177
        if(!ok)
736
0
      return TRUE;
737
177
        if( clientVersion == 0 )
738
1
      {
739
1
          printf("Unsupported client version (0).\n");
740
1
          return TRUE;
741
1
      }
742
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
743
        ok &= WriteUINT32(s, ServerVersion);
744
        ok &= WriteUINT32(s,
745
              tpmInRawMode | tpmPlatformAvailable | tpmSupportsPP);
746
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
747
176
        break;
748
        
749
176
      case TPM_SET_ALTERNATIVE_RESULT:
750
176
        ok = ReadBytes(s, (char*)&result, 4);
751
176
        if(!ok)
752
0
      return TRUE;
753
        // Alternative result is not applicable to the simulator.
754
176
        break;
755
        
756
176
      case TPM_SESSION_END:
757
        // Client signaled end-of-session
758
0
        return TRUE;
759
        
760
0
      case TPM_STOP:
761
        // Client requested the simulator to exit
762
0
        return FALSE;
763
53
      default:
764
53
        printf("Unrecognized TPM interface command %08x\n", Command);
765
53
        return TRUE;
766
16.2k
    }
767
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
768
      ok = WriteUINT32(s,0);
769
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
770
16.1k
      if(!ok)
771
0
    return TRUE;
772
16.1k
  }
773
0
    return FALSE;
774
254
}