text: /* 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 functions that process the commands received on the
  // control port or the command port of the simulator. The control port is used
  // to allow simulation of hardware events (such as, _TPM_Hash_Start) to test
  // the simulated TPM's reaction to those events. This improves code coverage
  // of the testing.
  
  //** Includes and Data Definitions
  #include <stdbool.h>
  #include "TpmBuildSwitches.h"
  
  #ifdef _MSC_VER
  #   pragma warning(push, 3)
  #   include <windows.h>
  #   include <winsock.h>
  #   pragma warning(pop)
  #elif defined(__unix__)
  #   include "BaseTypes.h"   // on behalf of TpmFail_fp.h
      typedef int SOCKET;
  #else
  #   error "Unsupported platform."
  #endif
  
  #include "Platform_fp.h"
  #include "ExecCommand_fp.h"
  #include "Manufacture_fp.h"
  #include "_TPM_Init_fp.h"
  #include "_TPM_Hash_Start_fp.h"
  #include "_TPM_Hash_Data_fp.h"
  #include "_TPM_Hash_End_fp.h"
  #include "TpmFail_fp.h"
  
  #include "TpmTcpProtocol.h"
  #include "Simulator_fp.h"
  
  static bool     s_isPowerOn = false;
  
  //** Functions
  
  //*** Signal_PowerOn()
  // This function processes a power-on indication. Among other things, it
  // calls the _TPM_Init() handler.
  void
  _rpc__Signal_PowerOn(
      bool        isReset
      )
  {
      // if power is on and this is not a call to do TPM reset then return
      if(s_isPowerOn && !isReset)
          return;
      // If this is a reset but power is not on, then return
      if(isReset && !s_isPowerOn)
          return;
      // Unless this is just a reset, pass power on signal to platform
      if(!isReset)
          _plat__Signal_PowerOn();
      // Power on and reset both lead to _TPM_Init()
      _plat__Signal_Reset();
  
      // Set state as power on
      s_isPowerOn = true;
  }
  
  //*** Signal_Restart()
  // This function processes the clock restart indication. All it does is call
  // the platform function.
  void
  _rpc__Signal_Restart(
      void
      )
  {
      _plat__TimerRestart();
  }
  
  //***Signal_PowerOff()
  // This function processes the power off indication. Its primary function is
  // to set a flag indicating that the next power on indication should cause
  // _TPM_Init() to be called.
  void
  _rpc__Signal_PowerOff(
      void
      )
  {
      if(s_isPowerOn)
          // Pass power off signal to platform
          _plat__Signal_PowerOff();
      // This could be redundant, but...
      s_isPowerOn = false;
  
      return;
  }
  
  //*** _rpc__ForceFailureMode()
  // This function is used to debug the Failure Mode logic of the TPM. It will set
  // a flag in the TPM code such that the next call to TPM2_SelfTest() will result
  // in a failure, putting the TPM into Failure Mode.
  void
  _rpc__ForceFailureMode(
      void
      )
  {
      SetForceFailureMode();
      return;
  }
  
  //*** _rpc__Signal_PhysicalPresenceOn()
  // This function is called to simulate activation of the physical presence "pin".
  void
  _rpc__Signal_PhysicalPresenceOn(
      void
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... pass physical presence on to platform
          _plat__Signal_PhysicalPresenceOn();
      return;
  }
  
  //*** _rpc__Signal_PhysicalPresenceOff()
  // This function is called to simulate deactivation of the physical presence "pin".
  void
  _rpc__Signal_PhysicalPresenceOff(
      void
      )
  {
      // If TPM is power on...
      if(s_isPowerOn)
          // ... pass physical presence off to platform
          _plat__Signal_PhysicalPresenceOff();
      return;
  }
  
  //*** _rpc__Signal_Hash_Start()
  // This function is called to simulate a _TPM_Hash_Start event. It will call
  //
  void
  _rpc__Signal_Hash_Start(
      void
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... pass _TPM_Hash_Start signal to TPM
          _TPM_Hash_Start();
      return;
  }
  
  //*** _rpc__Signal_Hash_Data()
  // This function is called to simulate a _TPM_Hash_Data event.
  void
  _rpc__Signal_Hash_Data(
      _IN_BUFFER       input
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... pass _TPM_Hash_Data signal to TPM
          _TPM_Hash_Data(input.BufferSize, input.Buffer);
      return;
  }
  
  //*** _rpc__Signal_HashEnd()
  // This function is called to simulate a _TPM_Hash_End event.
  void
  _rpc__Signal_HashEnd(
      void
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... pass _TPM_HashEnd signal to TPM
          _TPM_Hash_End();
      return;
  }
  
  //*** _rpc__Send_Command()
  // This is the interface to the TPM code.
  //  Return Type: void
  void
  _rpc__Send_Command(
      unsigned char    locality,
      _IN_BUFFER       request,
      _OUT_BUFFER     *response
      )
  {
      // If TPM is power off, reject any commands.
      if(!s_isPowerOn)
      {
          response->BufferSize = 0;
          return;
      }
      // Set the locality of the command so that it doesn't change during the command
      _plat__LocalitySet(locality);
      // Do implementation-specific command dispatch
      _plat__RunCommand(request.BufferSize, request.Buffer,
                        &response->BufferSize, &response->Buffer);
      return;
  }
  
  //*** _rpc__Signal_CancelOn()
  // This function is used to turn on the indication to cancel a command in process.
  // An executing command is not interrupted. The command code may periodically check
  // this indication to see if it should abort the current command processing and
  // returned TPM_RC_CANCELLED.
  void
  _rpc__Signal_CancelOn(
      void
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... set the platform canceling flag.
          _plat__SetCancel();
      return;
  }
  
  //*** _rpc__Signal_CancelOff()
  // This function is used to turn off the indication to cancel a command in process.
  void
  _rpc__Signal_CancelOff(
      void
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... set the platform canceling flag.
          _plat__ClearCancel();
      return;
  }
  
  //*** _rpc__Signal_NvOn()
  // In a system where the NV memory used by the TPM is not within the TPM, the
  // NV may not always be available. This function turns on the indicator that
  // indicates that NV is available.
  void
  _rpc__Signal_NvOn(
      void
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... make the NV available
          _plat__SetNvAvail();
      return;
  }
  
  //*** _rpc__Signal_NvOff()
  // This function is used to set the indication that NV memory is no
  // longer available.
  void
  _rpc__Signal_NvOff(
      void
      )
  {
      // If TPM power is on...
      if(s_isPowerOn)
          // ... make NV not available
          _plat__ClearNvAvail();
      return;
  }
  
  void RsaKeyCacheControl(int state);
  
  //*** _rpc__RsaKeyCacheControl()
  // This function is used to enable/disable the use of the RSA key cache during
  // simulation.
  void
  _rpc__RsaKeyCacheControl(
      int              state
      )
  {
  #if USE_RSA_KEY_CACHE
      RsaKeyCacheControl(state);
  #else
      NOT_REFERENCED(state);
  #endif
      return;
  }
  
  #define TPM_RH_ACT_0        0x40000110
  
  //*** _rpc__ACT_GetSignaled()
  // This function is used to count the ACT second tick.
  bool
  _rpc__ACT_GetSignaled(
      uint32_t actHandle
  )
  {
      // If TPM power is on...
      if (s_isPowerOn)
          // ... query the platform
          return _plat__ACT_GetSignaled(actHandle - TPM_RH_ACT_0);
      return false;
  }
  
  