text: //**********************************************************************;
  // Copyright (c) 2015, Intel Corporation
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  //
  // 2. 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.
  //**********************************************************************;
  
  //
  // tpmclient.cpp : Defines the entry point for the console test application.
  //
  
  #ifdef NO_RM_TESTS
  #include "tpmclient_wo_rm.h"
  #else
  #define SESSIONS_COUNT 5
  #endif
  
  #include <stdbool.h>
  
  #ifndef UNICODE
  #define UNICODE 1
  #endif
  
  #define sprintf_s   snprintf
  #define sscanf_s    sscanf
  
  #include <inttypes.h>
  #include <stdio.h>
  #include <stdlib.h>   // Needed for _wtoi
  #include <string.h>
  
  #include "sapi/tpm20.h"
  #include "../integration/sapi-util.h"
  #include "sample.h"
  #include "tpmclient.h"
  #include "tcti_util.h"
  #include "tss2_endian.h"
  
  // This is done to allow the tests to access fields
  // in the sysContext structure that are needed for
  // special test cases.
  //
  // ATTENTION:  Normal applications should NEVER do this!!
  //
  #include "sysapi_util.h"
  
  #include "tcti/tcti_device.h"
  #include "tcti/tcti_socket.h"
  #include "syscontext.h"
  #include "common/debug.h"
  
  //
  // TPM indices and sizes
  //
  #define NV_AUX_INDEX_SIZE     96
  #define NV_PS_INDEX_SIZE      34
  #define NV_PO_INDEX_SIZE      34
  
  #define INDEX_AUX                       0x01800003 // NV Storage
  #define INDEX_LCP_OWN                   0x01400001 // Launch Policy Owner
  #define INDEX_LCP_SUP                   0x01800001 // Launch Policy Default (Supplier)
  #define TPM20_INDEX_TEST1               0x01500015
  #define TPM20_INDEX_TEST2               0x01500016
  #define TPM20_INDEX_PASSWORD_TEST       0x01500020
  
  
  #define SET_PCR_SELECT_BIT( pcrSelection, pcr ) \
                                                  (pcrSelection).pcrSelect[( (pcr)/8 )] |= ( 1 << ( (pcr) % 8) );
  
  #define CLEAR_PCR_SELECT_BITS( pcrSelection ) \
                                                (pcrSelection).pcrSelect[0] = 0; \
                                                (pcrSelection).pcrSelect[1] = 0; \
                                                (pcrSelection).pcrSelect[2] = 0;
  
  #define SET_PCR_SELECT_SIZE( pcrSelection, size ) \
                                                    (pcrSelection).sizeofSelect = size;
  
  TPM_CC currentCommandCode;
  TPM_CC *currentCommandCodePtr = &currentCommandCode;
  
  #define errorStringSize 200
  char errorString[errorStringSize];
  
  UINT8 simulator = 1;
  
  UINT32 tpmMaxResponseLen = TPMBUF_LEN;
  
  UINT8 resMgrInitialized = 0;
  
  UINT8 pcrAfterExtend[20];
  TPM_HANDLE loadedRsaKeyHandle;
  TPM_HANDLE loadedSha1KeyHandle;
  
  TPM2B_AUTH loadedSha1KeyAuth;
  
  TPM_HANDLE handle1024, handle2048sha1, handle2048rsa;
  
  UINT8 indent = 0;
  
  TSS2_SYS_CONTEXT *sysContext;
  
  TCTI_SOCKET_CONF rmInterfaceConfig = {
      DEFAULT_HOSTNAME,
      DEFAULT_SIMULATOR_TPM_PORT,
      DebugPrintfCallback,
      DebugPrintBufferCallback,
      NULL
  };
  
  TSS2_TCTI_CONTEXT *resMgrTctiContext = 0;
  TSS2_ABI_VERSION abiVersion = { TSSWG_INTEROP, TSS_SAPI_FIRST_FAMILY, TSS_SAPI_FIRST_LEVEL, TSS_SAPI_FIRST_VERSION };
  
  UINT32 tpmSpecVersion = 0;
  UINT32 tpmManufacturer = 0;
  
  #define MSFT_MANUFACTURER_ID 0x4d534654
  #define IBM_MANUFACTURER_ID 0x49424d20
  
  //
  // These are helper functions that are called through function pointers so that
  // they could be swapped easily to point to different functions.
  //
  // Currently they are set to functions that use the TPM to perform the function, but SW-only
  // implementations could be substituted as well.
  //
  UINT32 ( *ComputeSessionHmacPtr )(
      TSS2_SYS_CONTEXT *sysContext,
      TPMS_AUTH_COMMAND *cmdAuth, // Pointer to session input struct
      TPM_HANDLE entityHandle,             // Used to determine if we're accessing a different
      // resource than the bound resoure.
      TPM_RC responseCode,                 // Response code for the command, 0xffff for "none" is
      // used to indicate that no response code is present
      // (used for calculating command HMACs vs response HMACs).
      TPM_HANDLE handle1,                  // First handle == 0xff000000 indicates no handle
      TPM_HANDLE handle2,                  // Second handle == 0xff000000 indicates no handle
      TPMA_SESSION sessionAttributes,      // Current session attributes
      TPM2B_DIGEST *result,                // Where the result hash is saved.
      TPM_RC sessionCmdRval
      ) = TpmComputeSessionHmac;
  
  TPM_RC ( *GetSessionAlgIdPtr )( TPMI_SH_AUTH_SESSION authHandle, TPMI_ALG_HASH *sessionAlgId ) = GetSessionAlgId;
  
  TPM_RC ( *CalcPHash )( TSS2_SYS_CONTEXT *sysContext,TPM_HANDLE handle1, TPM_HANDLE handle2, TPMI_ALG_HASH authHash,
      TPM_RC responseCode, TPM2B_DIGEST *pHash ) = TpmCalcPHash;
  
  UINT32 (*HmacFunctionPtr)( TPM_ALG_ID hashAlg, TPM2B *key,TPM2B **bufferList, TPM2B_DIGEST *result ) = TpmHmac;
  
  UINT32 (*HashFunctionPtr)( TPMI_ALG_HASH hashAlg, UINT16 size, BYTE *data, TPM2B_DIGEST *result ) = TpmHash;
  
  UINT32 (*HandleToNameFunctionPtr)( TPM_HANDLE handle, TPM2B_NAME *name ) = TpmHandleToName;
  
  TPMI_SH_AUTH_SESSION StartPolicySession();
  
  TPMI_SH_AUTH_SESSION InitNvAuxPolicySession();
  
  TPM_RC CompareTPM2B( TPM2B *buffer1, TPM2B *buffer2 )
  {
      int i;
  
      if( buffer1->size != buffer2->size )
          return TPM_RC_FAILURE;
      for( i = 0; i < buffer1->size; i++ )
      {
          if( buffer1->buffer[0] != buffer2->buffer[0] )
              return TPM_RC_FAILURE;
      }
      return TPM_RC_SUCCESS;
  }
  
  void PrintSizedBuffer( TPM2B *sizedBuffer )
  {
      int i;
  
      for( i = 0; i < sizedBuffer->size; i++ )
      {
          DebugPrintf( NO_PREFIX, "%2.2x ", sizedBuffer->buffer[i] );
  
          if( ( (i+1) % 16 ) == 0 )
          {
              DebugPrintf( NO_PREFIX, "\n" );
          }
      }
      DebugPrintf( NO_PREFIX, "\n" );
  }
  
  #define LEVEL_STRING_SIZE 50
  
  void ErrorHandler( UINT32 rval )
  {
      UINT32 errorLevel = rval & TSS2_ERROR_LEVEL_MASK;
      char levelString[LEVEL_STRING_SIZE + 1];
  
      switch( errorLevel )
      {
          case TSS2_TPM_ERROR_LEVEL:
              strncpy( levelString, "TPM", LEVEL_STRING_SIZE );
              break;
          case TSS2_APP_ERROR_LEVEL:
              strncpy( levelString, "Application", LEVEL_STRING_SIZE );
              break;
          case TSS2_SYS_ERROR_LEVEL:
              strncpy( levelString, "System API", LEVEL_STRING_SIZE );
              break;
          case TSS2_SYS_PART2_ERROR_LEVEL:
              strncpy( levelString, "System API TPM encoded", LEVEL_STRING_SIZE );
              break;
          case TSS2_TCTI_ERROR_LEVEL:
              strncpy( levelString, "TCTI", LEVEL_STRING_SIZE );
              break;
          case TSS2_RESMGRTPM_ERROR_LEVEL:
              strncpy( levelString, "Resource Mgr TPM encoded", LEVEL_STRING_SIZE );
              break;
          case TSS2_RESMGR_ERROR_LEVEL:
              strncpy( levelString, "Resource Mgr", LEVEL_STRING_SIZE );
              break;
          case TSS2_DRIVER_ERROR_LEVEL:
              strncpy( levelString, "Driver", LEVEL_STRING_SIZE );
              break;
          default:
              strncpy( levelString, "Unknown Level", LEVEL_STRING_SIZE );
              break;
  	}
  
      sprintf_s( errorString, errorStringSize, "%s Error: 0x%x\n", levelString, rval );
  }
  
  void Cleanup()
  {
      fflush( stdout );
  
      if( resMgrTctiContext != 0 )
      {
          PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
          TeardownTctiContext( &resMgrTctiContext );
      }
  
      exit(1);
  }
  
  void InitSysContextFailure()
  {
      DebugPrintf( NO_PREFIX, "InitSysContext failed, exiting...\n" );
      Cleanup();
  }
  
  void Delay( UINT16 delay)
  {
      volatile UINT32 i, j;
  
      for( j = 0; j < delay; j++ )
      {
          for( i = 0; i < 10000000; i++ )
              ;
      }
  }
  
  #define CheckPassed(rval) {				\
      							\
      DebugPrintf( NO_PREFIX, "\tpassing case:  " );			\
      if ( rval != TPM_RC_SUCCESS) {					\
        ErrorHandler( rval);						\
        DebugPrintf( NO_PREFIX, "\tFAILED!  %s (%s@%u)\n",		\
  		   errorString, __FUNCTION__, __LINE__ );		\
        Cleanup();							\
      } else {								\
        DebugPrintf( NO_PREFIX, "\tPASSED! (%s@%u)\n",			\
  		   __FUNCTION__, __LINE__);				\
      }									\
      									\
      Delay(0);							\
    }
  
  TPMS_AUTH_COMMAND nullSessionData;
  TPMS_AUTH_RESPONSE nullSessionDataOut;
  TPMS_AUTH_COMMAND *nullSessionDataArray[1] = { &nullSessionData };
  TPMS_AUTH_RESPONSE *nullSessionDataOutArray[1] = { &nullSessionDataOut };
  TSS2_SYS_CMD_AUTHS nullSessionsData = { 1, &nullSessionDataArray[0] };
  TSS2_SYS_RSP_AUTHS nullSessionsDataOut = { 1, &nullSessionDataOutArray[0] };
  TPM2B_NONCE nullSessionNonce, nullSessionNonceOut;
  TPM2B_AUTH nullSessionHmac;
  
  #define CheckFailed(rval, expectedTpmErrorCode) {			\
      DebugPrintf( NO_PREFIX, "\tfailing case:");				\
      if ( rval != expectedTpmErrorCode) {				\
        ErrorHandler( rval);						\
        DebugPrintf( NO_PREFIX, "\tFAILED!  Ret code s/b: 0x%x, but was: 0x%x (%s@%u)\n", \
  		   expectedTpmErrorCode, rval, __FUNCTION__, __LINE__ ); \
        Cleanup();							\
      }	else {								\
        DebugPrintf( NO_PREFIX, "\tPASSED! (%s@%u)\n",			\
  		   __FUNCTION__, __LINE__);				\
      }									\
      Delay(0);							\
    }
  
  
  TSS2_RC TpmReset()
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
  
      rval = (TSS2_RC)PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
      if( rval == TSS2_RC_SUCCESS )
      {
          rval = (TSS2_RC)PlatformCommand( resMgrTctiContext, MS_SIM_POWER_ON );
      }
      return rval;
  }
  
  void GetTpmVersion()
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
      TPMS_CAPABILITY_DATA capabilityData;
  
      rval = Tss2_Sys_GetCapability( sysContext, 0,
              TPM_CAP_TPM_PROPERTIES, TPM_PT_REVISION,
              1, 0, &capabilityData, 0 );
      CheckPassed( rval );
  
      if( capabilityData.data.tpmProperties.count == 1 &&
              (capabilityData.data.tpmProperties.tpmProperty[0].property == TPM_PT_REVISION) )
      {
          tpmSpecVersion = capabilityData.data.tpmProperties.tpmProperty[0].value;
          DebugPrintf( NO_PREFIX, "TPM spec version:  %d\n", tpmSpecVersion );
      }
      else
      {
          DebugPrintf( NO_PREFIX, "Failed to get TPM spec version!!\n" );
          Cleanup();
      }
  }
  
  void GetTpmManufacturer()
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
      TPMS_CAPABILITY_DATA capabilityData;
  
      rval = Tss2_Sys_GetCapability( sysContext, 0,
              TPM_CAP_TPM_PROPERTIES, TPM_PT_MANUFACTURER,
              1, 0, &capabilityData, 0 );
      CheckPassed( rval );
  
      if( capabilityData.data.tpmProperties.count == 1 &&
              (capabilityData.data.tpmProperties.tpmProperty[0].property == TPM_PT_MANUFACTURER ) )
      {
          tpmManufacturer = capabilityData.data.tpmProperties.tpmProperty[0].value;
      }
      else
      {
          DebugPrintf( NO_PREFIX, "Failed to get TPM manufacturer!!\n" );
          Cleanup();
      }
  }
  
  void TestDictionaryAttackLockReset()
  {
      UINT32 rval;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nDICTIONARY ATTACK LOCK RESET TEST  :\n" );
  
      // Init authHandle
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      rval = Tss2_Sys_DictionaryAttackLockReset ( sysContext, TPM_RH_LOCKOUT, &sessionsData, &sessionsDataOut );
      CheckPassed( rval );
  }
  
  TSS2_RC StartPolicySession( TPMI_SH_AUTH_SESSION *sessionHandle )
  {
      UINT8 i;
      TPM2B_NONCE nonceCaller, nonceTpm;
      TPM2B_ENCRYPTED_SECRET salt;
      TPMT_SYM_DEF symmetric;
      UINT16 digestSize;
      UINT32 rval;
  
      digestSize = GetDigestSize( TPM_ALG_SHA1 );
      nonceCaller.t.size = digestSize;
      for( i = 0; i < nonceCaller.t.size; i++ )
          nonceCaller.t.buffer[i] = 0;
  
      salt.t.size = 0;
      symmetric.algorithm = TPM_ALG_NULL;
  
      // Create policy session
      INIT_SIMPLE_TPM2B_SIZE( nonceTpm );
      rval = Tss2_Sys_StartAuthSession ( sysContext, TPM_RH_NULL, TPM_RH_NULL, 0, &nonceCaller, &salt,
              TPM_SE_POLICY, &symmetric, TPM_ALG_SHA1, sessionHandle, &nonceTpm, 0 );
      return( rval );
  }
  
  void TestTpmStartup()
  {
      UINT32 rval;
  
      DebugPrintf( NO_PREFIX, "\nSTARTUP TESTS:\n" );
  
      //
      // First test the one-call interface.
      //
  
      // First must do TPM reset.
      rval = TpmReset();
      CheckPassed(rval);
  
      // This one should pass.
      rval = Tss2_Sys_Startup( sysContext, TPM_SU_CLEAR );
      CheckPassed(rval);
  
      // This one should fail.
      rval = Tss2_Sys_Startup( sysContext, TPM_SU_CLEAR );
      CheckFailed( rval, TPM_RC_INITIALIZE );
  
  
      // Cycle power using simulator interface.
      rval = PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
      CheckPassed( rval );
      rval = PlatformCommand( resMgrTctiContext, MS_SIM_POWER_ON );
      CheckPassed( rval );
  
  
      //
      // Now test the synchronous, non-one-call interface.
      //
      rval = Tss2_Sys_Startup_Prepare( sysContext, TPM_SU_CLEAR );
      CheckPassed(rval);
  
      // Execute the command synchronously.
      rval = Tss2_Sys_Execute( sysContext );
      CheckPassed( rval );
  
      // Cycle power using simulator interface.
      rval = PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
      CheckPassed( rval );
      rval = PlatformCommand( resMgrTctiContext, MS_SIM_POWER_ON );
      CheckPassed( rval );
  
  
      //
      // Now test the asynchronous, non-one-call interface.
      //
      rval = Tss2_Sys_Startup_Prepare( sysContext, TPM_SU_CLEAR );
      CheckPassed(rval);
  
      // Execute the command asynchronously.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed(rval);
  
      // Get the command response. Wait a maximum of 20ms
      // for response.
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckPassed(rval);
  }
  
  void TestSapiApis()
  {
      UINT32 rval;
      TPM2B_MAX_BUFFER    outData = { { MAX_DIGEST_BUFFER, } };
      TPM_RC              testResult;
      TSS2_SYS_CONTEXT    *testSysContext;
      TPM2B_PUBLIC        outPublic;
      TPM2B_NAME          name;
      TPM2B_NAME          qualifiedName;
      UINT8               commandCode[4];
      size_t				rpBufferUsedSize;
  	const uint8_t 		*rpBuffer;
  	const uint8_t 		goodRpBuffer[] = { 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
                                             0x01, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00,
  										   0x40 };
      TPMI_YES_NO         moreData;
      TPMS_CAPABILITY_DATA	capabilityData;
      int                 rpBufferError = 0;
      unsigned int        i;
      UINT32              savedRspSize;
  
      DebugPrintf( NO_PREFIX, "\nSAPI API TESTS:\n" );
  
      //
      // First test the one-call interface.
      //
      rval = Tss2_Sys_GetTestResult( sysContext, 0, &outData, &testResult, 0 );
      CheckPassed(rval); // #1
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #2
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_Execute( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #3
  
      //
      // Now test the synchronous, non-one-call interface.
      //
      rval = Tss2_Sys_GetTestResult_Prepare( sysContext );
      CheckPassed(rval); // #4
  
      // Check for BAD_REFERENCE error.
      rval = Tss2_Sys_Execute( 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #5
  
      // Execute the command synchronously.
      rval = Tss2_Sys_Execute( sysContext );
      CheckPassed(rval); // #6
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_Execute( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #7
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #8
  
      // Get the command results
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_GetTestResult_Complete( sysContext, &outData, &testResult );
      CheckPassed(rval); // #9
  
      //
      // Now test the asynchronous, non-one-call interface.
      //
      rval = Tss2_Sys_GetTestResult_Prepare( sysContext );
      CheckPassed(rval); // #10
  
      // Test XXXX_Complete for bad sequence:  after _Prepare
      // and before ExecuteFinish
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_GetTestResult_Complete( sysContext, &outData, &testResult );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #11
  
      // Check for BAD_REFERENCE error.
      rval = Tss2_Sys_ExecuteAsync( 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #12
  
      // Test ExecuteFinish for BAD_SEQUENCE
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #13
  
      // Execute the command asynchronously.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed(rval); // #14
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #15
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_Execute( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #16
  
      // Test ExecuteFinish for BAD_REFERENCE
      rval = Tss2_Sys_ExecuteFinish( 0, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #17
  
      // Test XXXX_Complete for bad sequence:  after _Prepare
      // and before ExecuteFinish
      rval = Tss2_Sys_GetTestResult_Complete( sysContext, &outData, &testResult );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #18
  
      // Get the command response. Wait a maximum of 20ms
      // for response.
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckPassed(rval); // #19
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #20
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #21
  
      // Check for BAD_SEQUENCE error.
      rval = Tss2_Sys_Execute( sysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #22
  
      // Test _Complete for bad reference cases.
      rval = Tss2_Sys_GetTestResult_Complete( 0, &outData, &testResult );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #23
  
      // Get the command results
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_GetTestResult_Complete( sysContext, &outData, &testResult );
      CheckPassed(rval); // #24
  
      testSysContext = InitSysContext( 0,  resMgrTctiContext, &abiVersion );
      if( testSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      // Test GetCommandCode for bad sequence
      rval = Tss2_Sys_GetCommandCode( testSysContext, &commandCode );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #25
  
      rval = Tss2_Sys_GetRpBuffer( testSysContext, &rpBufferUsedSize, &rpBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #26
  
      TeardownSysContext( &testSysContext );
  
      rval = Tss2_Sys_ReadPublic_Prepare( sysContext, handle2048rsa );
      CheckPassed(rval); // #27
  
      // Execute the command synchronously.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed( rval ); // #28
  
      // Test _Complete for bad sequence case when ExecuteFinish has never
      // been done on a context.
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_ReadPublic_Complete( sysContext, &outPublic, &name, &qualifiedName );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #29
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckPassed( rval ); // #30
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #31
  
      rval = Tss2_Sys_ReadPublic_Prepare( sysContext, handle2048rsa );
      CheckPassed(rval); // #32
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #33
  
      rval = Tss2_Sys_ReadPublic_Prepare( sysContext, handle2048rsa );
      CheckPassed(rval); // #34
  
      // Execute the command synchronously.
      rval = Tss2_Sys_Execute( sysContext );
      CheckPassed( rval ); // #35
  
  	outPublic.t.size = name.t.size = qualifiedName.t.size = 0;
  	rval = Tss2_Sys_ReadPublic( sysContext, handle2048rsa, 0,
              &outPublic, 0, 0, 0 );
      CheckPassed( rval ); // #36
  
      // Check case of ExecuteFinish receving TPM error code.
      // Subsequent _Complete call should fail with SEQUENCE error.
      rval = TpmReset();
      CheckPassed(rval); // #37
  
      rval = Tss2_Sys_GetCapability_Prepare( sysContext,
              TPM_CAP_TPM_PROPERTIES, TPM_PT_ACTIVE_SESSIONS_MAX,
              1 );
      CheckPassed(rval); // #38
  
      // Execute the command asynchronously.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed(rval); // #39
  
      // Get the command response. Wait a maximum of 20ms
      // for response.
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TPM_RC_INITIALIZE ); // #40
  
      // Test _Complete for case when ExecuteFinish had an error.
      rval = Tss2_Sys_GetCapability_Complete( sysContext, 0, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #41
  
      rval = Tss2_Sys_Startup( sysContext, TPM_SU_CLEAR );
      CheckPassed(rval); // #42
  
      rval = Tss2_Sys_GetRpBuffer( 0, &rpBufferUsedSize, &rpBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #43
  
      rval = Tss2_Sys_GetRpBuffer( sysContext, 0, &rpBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #44
  
      rval = Tss2_Sys_GetRpBuffer( sysContext, &rpBufferUsedSize, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #45
  
      rval = Tss2_Sys_GetRpBuffer( sysContext, &rpBufferUsedSize, &rpBuffer );
      CheckPassed( rval ); // #46
  
      // Now test case for ExecuteFinish where TPM returns
      // an error.  ExecuteFinish should return same error
      // as TPM.
      rval = Tss2_Sys_Startup_Prepare( sysContext, TPM_SU_CLEAR );
      CheckPassed(rval); // #47
  
      // Execute the command ayncronously.
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed( rval ); // #48
  
      rval = Tss2_Sys_Startup( sysContext, TPM_SU_CLEAR );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #49
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TPM_RC_INITIALIZE ); // #50
  
      // Now test case for ExecuteFinish where TPM returns
      // an error.  ExecuteFinish should return same error
      // as TPM.
      rval = Tss2_Sys_Startup_Prepare( sysContext, TPM_SU_CLEAR );
      CheckPassed(rval); // #51
  
      rval = Tss2_Sys_GetRpBuffer( sysContext, &rpBufferUsedSize, &rpBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #52
  
      // Execute the command ayncronously.
      rval = Tss2_Sys_Execute( sysContext );
      CheckFailed( rval, TPM_RC_INITIALIZE ); // #53
  
      rval = Tss2_Sys_GetRpBuffer( sysContext, &rpBufferUsedSize, &rpBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #54
  
      // Test one-call for null sysContext pointer.
      rval = Tss2_Sys_Startup( 0, TPM_SU_CLEAR );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #55
  
      // Test one-call for NULL input parameter that should be a
      // pointer.
      rval = Tss2_Sys_Create( testSysContext, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #56
  
      // Test GetCommandCode for bad reference
      rval = Tss2_Sys_GetCommandCode( 0, &commandCode );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #57
  
      rval = Tss2_Sys_GetCommandCode( sysContext, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #58
  
      //
      // Test GetRpBuffer for case of no response params or handles.
      //
      rval = Tss2_Sys_Shutdown( sysContext, 0, TPM_SU_STATE, 0 );
      CheckPassed( rval ); // #59
  
      rval = Tss2_Sys_GetRpBuffer( sysContext, &rpBufferUsedSize, &rpBuffer );
      CheckPassed( rval ); // #60
  
      if( rpBufferUsedSize != 0 )
      {
          DebugPrintf( NO_PREFIX, "\nERROR!!  Tss2_Sys_GetRpBuffer returned non-zero size for command that returns no handles or parameters\n" );
          Cleanup();
      }
  
      //
      // Test GetRpBuffer for case of response params.
      //
      rval = Tss2_Sys_GetCapability( sysContext, 0,
              TPM_CAP_TPM_PROPERTIES, TPM_PT_ACTIVE_SESSIONS_MAX,
              1, &moreData, &capabilityData, 0 );
      CheckPassed(rval); // #61
  
      rval = Tss2_Sys_GetRpBuffer( sysContext, &rpBufferUsedSize, &rpBuffer );
      CheckPassed( rval ); // #62
  
      if( rpBufferUsedSize != 17 )
      {
          DebugPrintf( NO_PREFIX, "\nERROR!!  Tss2_Sys_GetRpBuffer returned wrong size for command that returns handles and/or parameters\n" );
          Cleanup();
      }
  
      // Now compare RP buffer to what it should be
      for( i = 0; i < rpBufferUsedSize; i++ )
      {
          if( rpBuffer[i] != goodRpBuffer[i] )
          {
              rpBufferError = 1;
              break;
          }
      }
  
      if( rpBufferError )
      {
          DebugPrintf( NO_PREFIX, "\nERROR!!  Tss2_Sys_GetRpBuffer returned wrong rpBuffer contents:\nrpBuffer was: \n\t" );
          DebugPrintBuffer( NO_PREFIX, (UINT8 *)&rpBuffer, rpBufferUsedSize );
          DebugPrintf( NO_PREFIX, "\nrpBuffer s/b:\n\t" );
          DebugPrintBuffer( NO_PREFIX, (UINT8 *)&(goodRpBuffer[0]), rpBufferUsedSize );
          Cleanup();
      }
  
      TeardownSysContext( &testSysContext );
  
      rval = Tss2_Sys_GetTestResult_Prepare( sysContext );
      CheckPassed(rval); // #63
  
      // Execute the command synchronously.
      rval = Tss2_Sys_Execute( sysContext );
      CheckPassed(rval); // #64
  
      // Get the command results
      // NOTE: this test modifies internal fields of the sysContext structure.
      // DON'T DO THIS IN REAL APPS!!
      savedRspSize = BE_TO_HOST_32(((TPM20_Header_Out *)(SYS_CONTEXT->tpmOutBuffPtr))->responseSize);
      ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr )  )->responseSize = 4097;
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_GetTestResult_Complete( sysContext, &outData, &testResult );
      ( (TPM20_Header_Out *)( SYS_CONTEXT->tpmOutBuffPtr )  )->responseSize = savedRspSize;
      CheckFailed( rval, TSS2_SYS_RC_MALFORMED_RESPONSE ); // #65
  
      // NOTE: this test case is kind of bogus--no application would ever do this
      // since apps can't change the responseSize after TPM has returned the response.
      // ONce the MALFOMED_RESPONSE occurs, there's no way to recover the response data.
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_GetTestResult_Complete( sysContext, &outData, &testResult );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #66
  }
  
  
  void TestTpmGetCapability()
  {
      UINT32 rval;
  
      char manuID[5] = "    ";
      char *manuIDPtr = &manuID[0];
      TPMI_YES_NO moreData;
      TPMS_CAPABILITY_DATA capabilityData;
  
      DebugPrintf( NO_PREFIX, "\nGET_CAPABILITY TESTS:\n" );
  
      rval = Tss2_Sys_GetCapability( sysContext, 0, TPM_CAP_TPM_PROPERTIES, TPM_PT_MANUFACTURER, 1, &moreData, &capabilityData, 0 );
      CheckPassed( rval );
  
      *((UINT32 *)manuIDPtr) = BE_TO_HOST_32(capabilityData.data.tpmProperties.tpmProperty[0].value);
      DebugPrintf( NO_PREFIX, "\t\tcount: %d, property: %x, manuId: %s\n",
              capabilityData.data.tpmProperties.count,
              capabilityData.data.tpmProperties.tpmProperty[0].property,
              manuID );
  
      rval = Tss2_Sys_GetCapability( sysContext, 0, TPM_CAP_TPM_PROPERTIES, TPM_PT_MAX_COMMAND_SIZE, 1, &moreData, &capabilityData, 0 );
      CheckPassed( rval );
      DebugPrintf( NO_PREFIX, "\t\tcount: %d, property: %x, max cmd size: %d\n",
              capabilityData.data.tpmProperties.count,
              capabilityData.data.tpmProperties.tpmProperty[0].property,
              capabilityData.data.tpmProperties.tpmProperty[0].value );
  
  
      rval = Tss2_Sys_GetCapability( sysContext, 0, TPM_CAP_TPM_PROPERTIES, TPM_PT_MAX_COMMAND_SIZE, 40, &moreData, &capabilityData, 0 );
      CheckPassed( rval );
      DebugPrintf( NO_PREFIX, "\t\tcount: %d, property: %x, max cmd size: %d\n",
              capabilityData.data.tpmProperties.count,
              capabilityData.data.tpmProperties.tpmProperty[0].property,
              capabilityData.data.tpmProperties.tpmProperty[0].value );
  
  
      rval = Tss2_Sys_GetCapability( sysContext, 0, TPM_CAP_TPM_PROPERTIES, TPM_PT_MAX_RESPONSE_SIZE, 1, &moreData, &capabilityData, 0 );
      CheckPassed( rval );
      DebugPrintf( NO_PREFIX, "\t count: %d, property: %x, max response size: %d\n",
              capabilityData.data.tpmProperties.count,
              capabilityData.data.tpmProperties.tpmProperty[0].property,
              capabilityData.data.tpmProperties.tpmProperty[0].value );
  
      rval = Tss2_Sys_GetCapability( sysContext, 0, 0xff, TPM_PT_MANUFACTURER, 1, &moreData, &capabilityData, 0 );
  
      if( tpmSpecVersion == 115 || tpmSpecVersion == 119 )
      {
          CheckFailed( rval, TPM_RC_VALUE );
      }
      else
      {
          CheckFailed( rval, TPM_RC_VALUE+TPM_RC_1+TPM_RC_P );
      }
  }
  
  void TestTpmClear()
  {
      UINT32 rval;
      TPM2B_AUTH      hmac;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TPM2B_NONCE     nonce;
      TSS2_SYS_CMD_AUTHS sessionsDataIn;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsDataIn.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
      sessionsDataOut.rspAuths[0] = &sessionDataOut;
  
      DebugPrintf( NO_PREFIX, "\nCLEAR and CLEAR CONTROL TESTS:\n" );
  
      // Init sessionHandle
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      nonce.t.size = 0;
      sessionData.nonce = nonce;
  
      // init hmac
      hmac.t.size = 0;
      sessionData.hmac = hmac;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsDataIn.cmdAuthsCount = 1;
      sessionsDataIn.cmdAuths[0] = &sessionData;
  
      rval = Tss2_Sys_Clear ( sysContext, TPM_RH_PLATFORM, &sessionsDataIn, 0 );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ClearControl ( sysContext, TPM_RH_PLATFORM, &sessionsDataIn, YES, &sessionsDataOut );
      CheckPassed( rval );
  
      rval = Tss2_Sys_Clear ( sysContext, TPM_RH_PLATFORM, &sessionsDataIn, 0 );
      CheckFailed( rval, TPM_RC_DISABLED );
  
      rval = Tss2_Sys_ClearControl ( sysContext, TPM_RH_PLATFORM, &sessionsDataIn, NO, &sessionsDataOut );
      CheckPassed( rval );
  
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0xff;
      sessionsDataIn.cmdAuths[0] = &sessionData;
      rval = Tss2_Sys_Clear ( sysContext, TPM_RH_PLATFORM, &sessionsDataIn, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_9 + TPM_RC_RESERVED_BITS );
  
      rval = Tss2_Sys_ClearControl ( sysContext, TPM_RH_PLATFORM, &sessionsDataIn, NO, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_9 + TPM_RC_RESERVED_BITS );
  
      hmac.t.size = 0;
  
  
  }
  
  #define SESSIONS_ABOVE_MAX_ACTIVE 0
  #define DEBUG_MAX_ACTIVE_SESSIONS   8
  #define DEBUG_GAP_MAX   2*DEBUG_MAX_ACTIVE_SESSIONS
  
  SESSION *sessions[SESSIONS_COUNT];
  
  void TestStartAuthSession()
  {
      UINT32 rval;
      TPM2B_ENCRYPTED_SECRET encryptedSalt;
      TPMT_SYM_DEF symmetric;
      SESSION *authSession = NULL;
      TPM2B_NONCE nonceCaller;
      UINT16 i;
      TPM_HANDLE badSessionHandle = 0x03010000;
  
      TPMS_AUTH_COMMAND sessionData;
      TPM2B_NONCE     nonce;
  
  
      TPM2B_AUTH      hmac;
  
  
      // Init sessionHandle
      sessionData.sessionHandle = badSessionHandle;
  
      // Init nonce.
      nonce.t.size = 0;
      sessionData.nonce = nonce;
  
      // init hmac
      hmac.t.size = 0;
      sessionData.hmac = hmac;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      encryptedSalt.t.size = 0;
  
      DebugPrintf( NO_PREFIX, "\nSTART_AUTH_SESSION TESTS:\n" );
  
      symmetric.algorithm = TPM_ALG_NULL;
      symmetric.keyBits.sym = 0;
      symmetric.mode.sym = 0;
  
      nonceCaller.t.size = 0;
  
      encryptedSalt.t.size = 0;
  
       // Init session
      rval = StartAuthSessionWithParams( &authSession, TPM_RH_NULL, 0, TPM_RH_PLATFORM, 0, &nonceCaller, &encryptedSalt, TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_FlushContext( sysContext, authSession->sessionHandle );
      CheckPassed( rval );
      EndAuthSession( authSession );
  
      // Init session
      rval = StartAuthSessionWithParams( &authSession, TPM_RH_NULL, 0, TPM_RH_PLATFORM, 0, &nonceCaller, &encryptedSalt, 0xff, &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckFailed( rval, TPM_RC_VALUE + TPM_RC_P + TPM_RC_3 );
  
      // Try starting a bunch to see if resource manager handles this correctly.
      for( i = 0; i < ( sizeof(sessions) / sizeof (SESSION *) ); i++ )
      {
  //        DebugPrintf( NO_PREFIX, "i = 0x%4.4x\n", i );
  
          // Init session struct
          rval = StartAuthSessionWithParams( &sessions[i], TPM_RH_NULL, 0, TPM_RH_PLATFORM, 0, &nonceCaller, &encryptedSalt, TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
          CheckPassed( rval );
          DebugPrintf( NO_PREFIX, "Number of sessions created: %d\n\n", i+1 );
  
      }
      
  #ifdef SKIP_BAD_HANDLE_TEST
      printf("** Skipping bad session handle test\n");
  #else
      // Now try two ways of using a bad session handle.  Both should fail.
      // first way is to use as command parameter.
      TPMA_LOCALITY locality;
      TSS2_SYS_CMD_AUTHS sessionsDataIn;
      TPMS_AUTH_COMMAND *sessionDataArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionsDataIn.cmdAuths = &sessionDataArray[0];
      sessionsDataIn.cmdAuthsCount = 1;
  
      *(UINT8 *)( (void *)&locality ) = 0;
      locality.TPM_LOC_THREE = 1;
      rval = Tss2_Sys_PolicyLocality( sysContext, badSessionHandle, 0, locality, 0 );
      CheckFailed( rval, TSS2_RESMGRTPM_ERROR_LEVEL + TPM_RC_HANDLE + ( 1 << 8 ) );
  
      // Second way is to use as handle in session area.
      rval = Tss2_Sys_PolicyLocality( sysContext, sessions[0]->sessionHandle, &sessionsDataIn, locality, 0 );
      CheckFailed( rval, TSS2_RESMGRTPM_ERROR_LEVEL + TPM_RC_VALUE + TPM_RC_S + ( 1 << 8 ) );
  #endif // SKIP_1
      
      // clean up the sessions that I don't want here.
      for( i = 0; i < ( sizeof(sessions) / sizeof (SESSION *)); i++ )
      {
  //        DebugPrintf( NO_PREFIX, "i(2) = 0x%4.4x\n", i );
          rval = Tss2_Sys_FlushContext( sysContext, sessions[i]->sessionHandle );
  
          rval = EndAuthSession( sessions[i] );
      }
  
      // Now do some gap tests.
      rval = StartAuthSessionWithParams( &sessions[0], TPM_RH_NULL, 0, TPM_RH_PLATFORM, 0, &nonceCaller, &encryptedSalt, TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval );
  
      for( i = 1; i < ( sizeof(sessions) / sizeof (SESSION *) ); i++ )
      {
  //        DebugPrintf( NO_PREFIX, "i(3) = 0x%4.4x\n", i );
  
          rval = StartAuthSessionWithParams( &sessions[i], TPM_RH_NULL, 0, TPM_RH_PLATFORM, 0, &nonceCaller, &encryptedSalt, TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
          CheckPassed( rval );
  
          rval = Tss2_Sys_FlushContext( sysContext, sessions[i]->sessionHandle );
          CheckPassed( rval );
  
          rval = EndAuthSession( sessions[i] );
          CheckPassed( rval );
      }
  
      for( i = 0; i < ( sizeof(sessions) / sizeof (SESSION *) ); i++ )
      {
  //        DebugPrintf( NO_PREFIX, "i(4) = 0x%4.4x\n", i );
          rval = StartAuthSessionWithParams( &sessions[i], TPM_RH_NULL, 0, TPM_RH_PLATFORM, 0, &nonceCaller, &encryptedSalt, TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
          CheckPassed( rval );
  
          rval = Tss2_Sys_FlushContext( sysContext, sessions[i]->sessionHandle );
          CheckPassed( rval );
  
          rval = EndAuthSession( sessions[i] );
          CheckPassed( rval );
  
      }
  }
  
  void TestChangeEps()
  {
      UINT32 rval;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nCHANGE_EPS TESTS:\n" );
  
  	sessionsData.cmdAuthsCount = 1;
  
      // Init authHandle
      sessionsData.cmdAuths[0]->sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionsData.cmdAuths[0]->nonce.t.size = 0;
  
      // init hmac
      sessionsData.cmdAuths[0]->hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionsData.cmdAuths[0]->sessionAttributes ) ) = 0;
  
      rval = Tss2_Sys_ChangeEPS( sysContext, TPM_RH_PLATFORM, &sessionsData, &sessionsDataOut );
      CheckPassed( rval );
  
      sessionsData.cmdAuths[0]->hmac.t.size = 0x10;
  
      rval = Tss2_Sys_ChangeEPS( sysContext, TPM_RH_PLATFORM, &sessionsData, 0 );
      CheckFailed( rval, TPM_RC_1 + TPM_RC_S + TPM_RC_BAD_AUTH );
  }
  
  void TestChangePps()
  {
      UINT32 rval;
      TSS2_SYS_CMD_AUTHS sessionsData;
  
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nCHANGE_PPS TESTS:\n" );
  
      sessionsData.cmdAuthsCount = 1;
  
      // Init authHandle
      sessionsData.cmdAuths[0]->sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionsData.cmdAuths[0]->nonce.t.size = 0;
  
      // init hmac
      sessionsData.cmdAuths[0]->hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionsData.cmdAuths[0]->sessionAttributes ) ) = 0;
  
      rval = Tss2_Sys_ChangePPS( sysContext, TPM_RH_PLATFORM, &sessionsData, &sessionsDataOut );
      CheckPassed( rval );
  
      sessionsData.cmdAuths[0]->hmac.t.size = 0x10;
  
      rval = Tss2_Sys_ChangePPS( sysContext, TPM_RH_PLATFORM, &sessionsData, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_1 + TPM_RC_S + TPM_RC_BAD_AUTH );
  }
  
  void TestHierarchyChangeAuth()
  {
      UINT32 rval;
      TPM2B_AUTH      newAuth;
      TPMS_AUTH_COMMAND sessionData;
      TSS2_SYS_CMD_AUTHS sessionsData;
      int i;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
  
      sessionDataArray[0] = &sessionData;
  
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      DebugPrintf( NO_PREFIX, "\nHIERARCHY_CHANGE_AUTH TESTS:\n" );
  
      // Init authHandle
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      newAuth.t.size = 0;
      rval = Tss2_Sys_HierarchyChangeAuth( sysContext, TPM_RH_PLATFORM, &sessionsData, &newAuth, 0 );
      CheckPassed( rval );
  
      // Init new auth
      newAuth.t.size = 20;
      for( i = 0; i < newAuth.t.size; i++ )
          newAuth.t.buffer[i] = i;
  
      rval = Tss2_Sys_HierarchyChangeAuth( sysContext, TPM_RH_PLATFORM, &sessionsData, &newAuth, 0 );
      CheckPassed( rval );
  
      sessionData.hmac = newAuth;
      rval = Tss2_Sys_HierarchyChangeAuth( sysContext, TPM_RH_PLATFORM, &sessionsData, &newAuth, 0 );
      CheckPassed( rval );
  
      // Init new auth
      newAuth.t.size = 0;
  
      rval = Tss2_Sys_HierarchyChangeAuth( sysContext, TPM_RH_PLATFORM, &sessionsData, &newAuth, 0 );
      CheckPassed( rval );
  
      sessionsData.cmdAuths[0] = &sessionData;
      rval = Tss2_Sys_HierarchyChangeAuth( sysContext, TPM_RH_PLATFORM, &sessionsData, &newAuth, 0 );
      CheckFailed( rval, TPM_RC_1 + TPM_RC_S + TPM_RC_BAD_AUTH );
  
      rval = Tss2_Sys_HierarchyChangeAuth( sysContext, 0, &sessionsData, &newAuth, 0 );
      CheckFailed( rval, TPM_RC_1 + TPM_RC_VALUE );
  }
  
  #define PCR_0   0
  #define PCR_1   1
  #define PCR_2   2
  #define PCR_3   3
  #define PCR_4   4
  #define PCR_5   5
  #define PCR_6   6
  #define PCR_7   7
  #define PCR_8   8
  #define PCR_9   9
  #define PCR_10  10
  #define PCR_11  11
  #define PCR_12  12
  #define PCR_13  13
  #define PCR_14  14
  #define PCR_15  15
  #define PCR_16  16
  #define PCR_17  17
  #define PCR_18  18
  
  #define PCR_SIZE 20
  
  void TestPcrExtend()
  {
      UINT32 rval;
      TPMS_AUTH_COMMAND sessionData;
      TSS2_SYS_CMD_AUTHS sessionsData;
      UINT16 i, digestSize;
      TPML_PCR_SELECTION  pcrSelection;
      UINT32 pcrUpdateCounterBeforeExtend;
      UINT32 pcrUpdateCounterAfterExtend;
      UINT8 pcrBeforeExtend[PCR_SIZE];
      TPM2B_EVENT eventData;
      TPML_DIGEST pcrValues;
      TPML_DIGEST_VALUES digests;
      TPML_PCR_SELECTION pcrSelectionOut;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      DebugPrintf( NO_PREFIX, "\nPCR_EXTEND, PCR_EVENT, PCR_ALLOCATE, and PCR_READ TESTS:\n" );
  
      // Init authHandle
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      // Init digests
      digests.count = 1;
      digests.digests[0].hashAlg = TPM_ALG_SHA1;
      digestSize = GetDigestSize( digests.digests[0].hashAlg );
  
      for( i = 0; i < digestSize; i++ )
      {
          digests.digests[0].digest.sha1[i] = (UINT8)(i % 256);
      }
  
      pcrSelection.count = 1;
      pcrSelection.pcrSelections[0].hash = TPM_ALG_SHA1;
      pcrSelection.pcrSelections[0].sizeofSelect = 3;
  
      // Clear out PCR select bit field
      pcrSelection.pcrSelections[0].pcrSelect[0] = 0;
      pcrSelection.pcrSelections[0].pcrSelect[1] = 0;
      pcrSelection.pcrSelections[0].pcrSelect[2] = 0;
  
      // Now set the PCR you want to read
      SET_PCR_SELECT_BIT( pcrSelection.pcrSelections[0], PCR_17 );
  
      rval = Tss2_Sys_PCR_Read( sysContext, 0, &pcrSelection, &pcrUpdateCounterBeforeExtend, &pcrSelectionOut, &pcrValues, 0 );
      CheckPassed( rval );
  
      if( pcrValues.digests[0].t.size <= PCR_SIZE &&
              pcrValues.digests[0].t.size <= sizeof( pcrValues.digests[0].t.buffer ) )
          memcpy( &( pcrBeforeExtend[0] ), &( pcrValues.digests[0].t.buffer[0] ), pcrValues.digests[0].t.size );
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      rval = Tss2_Sys_PCR_Extend( sysContext, PCR_17, &sessionsData, &digests, 0  );
      CheckPassed( rval );
  
      rval = Tss2_Sys_PCR_Read( sysContext, 0, &pcrSelection, &pcrUpdateCounterAfterExtend, &pcrSelectionOut, &pcrValues, 0 );
      CheckPassed( rval );
  
      memcpy( &( pcrAfterExtend[0] ), &( pcrValues.digests[0].t.buffer[0] ), pcrValues.digests[0].t.size );
  
      if( pcrUpdateCounterBeforeExtend == pcrUpdateCounterAfterExtend )
      {
          DebugPrintf( NO_PREFIX, "ERROR!! pcrUpdateCounter didn't change value\n" );
          Cleanup();
      }
  
      if( 0 == memcmp( &( pcrBeforeExtend[0] ), &( pcrAfterExtend[0] ), 20 ) )
      {
          DebugPrintf( NO_PREFIX, "ERROR!! PCR didn't change value\n" );
          Cleanup();
      }
  
      pcrSelection.pcrSelections[0].sizeofSelect = 4;
  
      rval = Tss2_Sys_PCR_Read( sysContext, 0, &pcrSelection, &pcrUpdateCounterAfterExtend, 0, 0, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE );
  
      eventData.t.size = 4;
      eventData.t.buffer[0] = 0;
      eventData.t.buffer[1] = 0xff;
      eventData.t.buffer[2] = 0x55;
      eventData.t.buffer[3] = 0xaa;
  
      rval = Tss2_Sys_PCR_Event( sysContext, PCR_18, &sessionsData, &eventData, &digests, 0  );
      CheckPassed( rval );
  }
  
  void TestShutdown()
  {
      UINT32 rval;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
      TPMS_AUTH_RESPONSE sessionDataOut;
  
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nSHUTDOWN TESTS:\n" );
  
      rval = Tss2_Sys_Shutdown( sysContext, 0, TPM_SU_STATE, &sessionsDataOut );
      CheckPassed( rval );
  
      rval = Tss2_Sys_Shutdown( sysContext, 0, TPM_SU_CLEAR, &sessionsDataOut );
      CheckPassed( rval );
  
      if( !( tpmSpecVersion == 115 || tpmSpecVersion == 119 ) )
      {
          rval = Tss2_Sys_Shutdown( sysContext, 0, 0xff, 0 );
          CheckFailed( rval, TPM_RC_VALUE+TPM_RC_1+TPM_RC_P );
      }
  }
  
  void TestNV()
  {
      UINT32 rval;
      TPM2B_NV_PUBLIC publicInfo;
      TPM2B_AUTH  nvAuth;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
      int i;
      TPM2B_MAX_NV_BUFFER nvWriteData;
      TPM2B_MAX_NV_BUFFER nvData;
  
      TPM2B_NV_PUBLIC nvPublic;
      TPM2B_NAME nvName;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nNV INDEX TESTS:\n" );
  
      nvAuth.t.size = 20;
      for( i = 0; i < nvAuth.t.size; i++ ) {
          nvAuth.t.buffer[i] = (UINT8)i;
      }
  
      publicInfo.t.size = sizeof( TPMI_RH_NV_INDEX ) +
          sizeof( TPMI_ALG_HASH ) + sizeof( TPMA_NV ) + sizeof( UINT16) +
          sizeof( UINT16 );
      publicInfo.t.nvPublic.nvIndex = TPM20_INDEX_TEST1;
      publicInfo.t.nvPublic.nameAlg = TPM_ALG_SHA1;
  
      // First zero out attributes.
      *(UINT32 *)&( publicInfo.t.nvPublic.attributes ) = 0;
  
      // Now set the attributes.
      publicInfo.t.nvPublic.attributes.TPMA_NV_PPREAD = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PPWRITE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_WRITE_STCLEAR = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_ORDERLY = 1;
      publicInfo.t.nvPublic.authPolicy.t.size = 0;
      publicInfo.t.nvPublic.dataSize = 32;
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      INIT_SIMPLE_TPM2B_SIZE( nvData );
      rval = Tss2_Sys_NV_Read( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 32, 0, &nvData, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_2 + TPM_RC_HANDLE );
  
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM, &sessionsData, &nvAuth, &publicInfo, &sessionsDataOut );
      CheckPassed( rval );
  
      nvPublic.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( nvName );
      rval = Tss2_Sys_NV_ReadPublic( sysContext, TPM20_INDEX_TEST1, 0, &nvPublic, &nvName, 0 );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( nvData );
      rval = Tss2_Sys_NV_Read( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 32, 0, &nvData, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_NV_UNINITIALIZED );
  
      // Should fail since index is already defined.
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM, &sessionsData, &nvAuth, &publicInfo, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_NV_DEFINED );
  
      nvWriteData.t.size = 4;
      for( i = 0; i < nvWriteData.t.size; i++ )
          nvWriteData.t.buffer[i] = 0xff - i;
  
  #if 1
      //
      // Following, at one point, was commented out so that NVDefine will work on successive
      // invocations of client app.
      //
      // Noticed on 12/13/12, this doesn't seem to be necessary anymore.  Maybe something else
      // I did fixed it.
      //
      // Seems to be a bug in TPM 2.0 simulator that if:
      //   First pass of tpmclient.exe after restarting TPM 2.0 simulator will work fine.
      //   If NVWrite is done, subsequent invocations of tpmclient.exe will ALWAYS fail on
      //      first call to Tpm2NVDefineSpace with 0x2cb error. Removing NVWrite removes this.
      //      And restarting TPM 2.0 simulator will make it work the first time and fail
      //      subsequent times.
      //      Removing NVWrite works around this problem.
      //
      rval = Tss2_Sys_NV_Write( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, &nvWriteData, 0, &sessionsDataOut );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( nvData );
      rval = Tss2_Sys_NV_Read( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 32, 0, &nvData, &sessionsDataOut );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_WriteLock( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, &sessionsDataOut );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_Write( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, &nvWriteData, 0, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_NV_LOCKED );
  #endif
  
      // Now undefine the index.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 0 );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM, &sessionsData, &nvAuth, &publicInfo, 0 );
      CheckPassed( rval );
  
      // Now undefine the index so that next run will work correctly.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 0 );
      CheckPassed( rval );
  
      publicInfo.t.nvPublic.attributes.TPMA_NV_PPREAD = 0;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PPWRITE = 0;
      publicInfo.t.nvPublic.attributes.TPMA_NV_OWNERREAD = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_OWNERWRITE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE = 0;
      publicInfo.t.nvPublic.attributes.TPMA_NV_ORDERLY = 1;
      publicInfo.t.nvPublic.nvIndex = TPM20_INDEX_TEST2;
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_OWNER, &sessionsData, &nvAuth, &publicInfo, 0 );
      CheckPassed( rval );
  
      nvPublic.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( nvName );
      rval = Tss2_Sys_NV_ReadPublic( sysContext, TPM20_INDEX_TEST2, 0, &nvPublic, &nvName, 0 );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( nvData );
      rval = Tss2_Sys_NV_Read( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST2, &sessionsData, 32, 0, &nvData, 0 );
      CheckFailed( rval, TPM_RC_NV_AUTHORIZATION );
  
      // Now undefine the index.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_OWNER, TPM20_INDEX_TEST2, &sessionsData, 0 );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_OWNER, &sessionsData, &nvAuth, &publicInfo, 0 );
      CheckPassed( rval );
  
      // Now undefine the index so that next run will work correctly.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_OWNER, TPM20_INDEX_TEST2, &sessionsData, 0 );
      CheckPassed( rval );
  }
  
  void TestHierarchyControl()
  {
      UINT32 rval;
      TPM2B_NV_PUBLIC publicInfo;
      TPM2B_AUTH  nvAuth;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
      int i;
      TPM2B_NAME nvName;
      TPM2B_NV_PUBLIC nvPublic;
      TPM2B_MAX_NV_BUFFER nvData;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nHIERARCHY CONTROL TESTS:\n" );
  
      nvAuth.t.size = 20;
      for( i = 0; i < nvAuth.t.size; i++ ) {
          nvAuth.t.buffer[i] = i;
      }
  
      publicInfo.t.size = sizeof( TPMI_RH_NV_INDEX ) +
          sizeof( TPMI_ALG_HASH ) + sizeof( TPMA_NV ) + sizeof( UINT16) +
          sizeof( UINT16 );
      publicInfo.t.nvPublic.nvIndex = TPM20_INDEX_TEST1;
      publicInfo.t.nvPublic.nameAlg = TPM_ALG_SHA1;
  
      // First zero out attributes.
      *(UINT32 *)&( publicInfo.t.nvPublic.attributes ) = 0;
  
      // Now set the attributes.
      publicInfo.t.nvPublic.attributes.TPMA_NV_PPREAD = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PPWRITE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PPWRITE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_WRITE_STCLEAR = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_ORDERLY = 1;
      publicInfo.t.nvPublic.authPolicy.t.size = 0;
      publicInfo.t.nvPublic.dataSize = 32;
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM, &sessionsData, &nvAuth, &publicInfo, 0 );
      CheckPassed( rval );
  
      // Test SAPI for case where nvPublic.t.size != 0
      nvPublic.t.size = 0xff;
      INIT_SIMPLE_TPM2B_SIZE( nvName );
      rval = Tss2_Sys_NV_ReadPublic( sysContext, TPM20_INDEX_TEST1, 0, &nvPublic, &nvName, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE );
  
      nvPublic.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( nvName );
      rval = Tss2_Sys_NV_ReadPublic( sysContext, TPM20_INDEX_TEST1, 0, &nvPublic, &nvName, 0 );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_Read( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 32, 0, &nvData, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_NV_UNINITIALIZED );
  
      rval = Tss2_Sys_HierarchyControl( sysContext, TPM_RH_PLATFORM, &sessionsData, TPM_RH_PLATFORM, NO, &sessionsDataOut );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_Read( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 32, 0, &nvData, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_1 + TPM_RC_HIERARCHY );
  
      rval = Tss2_Sys_HierarchyControl( sysContext, TPM_RH_PLATFORM, &sessionsData, TPM_RH_PLATFORM, YES, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_1 + TPM_RC_HIERARCHY );
  
      // Need to do TPM reset and Startup to re-enable platform hierarchy.
      rval = TpmReset();
      CheckPassed(rval);
  
      rval = Tss2_Sys_Startup ( sysContext, TPM_SU_CLEAR );
      CheckPassed( rval );
  
      rval = Tss2_Sys_HierarchyControl( sysContext, TPM_RH_PLATFORM, &sessionsData, TPM_RH_PLATFORM, YES, &sessionsDataOut );
      CheckPassed( rval );
  
      // Now undefine the index so that next run will work correctly.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &sessionsData, 0 );
      CheckPassed( rval );
  }
  
  TPM2B_PUBLIC    inPublic = { { sizeof( TPM2B_PUBLIC ) - 2, } };
  
  void TestCreate(){
      UINT32 rval;
      TPM2B_SENSITIVE_CREATE  inSensitive = { { sizeof( TPM2B_SENSITIVE_CREATE ) - 2, } };
      TPM2B_DATA              outsideInfo = { { sizeof( TPM2B_DATA ) - 2, } };
      TPML_PCR_SELECTION      creationPCR;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
  
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  	TPM2B_NAME name = { { sizeof( TPM2B_NAME ) - 2, } };
  	TPM2B_NAME name1 = { { sizeof( TPM2B_NAME ) - 2, } };
      TPM2B_PRIVATE outPrivate = { { sizeof( TPM2B_PRIVATE ) - 2, } };
      TPM2B_PUBLIC outPublic = { { sizeof( TPM2B_PUBLIC ) - 2, } };
      TPM2B_CREATION_DATA creationData =  { { sizeof( TPM2B_CREATION_DATA ) - 2, } };
  	TPM2B_DIGEST creationHash = { { sizeof( TPM2B_DIGEST ) - 2, } };
  	TPMT_TK_CREATION creationTicket = { 0, 0, { { sizeof( TPM2B_DIGEST ) - 2, } } };
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nCREATE, CREATE PRIMARY, and LOAD TESTS:\n" );
  
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.data.t.size = 0;
      inSensitive.t.size = loadedSha1KeyAuth.b.size + 2;
  
      inPublic.t.publicArea.type = TPM_ALG_RSA;
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA1;
  
      // First clear attributes bit field.
      *(UINT32 *)&( inPublic.t.publicArea.objectAttributes) = 0;
      inPublic.t.publicArea.objectAttributes.restricted = 1;
      inPublic.t.publicArea.objectAttributes.userWithAuth = 1;
      inPublic.t.publicArea.objectAttributes.decrypt = 1;
      inPublic.t.publicArea.objectAttributes.fixedTPM = 1;
      inPublic.t.publicArea.objectAttributes.fixedParent = 1;
      inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin = 1;
  
      inPublic.t.publicArea.authPolicy.t.size = 0;
  
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_ECB;
      inPublic.t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 1024;
      inPublic.t.publicArea.parameters.rsaDetail.exponent = 0;
  
      inPublic.t.publicArea.unique.rsa.t.size = 0;
  
      outsideInfo.t.size = 0;
      creationPCR.count = 0;
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 2048;
  
      // Do SAPI test for non-zero sized outPublic
      outPublic.t.size = 0xff;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_CreatePrimary( sysContext, TPM_RH_PLATFORM, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR, &handle2048rsa, &outPublic, &creationData, &creationHash,
              &creationTicket, &name, &sessionsDataOut );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE );
  
      rval = Tss2_Sys_FlushContext( sysContext, handle2048rsa );
      CheckPassed( rval );
  
      outPublic.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( creationData );
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_CreatePrimary( sysContext, TPM_RH_PLATFORM, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR, &handle2048rsa, &outPublic, &creationData, &creationHash,
              &creationTicket, &name, &sessionsDataOut );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE );
  
      rval = Tss2_Sys_FlushContext( sysContext, handle2048rsa );
      CheckPassed( rval );
  
      outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_CreatePrimary( sysContext, TPM_RH_PLATFORM, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR, &handle2048rsa, &outPublic, &creationData, &creationHash,
              &creationTicket, &name, &sessionsDataOut );
      CheckPassed( rval );
  
      DebugPrintf( NO_PREFIX, "\nNew key successfully created in platform hierarchy (RSA 2048).  Handle: 0x%8.8x\n",
              handle2048rsa );
  
      sessionData.hmac.t.size = 2;
      sessionData.hmac.t.buffer[0] = 0x00;
      sessionData.hmac.t.buffer[1] = 0xff;
  
      inPublic.t.publicArea.type = TPM_ALG_KEYEDHASH;
      inPublic.t.publicArea.objectAttributes.decrypt = 0;
      inPublic.t.publicArea.objectAttributes.sign = 1;
  
      inPublic.t.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_HMAC;
      inPublic.t.publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg = TPM_ALG_SHA1;
  
      inPublic.t.publicArea.unique.keyedHash.t.size = 0;
  
      outsideInfo.t.size = 0;
      outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( outPrivate );
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      rval = TSS2_RETRY_EXP( Tss2_Sys_Create( sysContext, handle2048rsa, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR,
              &outPrivate, &outPublic, &creationData,
              &creationHash, &creationTicket, &sessionsDataOut ));
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_Load ( sysContext, handle2048rsa, &sessionsData, &outPrivate, &outPublic,
              &loadedSha1KeyHandle, &name, &sessionsDataOut);
      CheckPassed( rval );
  
      rval = (*HandleToNameFunctionPtr)( loadedSha1KeyHandle, &name1 );
      CheckPassed( rval );
      DebugPrintf( NO_PREFIX, "Name of loaded key: " );
      PrintSizedBuffer( (TPM2B *)&name1 );
  
      rval = CompareTPM2B( &name.b, &name1.b );
      CheckPassed( rval );
  
      DebugPrintf( NO_PREFIX, "\nLoaded key handle:  %8.8x\n", loadedSha1KeyHandle );
  }
  
  void TestEvict()
  {
      TPM_RC rval = TPM_RC_SUCCESS;
      TPM2B_SENSITIVE_CREATE  inSensitive = { { sizeof( TPM2B_SENSITIVE_CREATE ) - 2, } };
      TPM2B_DATA              outsideInfo = { { sizeof( TPM2B_DATA ) - 2, } };
      TPML_PCR_SELECTION      creationPCR;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  
      TPM2B_PRIVATE outPrivate = { { sizeof( TPM2B_PRIVATE ) - 2, } };
      TPM2B_PUBLIC outPublic = { { sizeof( TPM2B_PUBLIC ) - 2, } };
      TPM2B_CREATION_DATA creationData =  { { sizeof( TPM2B_CREATION_DATA ) - 2, } };
  	TPM2B_DIGEST creationHash = { { sizeof( TPM2B_DIGEST ) - 2, } };
  	TPMT_TK_CREATION creationTicket = { 0, 0, { { sizeof( TPM2B_DIGEST ) - 2, } } };
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
      sessionsData.cmdAuthsCount = 1;
  
      sessionsDataOut.rspAuthsCount = 1;
  
      outsideInfo.t.size = 0;
      creationPCR.count = 0;
  
      DebugPrintf( NO_PREFIX, "\nEVICT CONTROL TESTS:\n" );
  
      // Make transient key persistent.
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      rval = Tss2_Sys_EvictControl( sysContext, TPM_RH_PLATFORM, handle2048rsa, &sessionsData, 0x81800000, &sessionsDataOut );
      CheckPassed( rval );
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      // Create new key under persistent one.
      sessionData.hmac.t.size = 2;
      sessionData.hmac.t.buffer[0] = 0x00;
      sessionData.hmac.t.buffer[1] = 0xff;
  
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA1;
      inPublic.t.publicArea.type = TPM_ALG_KEYEDHASH;
      inPublic.t.publicArea.objectAttributes.decrypt = 0;
      inPublic.t.publicArea.objectAttributes.sign = 1;
  
      inPublic.t.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_HMAC;
      inPublic.t.publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg = TPM_ALG_SHA1;
  
      inPublic.t.publicArea.unique.keyedHash.t.size = 0;
  
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.data.t.size = 0;
      inSensitive.t.size = loadedSha1KeyAuth.b.size + 2;
  
      outsideInfo.t.size = 0;
      outPublic.t.size = 0;
      creationData.t.size = 0;
  
      // Try creating a key under the persistent key using a different context.
      rval = Tss2_Sys_Create( sysContext, 0x81800000, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR,
              &outPrivate, &outPublic, &creationData,
              &creationHash, &creationTicket, &sessionsDataOut );
      CheckPassed( rval );
  
      outsideInfo.t.size = 0;
      outPublic.t.size = 0;
      creationData.t.size = 0;
  
      // Try creating a key under the transient key.  This should work, too.
      INIT_SIMPLE_TPM2B_SIZE( outPrivate );
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      rval = Tss2_Sys_Create( sysContext, handle2048rsa, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR,
              &outPrivate, &outPublic, &creationData,
              &creationHash, &creationTicket, &sessionsDataOut );
      CheckPassed( rval );
  
      // Reset persistent key to be transitent.
      sessionData.hmac.t.size = 0;
      rval = Tss2_Sys_EvictControl( sysContext, TPM_RH_PLATFORM, 0x81800000, &sessionsData, 0x81800000, &sessionsDataOut );
      CheckPassed( rval );
  }
  
  TPM_RC DefineNvIndex( TPMI_RH_PROVISION authHandle, TPMI_SH_AUTH_SESSION sessionAuthHandle, TPM2B_AUTH *auth, TPM2B_DIGEST *authPolicy,
      TPMI_RH_NV_INDEX nvIndex, TPMI_ALG_HASH nameAlg, TPMA_NV attributes, UINT16 size  )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
      TPM2B_NV_PUBLIC publicInfo;
  
      // Command and response session data structures.
      TPMS_AUTH_COMMAND sessionData = { sessionAuthHandle, };
      TPMS_AUTH_RESPONSE sessionDataOut;
      TPMS_AUTH_COMMAND *sessionDataArray[1] = { &sessionData };
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1] = { &sessionDataOut };
      TSS2_SYS_CMD_AUTHS sessionsData = { 1, &sessionDataArray[0] };
      TSS2_SYS_RSP_AUTHS sessionsDataOut = { 1, &sessionDataOutArray[0] };
      // Init nonce.
      sessionData.nonce.t.size = 0;
      // init hmac
      sessionData.hmac.t.size = 0;
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      attributes.TPMA_NV_ORDERLY = 1;
  
      // Init public info structure.
      publicInfo.t.nvPublic.attributes = attributes;
      CopySizedByteBuffer( &publicInfo.t.nvPublic.authPolicy.b, &authPolicy->b );
      publicInfo.t.nvPublic.dataSize = size;
      publicInfo.t.size = sizeof( TPMI_RH_NV_INDEX ) +
              sizeof( TPMI_ALG_HASH ) + sizeof( TPMA_NV ) + sizeof( UINT16) +
              sizeof( UINT16 );
      publicInfo.t.nvPublic.nvIndex = nvIndex;
      publicInfo.t.nvPublic.nameAlg = nameAlg;
  
      // Create the index
      rval = Tss2_Sys_NV_DefineSpace( sysContext, authHandle, &sessionsData, auth, &publicInfo, &sessionsDataOut );
  
      return rval;
  }
  
  typedef struct {
      char name[50];
      TPM_RC (*buildPolicyFn )( TSS2_SYS_CONTEXT *sysContext, SESSION *trialPolicySession, TPM2B_DIGEST *policyDigest );
      TPM_RC (*createObjectFn )( TSS2_SYS_CONTEXT *sysContext, SESSION **policySession, TPM2B_DIGEST *policyDigest );
      TPM_RC (*testPolicyFn )( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession );
  } POLICY_TEST_SETUP;
  
  TPM_RC BuildPolicy( TSS2_SYS_CONTEXT *sysContext, SESSION **policySession,
      TPM_RC (*buildPolicyFn )( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession, TPM2B_DIGEST *policyDigest ),
      TPM2B_DIGEST *policyDigest, bool trialSession )
  {
      // NOTE:  this policySession will be either a trial or normal policy session
      // depending on the value of the passed in trialSession parameter.
      TPM2B_ENCRYPTED_SECRET  encryptedSalt = { {0}, };
      TPMT_SYM_DEF symmetric;
      TPM_RC rval;
      TPM2B_NONCE nonceCaller;
  
      nonceCaller.t.size = 0;
  
      // Start policy session.
      symmetric.algorithm = TPM_ALG_NULL;
      rval = StartAuthSessionWithParams( policySession, TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller, &encryptedSalt, trialSession ? TPM_SE_TRIAL : TPM_SE_POLICY , &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      if( rval != TPM_RC_SUCCESS )
          return rval;
  
      // Send policy command.
      rval = ( *buildPolicyFn )( sysContext, *policySession, policyDigest );
      CheckPassed( rval );
  
      // Get policy hash.
      INIT_SIMPLE_TPM2B_SIZE( *policyDigest );
      rval = Tss2_Sys_PolicyGetDigest( sysContext, (*policySession)->sessionHandle,
              0, policyDigest, 0 );
      CheckPassed( rval );
  
      if( trialSession )
      {
          // Need to flush the session here.
          rval = Tss2_Sys_FlushContext( sysContext, (*policySession)->sessionHandle );
          CheckPassed( rval );
  
          // And remove the session from sessions table.
          rval = EndAuthSession( *policySession );
          CheckPassed( rval );
      }
  
      return rval;
  }
  
  TPM_RC CreateNVIndex( TSS2_SYS_CONTEXT *sysContext, SESSION **policySession, TPM2B_DIGEST *policyDigest )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
      TPMA_LOCALITY locality;
      TPM2B_ENCRYPTED_SECRET encryptedSalt = { {0}, };
      TPMT_SYM_DEF symmetric;
      TPMA_NV nvAttributes;
      TPM2B_AUTH  nvAuth;
      TPM2B_NONCE nonceCaller;
  
      nonceCaller.t.size = 0;
  
      // Since locality is a fairly simple command and we can guarantee
      // its correctness, we don't need a trial session for this.
  
      // Start real policy session
      symmetric.algorithm = TPM_ALG_NULL;
      rval = StartAuthSessionWithParams( policySession, TPM_RH_NULL,
              0, TPM_RH_NULL, 0, &nonceCaller, &encryptedSalt, TPM_SE_POLICY,
              &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval );
  
      // Send PolicyLocality command
      *(UINT8 *)( (void *)&locality ) = 0;
      locality.TPM_LOC_THREE = 1;
      rval = Tss2_Sys_PolicyLocality( sysContext, (*policySession)->sessionHandle,
              0, locality, 0 );
      CheckPassed( rval );
  
      // Read policyHash
      INIT_SIMPLE_TPM2B_SIZE( *policyDigest );
      rval = Tss2_Sys_PolicyGetDigest( sysContext,
              (*policySession)->sessionHandle, 0, policyDigest, 0 );
      CheckPassed( rval );
  
      nvAuth.t.size = 0;
  
      // Now set the attributes.
      *(UINT32 *)( (void *)&nvAttributes ) = 0;
      nvAttributes.TPMA_NV_POLICYREAD = 1;
      nvAttributes.TPMA_NV_POLICYWRITE = 1;
      nvAttributes.TPMA_NV_PLATFORMCREATE = 1;
  
      rval = DefineNvIndex( TPM_RH_PLATFORM, TPM_RS_PW, &nvAuth, policyDigest,
              TPM20_INDEX_PASSWORD_TEST, TPM_ALG_SHA256, nvAttributes, 32  );
      CheckPassed( rval );
  
      AddEntity( TPM20_INDEX_PASSWORD_TEST, &nvAuth );
      CheckPassed( rval );
  
      return rval;
  }
  
  
  TPM_RC TestLocality( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession )
  {
      TSS2_RC rval = TPM_RC_SUCCESS;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TPM2B_MAX_NV_BUFFER nvWriteData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut = { 1, };
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      // Init write data.
      nvWriteData.t.size = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0]->sessionHandle = policySession->sessionHandle;
      sessionsData.cmdAuths[0]->nonce.t.size = 0;
      sessionsData.cmdAuths[0]->hmac.t.size = 0;
  
      *(UINT8 *)( (void *)&( sessionsData.cmdAuths[0]->sessionAttributes ) ) = 0;
       sessionsData.cmdAuths[0]->sessionAttributes.continueSession = 1;
  
      rval = SetLocality( sysContext, 2 );
      CheckPassed( rval );
  
      // Do NV write using open session's policy.
      rval = Tss2_Sys_NV_Write( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &sessionsData, &nvWriteData, 0, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_LOCALITY );
  
      rval = SetLocality( sysContext, 3 );
      CheckPassed( rval );
  
      // Do NV write using open session's policy.
      rval = Tss2_Sys_NV_Write( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &sessionsData, &nvWriteData, 0, &sessionsDataOut );
      CheckPassed( rval );
  
      // Do another NV write using open session's policy.
      rval = Tss2_Sys_NV_Write( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &sessionsData, &nvWriteData, 0, &sessionsDataOut );
      CheckFailed( rval, TPM_RC_POLICY_FAIL + TPM_RC_S + TPM_RC_1 );
  
      // Delete NV index
      sessionsData.cmdAuths[0]->sessionHandle = TPM_RS_PW;
      sessionsData.cmdAuths[0]->nonce.t.size = 0;
      sessionsData.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
      sessionData.hmac.t.size = 0;
  
      // Now undefine the index.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM,
              TPM20_INDEX_PASSWORD_TEST, &sessionsData, 0 );
      CheckPassed( rval );
  
      rval = DeleteEntity( TPM20_INDEX_PASSWORD_TEST );
      CheckPassed( rval );
  
      return rval;
  }
  
  UINT8 passwordPCRTestPassword[] = "password PCR";
  UINT8 dataBlob[] = "some data";
  TPM_HANDLE blobHandle;
  TPM2B_AUTH blobAuth;
  
  TPM_RC BuildPasswordPolicy( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession, TPM2B_DIGEST *policyDigest )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
  
      rval = Tss2_Sys_PolicyPassword( sysContext, policySession->sessionHandle, 0, 0 );
      CheckPassed( rval );
  
      return rval;
  }
  
  TPM_RC BuildAuthValuePolicy( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession, TPM2B_DIGEST *policyDigest )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
  
      rval = Tss2_Sys_PolicyAuthValue( sysContext, policySession->sessionHandle, 0, 0 );
      CheckPassed( rval );
  
      return rval;
  }
  
  
  TPM_RC BuildPasswordPcrPolicy( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession, TPM2B_DIGEST *policyDigest )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
      TPM2B_DIGEST pcrDigest;
      TPML_PCR_SELECTION pcrs;
      TPML_DIGEST pcrValues;
      UINT32 pcrUpdateCounter;
      TPML_PCR_SELECTION pcrSelectionOut;
  
      pcrDigest.t.size = 0;
      rval = Tss2_Sys_PolicyPassword( sysContext, policySession->sessionHandle, 0, 0 );
      CheckPassed( rval );
  
      pcrs.count = 1;
      pcrs.pcrSelections[0].hash = TPM_ALG_SHA1;
      pcrs.pcrSelections[0].sizeofSelect = 3;
      pcrs.pcrSelections[0].pcrSelect[0] = 0;
      pcrs.pcrSelections[0].pcrSelect[1] = 0;
      pcrs.pcrSelections[0].pcrSelect[2] = 0;
      SET_PCR_SELECT_BIT( pcrs.pcrSelections[0], PCR_0 );
      SET_PCR_SELECT_BIT( pcrs.pcrSelections[0], PCR_3 );
  
      //
      // Compute pcrDigest
      //
      // Read PCRs
      rval = Tss2_Sys_PCR_Read( sysContext, 0, &pcrs, &pcrUpdateCounter, &pcrSelectionOut, &pcrValues, 0 );
      CheckPassed( rval );
  
      // Hash them together
      INIT_SIMPLE_TPM2B_SIZE( pcrDigest );
      rval = TpmHashSequence( policySession->authHash, pcrValues.count, &pcrValues.digests[0], &pcrDigest );
      CheckPassed( rval );
  
      rval = Tss2_Sys_PolicyPCR( sysContext, policySession->sessionHandle, 0, &pcrDigest, &pcrs, 0 );
      CheckPassed( rval );
  
      return rval;
  }
  
  
  TPM_RC CreateDataBlob( TSS2_SYS_CONTEXT *sysContext, SESSION **policySession, TPM2B_DIGEST *policyDigest )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
      TPMS_AUTH_COMMAND cmdAuth;
      TPMS_AUTH_COMMAND *cmdSessionArray[1] = { &cmdAuth };
      TSS2_SYS_CMD_AUTHS cmdAuthArray = { 1, &cmdSessionArray[0] };
      TPM2B_SENSITIVE_CREATE inSensitive;
      TPM2B_PUBLIC inPublic;
      TPM2B_DATA outsideInfo = { { 0, } };
      TPML_PCR_SELECTION creationPcr = { 0 };
      TPM2B_PUBLIC outPublic;
      TPM2B_CREATION_DATA creationData;
      TPM_HANDLE srkHandle;
      TPM2B_DIGEST creationHash;
      TPMT_TK_CREATION creationTicket;
      TPM2B_NAME srkName, blobName;
  	TPM2B_DIGEST data;
      TPM2B_PRIVATE outPrivate;
  
      cmdAuth.sessionHandle = TPM_RS_PW;
      cmdAuth.nonce.t.size = 0;
      *( (UINT8 *)((void *)&cmdAuth.sessionAttributes ) ) = 0;
      cmdAuth.hmac.t.size = 0;
  
      inSensitive.t.sensitive.userAuth.t.size = 0;
      inSensitive.t.sensitive.data.t.size = 0;
  
      inPublic.t.publicArea.type = TPM_ALG_RSA;
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA1;
      *(UINT32 *)&( inPublic.t.publicArea.objectAttributes) = 0;
      inPublic.t.publicArea.objectAttributes.restricted = 1;
      inPublic.t.publicArea.objectAttributes.userWithAuth = 1;
      inPublic.t.publicArea.objectAttributes.decrypt = 1;
      inPublic.t.publicArea.objectAttributes.fixedTPM = 1;
      inPublic.t.publicArea.objectAttributes.fixedParent = 1;
      inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin = 1;
      inPublic.t.publicArea.authPolicy.t.size = 0;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CBC;
      inPublic.t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 2048;
      inPublic.t.publicArea.parameters.rsaDetail.exponent = 0;
      inPublic.t.publicArea.unique.rsa.t.size = 0;
  
      outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      INIT_SIMPLE_TPM2B_SIZE( srkName );
      rval = Tss2_Sys_CreatePrimary( sysContext, TPM_RH_PLATFORM, &cmdAuthArray,
              &inSensitive, &inPublic, &outsideInfo, &creationPcr,
              &srkHandle, &outPublic, &creationData, &creationHash,
              &creationTicket, &srkName, 0 );
      CheckPassed( rval );
  
      cmdAuth.sessionHandle = TPM_RS_PW;
  
      inSensitive.t.sensitive.userAuth.t.size = 0;
      blobAuth.t.size = sizeof( passwordPCRTestPassword );
      memcpy( &blobAuth.t.buffer, passwordPCRTestPassword, sizeof( passwordPCRTestPassword ) );
      CopySizedByteBuffer( &(inSensitive.t.sensitive.userAuth.b ), &blobAuth.b );
      data.t.size = sizeof( dataBlob );
      memcpy( &data.t.buffer, dataBlob, sizeof( dataBlob ) );
      CopySizedByteBuffer( &(inSensitive.t.sensitive.data.b ), &data.b );
  
      inPublic.t.publicArea.type = TPM_ALG_KEYEDHASH;
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA256;
      inPublic.t.publicArea.objectAttributes.restricted = 0;
      inPublic.t.publicArea.objectAttributes.decrypt = 0;
      inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin = 0;
      CopySizedByteBuffer( &( inPublic.t.publicArea.authPolicy.b), &( policyDigest->b ) );
      inPublic.t.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_NULL;
      inPublic.t.publicArea.unique.keyedHash.t.size = 0;
  
      outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( outPrivate );
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      rval = Tss2_Sys_Create( sysContext, srkHandle, &cmdAuthArray,
              &inSensitive, &inPublic, &outsideInfo, &creationPcr,
              &outPrivate, &outPublic, &creationData, &creationHash,
              &creationTicket, 0 );
      CheckPassed( rval );
  
      // Now we need to load the object.
      INIT_SIMPLE_TPM2B_SIZE( blobName );
      rval = Tss2_Sys_Load( sysContext, srkHandle, &cmdAuthArray, &outPrivate, &outPublic, &blobHandle, &blobName, 0 );
      CheckPassed( rval );
  
      return rval;
  }
  
  TPM_RC AuthValueUnseal( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
      TPM2B_SENSITIVE_DATA outData;
      TPMS_AUTH_COMMAND cmdAuth;
      TPMS_AUTH_COMMAND *cmdSessionArray[1] = { &cmdAuth };
      TSS2_SYS_CMD_AUTHS cmdAuthArray = { 1, &cmdSessionArray[0] };
  
      cmdAuth.sessionHandle = policySession->sessionHandle;
      cmdAuth.nonce.t.size = 0;
      *( (UINT8 *)((void *)&cmdAuth.sessionAttributes ) ) = 0;
      cmdAuth.sessionAttributes.continueSession = 1;
      cmdAuth.hmac.t.size = 0;
  
      // Now try to unseal the blob without setting the HMAC.
      // This test should fail.
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_Unseal( sysContext, blobHandle, &cmdAuthArray, &outData, 0 );
      CheckFailed( rval, TPM_RC_S + TPM_RC_1 + TPM_RC_AUTH_FAIL );
  
      // Clear DA lockout.
      TestDictionaryAttackLockReset();
  
      //
      // Now try to unseal the blob after setting the HMAC.
      // This test should pass.
      //
  
      // First, call Prepare.
      rval = Tss2_Sys_Unseal_Prepare( sysContext, blobHandle );
      CheckPassed( rval );
  
      rval = AddEntity( blobHandle, &blobAuth );
      CheckPassed( rval );
  
      // Roll nonces for command.
      RollNonces( policySession, &cmdAuth.nonce );
  
      // Now generate the HMAC.
      rval = ComputeCommandHmacs( sysContext,
              blobHandle,
              TPM_HT_NO_HANDLE, &cmdAuthArray, 1 );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_Unseal( sysContext, blobHandle, &cmdAuthArray, &outData, 0 );
      CheckPassed( rval );
  
      rval = DeleteEntity( blobHandle );
      CheckPassed( rval );
  
      // Add test to make sure we unsealed correctly.
  
      // Now we'll want to flush the data blob and remove it
      // from resource manager tables.
      rval = Tss2_Sys_FlushContext( sysContext, blobHandle );
      CheckPassed( rval );
  
      return rval;
  }
  
  TPM_RC PasswordUnseal( TSS2_SYS_CONTEXT *sysContext, SESSION *policySession )
  {
      TPM_RC rval = TPM_RC_SUCCESS;
      TPM2B_SENSITIVE_DATA outData;
      TPMS_AUTH_COMMAND cmdAuth;
      TPMS_AUTH_COMMAND *cmdSessionArray[1] = { &cmdAuth };
      TSS2_SYS_CMD_AUTHS cmdAuthArray = { 1, &cmdSessionArray[0] };
  
      cmdAuth.sessionHandle = policySession->sessionHandle;
      cmdAuth.nonce.t.size = 0;
      *( (UINT8 *)((void *)&cmdAuth.sessionAttributes ) ) = 0;
      cmdAuth.sessionAttributes.continueSession = 1;
      cmdAuth.hmac.t.size = 0;
  
      // Now try to unseal the blob without setting the password.
      // This test should fail.
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_Unseal( sysContext, blobHandle, &cmdAuthArray, &outData, 0 );
      CheckFailed( rval, TPM_RC_S + TPM_RC_1 + TPM_RC_AUTH_FAIL );
  
      // Clear DA lockout.
      TestDictionaryAttackLockReset();
  
      // Now try to unseal the blob after setting the password.
      // This test should pass.
      INIT_SIMPLE_TPM2B_SIZE( outData );
      cmdAuth.hmac.t.size = sizeof( passwordPCRTestPassword );
      memcpy( &cmdAuth.hmac.t.buffer, passwordPCRTestPassword, sizeof( passwordPCRTestPassword ) );
      rval = Tss2_Sys_Unseal( sysContext, blobHandle, &cmdAuthArray, &outData, 0 );
      CheckPassed( rval );
  
      // Add test to make sure we unsealed correctly.
  
      // Now we'll want to flush the data blob and remove it
      // from resource manager tables.
      rval = Tss2_Sys_FlushContext( sysContext, blobHandle );
      CheckPassed( rval );
  
      return rval;
  }
  
  POLICY_TEST_SETUP policyTestSetups[] =
  {
      // NOTE:  Since locality is a fairly simple command and we
      // can guarantee its correctness, we don't need a trial
      // session for this. buildPolicyFn pointer can be 0 in
      // this case.
      { "LOCALITY", 0, CreateNVIndex, TestLocality },
      { "PASSWORD", BuildPasswordPolicy, CreateDataBlob, PasswordUnseal },
      #ifndef SKIP_PASSWORD_PCR_POLICY_TEST
      { "PASSWORD/PCR", BuildPasswordPcrPolicy, CreateDataBlob, PasswordUnseal },
      #endif
      #ifndef SKIP_AUTH_VALUE_POLICY_TEST
      { "AUTHVALUE", BuildAuthValuePolicy, CreateDataBlob, AuthValueUnseal },
      #endif
      // TBD...
  };
  
  void TestPolicy()
  {
      UINT32 rval;
      unsigned int i;
      SESSION *policySession = 0;
  
      DebugPrintf( NO_PREFIX, "\nPOLICY TESTS:\n" );
  
      for( i = 0; i < ( sizeof( policyTestSetups ) / sizeof( POLICY_TEST_SETUP ) ); i++ )
      {
          TPM2B_DIGEST policyDigest;
  
          policyDigest.t.size = 0;
  
          rval = TPM_RC_SUCCESS;
  
          DebugPrintf( NO_PREFIX, "Policy Test: %s\n", policyTestSetups[i].name );
  
          // Create trial policy session and run policy commands, in order to create policyDigest.
          if( policyTestSetups[i].buildPolicyFn != 0)
          {
              rval = BuildPolicy( sysContext, &policySession, policyTestSetups[i].buildPolicyFn, &policyDigest, true );
              CheckPassed( rval );
  #ifdef DEBUG
              DebugPrintf( NO_PREFIX, "Built policy digest:  \n" );
              DebugPrintBuffer( NO_PREFIX, &(policyDigest.t.buffer[0]), policyDigest.t.size );
  #endif
          }
  
          // Create entity that will use that policyDigest as authPolicy.
          if( policyTestSetups[i].createObjectFn != 0 )
          {
  #ifdef DEBUG
              DebugPrintf( NO_PREFIX, "Policy digest used to create object:  \n" );
              DebugPrintBuffer( NO_PREFIX, &(policyDigest.t.buffer[0]), policyDigest.t.size );
  #endif
  
              rval = ( *policyTestSetups[i].createObjectFn )( sysContext, &policySession, &policyDigest);
              CheckPassed( rval );
          }
  
          // Create real policy session and run policy commands; after this we're ready
          // to authorize actions on the entity.
          if( policyTestSetups[i].buildPolicyFn != 0)
          {
              rval = BuildPolicy( sysContext, &policySession, policyTestSetups[i].buildPolicyFn, &policyDigest, false );
              CheckPassed( rval );
  #ifdef DEBUG
              DebugPrintf( NO_PREFIX, "Command policy digest:  \n" );
              DebugPrintBuffer( NO_PREFIX, &(policyDigest.t.buffer[0]), policyDigest.t.size );
  #endif
          }
  
          if( policySession )
          {
              // Now do tests by authorizing actions on the entity.
              rval = ( *policyTestSetups[i].testPolicyFn)( sysContext, policySession );
              CheckPassed( rval );
  
              // Need to flush the session here.
              rval = Tss2_Sys_FlushContext( sysContext, policySession->sessionHandle );
              CheckPassed( rval );
  
              // And remove the session from test app session table.
              rval = EndAuthSession( policySession );
          }
          else
          {
              CheckFailed( rval, 0xffffffff );
          }
  
          CheckPassed( rval );
      }
  }
  
  #define MAX_TEST_SEQUENCES 10
  void TestHash()
  {
      UINT32 rval;
      TPM2B_AUTH      auth;
      TPMI_DH_OBJECT  sequenceHandle[MAX_TEST_SEQUENCES];
      TPMS_AUTH_COMMAND sessionData, sessionData1;
      TPMS_AUTH_RESPONSE sessionDataOut, sessionDataOut1;
      TSS2_SYS_CMD_AUTHS sessionsData;
      int i;
      TPM2B_MAX_BUFFER dataToHash;
  
      UINT8           memoryToHash[] =
      {
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
            0xde, 0xad, 0xbe, 0xef
      };
  
      // Known good hash of above memory.
      UINT8           goodHashValue[] =
              { 0xB3, 0xFD, 0x6A, 0xD2, 0x9F, 0xD0, 0x13, 0x52, 0xBA, 0xFC,
                0x8B, 0x22, 0xC9, 0x6D, 0x88, 0x42, 0xA3, 0x3C, 0xB0, 0xC9 };
  
      // Hash to be calculated by TPM.
      TPM2B_DIGEST result;
      TPMT_TK_HASHCHECK validation;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
  
      TPMS_AUTH_COMMAND *sessionDataArray[2];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[2];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
      sessionDataArray[1] = &sessionData1;
      sessionDataOutArray[1] = &sessionDataOut1;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nHASH TESTS:\n" );
  
      auth.t.size = 2;
      auth.t.buffer[0] = 0;
      auth.t.buffer[1] = 0xff;
      rval = Tss2_Sys_HashSequenceStart ( sysContext, 0, &auth, TPM_ALG_SHA1, &sequenceHandle[0], 0 );
      CheckPassed( rval );
  
      // Init authHandle
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac = auth;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      dataToHash.t.size = MAX_DIGEST_BUFFER;
      memcpy( &dataToHash.t.buffer[0], &memoryToHash[0], dataToHash.t.size );
  
      rval = Tss2_Sys_SequenceUpdate ( sysContext, sequenceHandle[0], &sessionsData, &dataToHash, &sessionsDataOut );
      CheckPassed( rval );
  
      // Now try starting a bunch of sequences to see what happens.
      // This checks that the resource manager properly saves and restores the context
      // of the interrupted original sequence.
      for( i = 1; i < 5; i++ )
      {
          rval = Tss2_Sys_HashSequenceStart ( sysContext, 0, &auth, TPM_ALG_SHA1, &sequenceHandle[i], 0 );
          CheckPassed( rval );
      }
  
      // Now end the created sequences.
      dataToHash.t.size = 0;
      for( i = 1; i < 5; i++ )
      {
          INIT_SIMPLE_TPM2B_SIZE( result );
          rval = Tss2_Sys_SequenceComplete ( sysContext, sequenceHandle[i], &sessionsData, &dataToHash,
                  TPM_RH_PLATFORM, &result, &validation, &sessionsDataOut );
          CheckPassed( rval );
      }
  
      //  Now try to finish the interrupted sequence.
      rval = Tss2_Sys_SequenceUpdate ( sysContext, sequenceHandle[0], &sessionsData, &dataToHash, &sessionsDataOut );
      CheckPassed( rval );
  
      dataToHash.t.size = sizeof( memoryToHash ) - MAX_DIGEST_BUFFER;
      memcpy( &dataToHash.t.buffer[0], &memoryToHash[MAX_DIGEST_BUFFER], dataToHash.t.size );
      INIT_SIMPLE_TPM2B_SIZE( result );
      rval = Tss2_Sys_SequenceComplete ( sysContext, sequenceHandle[0], &sessionsData, &dataToHash,
              TPM_RH_PLATFORM, &result, &validation, &sessionsDataOut );
      CheckPassed( rval );
  
      // Test the resulting hash.
      if( memcmp( (void *)&( result.t.buffer[0] ), (void *)&( goodHashValue[0] ), result.t.size ) )
      {
          DebugPrintf( NO_PREFIX, "ERROR!! resulting hash is incorrect.\n" );
          Cleanup();
      }
  
      // Now try starting a bunch of sequences to see what happens.
      // This stresses the resource manager.
      for( i = 0; i < MAX_TEST_SEQUENCES; i++ )
      {
          rval = Tss2_Sys_HashSequenceStart ( sysContext, 0, &auth, TPM_ALG_SHA1, &sequenceHandle[i], 0 );
          CheckPassed( rval );
      }
  
      // Now end them all
      dataToHash.t.size = 0;
      for( i = (MAX_TEST_SEQUENCES - 1); i >= 0; i-- )
  //    for( i = 0; i < MAX_TEST_SEQUENCES; i++ )
      {
          INIT_SIMPLE_TPM2B_SIZE( result );
          rval = Tss2_Sys_SequenceComplete ( sysContext, sequenceHandle[i], &sessionsData, &dataToHash,
                  TPM_RH_PLATFORM, &result, &validation, &sessionsDataOut );
          CheckPassed( rval );
      }
  }
  
  void TestQuote()
  {
      UINT32 rval;
      TPM2B_DATA qualifyingData;
      UINT8 qualDataString[] = { 0x00, 0xff, 0x55, 0xaa };
      TPMT_SIG_SCHEME inScheme;
      TPML_PCR_SELECTION  pcrSelection;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
      TPM2B_ATTEST quoted;
      TPMT_SIGNATURE signature;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nQUOTE CONTROL TESTS:\n" );
  
      // Init authHandle
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 2;
      sessionData.hmac.t.buffer[0] = 0x00;
      sessionData.hmac.t.buffer[1] = 0xff;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      qualifyingData.t.size = sizeof( qualDataString );
      memcpy( &( qualifyingData.t.buffer[0] ), qualDataString, sizeof( qualDataString ) );
  
      inScheme.scheme = TPM_ALG_NULL;
  
      pcrSelection.count = 1;
      pcrSelection.pcrSelections[0].hash = TPM_ALG_SHA1;
      pcrSelection.pcrSelections[0].sizeofSelect = 3;
  
      // Clear out PCR select bit field
      pcrSelection.pcrSelections[0].pcrSelect[0] = 0;
      pcrSelection.pcrSelections[0].pcrSelect[1] = 0;
      pcrSelection.pcrSelections[0].pcrSelect[2] = 0;
  
      // Now set the PCR you want
      pcrSelection.pcrSelections[0].pcrSelect[( PCR_17/8 )] = ( 1 << ( PCR_18 % 8) );
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      // Test with wrong type of key.
      INIT_SIMPLE_TPM2B_SIZE( quoted );
      rval = Tss2_Sys_Quote ( sysContext, loadedSha1KeyHandle, &sessionsData, &qualifyingData, &inScheme,
              &pcrSelection,  &quoted, &signature, &sessionsDataOut );
      CheckPassed( rval );
  
      // Create signing key
  
  
      // Now test quote operation
  //    Tpm20Quote ( ??TPMI_DH_OBJECT signHandle, TPM2B_DATA *qualifyingData,
  //    TPMT_SIG_SCHEME *inScheme, TPML_PCR_SELECTION *pcrSelect,
  //    TPMS_AUTH_COMMAND *sessionsData)
  
  }
  
  void ProvisionOtherIndices()
  {
      UINT32 rval;
      TPMI_SH_AUTH_SESSION otherIndicesPolicyAuthHandle;
      TPM2B_DIGEST  nvPolicyHash;
      TPM2B_AUTH  nvAuth;
      TPMS_AUTH_COMMAND otherIndicesSessionData;
      TPMS_AUTH_RESPONSE otherIndicesSessionDataOut;
      TSS2_SYS_CMD_AUTHS otherIndicesSessionsData;
      TSS2_SYS_RSP_AUTHS otherIndicesSessionsDataOut;
      TPM2B_NV_PUBLIC publicInfo;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &otherIndicesSessionData;
      sessionDataOutArray[0] = &otherIndicesSessionDataOut;
  
      otherIndicesSessionsDataOut.rspAuths = &sessionDataOutArray[0];
      otherIndicesSessionsData.cmdAuths = &sessionDataArray[0];
  
      otherIndicesSessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nPROVISION OTHER NV INDICES:\n" );
  
      //
      // AUX index: Write is controlled by TPM2_PolicyLocality; Read is controlled by authValue and is unrestricted since authValue is set to emptyBuffer
      // Do this by setting up two policies and ORing them together when creating AuxIndex:
      // 1.  PolicyLocality(3) && PolicyCommand(NVWrite)
      // 2.  EmptyAuth policy && PolicyCommand(NVRead)
      // Page 126 of Part 1 describes how to do this.
      //
  
      // Steps:
      rval = StartPolicySession( &otherIndicesPolicyAuthHandle );
      CheckPassed( rval );
  
      // 3.  GetPolicyDigest and save it
      INIT_SIMPLE_TPM2B_SIZE( nvPolicyHash );
      rval = Tss2_Sys_PolicyGetDigest( sysContext, otherIndicesPolicyAuthHandle, 0, &nvPolicyHash, 0 );
      CheckPassed( rval );
  
      // Now save the policy digest from the first OR branch.
      DEBUG_PRINT_BUFFER( NO_PREFIX, &( nvPolicyHash.t.buffer[0] ), nvPolicyHash.t.size );
  
      // 4.  CreateNvIndex
      otherIndicesSessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      otherIndicesSessionData.nonce.t.size = 0;
  
      // init hmac
      otherIndicesSessionData.hmac.t.size = 0;
  
      // init nvAuth
      nvAuth.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&otherIndicesSessionData.sessionAttributes ) ) = 0;
  
      publicInfo.t.size = sizeof( TPMI_RH_NV_INDEX ) +
              sizeof( TPMI_ALG_HASH ) + sizeof( TPMA_NV ) + sizeof( UINT16) +
              sizeof( UINT16 );
      publicInfo.t.nvPublic.nvIndex = INDEX_LCP_SUP;
      publicInfo.t.nvPublic.nameAlg = TPM_ALG_SHA1;
  
      // First zero out attributes.
      *(UINT32 *)&( publicInfo.t.nvPublic.attributes ) = 0;
  
      // Now set the attributes.
      publicInfo.t.nvPublic.attributes.TPMA_NV_AUTHREAD = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_AUTHWRITE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE = 1;
      // Following commented out for convenience during development.
      // publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_WRITEDEFINE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_ORDERLY = 1;
  
      publicInfo.t.nvPublic.authPolicy.t.size = 0;
      publicInfo.t.nvPublic.dataSize = NV_PS_INDEX_SIZE;
  
      otherIndicesSessionsData.cmdAuthsCount = 1;
      otherIndicesSessionsData.cmdAuths[0] = &otherIndicesSessionData;
  
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM, &otherIndicesSessionsData,
              &nvAuth, &publicInfo, &otherIndicesSessionsDataOut );
      CheckPassed( rval );
  
      publicInfo.t.nvPublic.nvIndex = INDEX_LCP_OWN;
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM, &otherIndicesSessionsData,
              &nvAuth, &publicInfo, &otherIndicesSessionsDataOut );
      CheckPassed( rval );
  
      // Now teardown session
      rval = Tss2_Sys_FlushContext( sysContext, otherIndicesPolicyAuthHandle );
      CheckPassed( rval );
  }
  
  
  TSS2_RC InitNvAuxPolicySession( TPMI_SH_AUTH_SESSION *nvAuxPolicySessionHandle )
  {
      TPMA_LOCALITY locality;
      TPM_RC rval;
  
      rval = StartPolicySession( nvAuxPolicySessionHandle );
      CheckPassed( rval );
  
      // 2.  PolicyLocality(3)
      *(UINT8 *)((void *)&locality) = 0;
      locality.TPM_LOC_THREE = 1;
      locality.TPM_LOC_FOUR = 1;
      rval = Tss2_Sys_PolicyLocality( sysContext, *nvAuxPolicySessionHandle, 0, locality, 0 );
  
      return( rval );
  }
  
  void ProvisionNvAux()
  {
      UINT32 rval;
      TPMI_SH_AUTH_SESSION nvAuxPolicyAuthHandle;
      TPM2B_DIGEST  nvPolicyHash;
      TPM2B_AUTH  nvAuth;
      TPMS_AUTH_COMMAND nvAuxSessionData;
      TPMS_AUTH_RESPONSE nvAuxSessionDataOut;
      TSS2_SYS_CMD_AUTHS nvAuxSessionsData;
      TSS2_SYS_RSP_AUTHS nvAuxSessionsDataOut;
      TPM2B_NV_PUBLIC publicInfo;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &nvAuxSessionData;
      sessionDataOutArray[0] = &nvAuxSessionDataOut;
  
      nvAuxSessionsDataOut.rspAuths = &sessionDataOutArray[0];
      nvAuxSessionsData.cmdAuths = &sessionDataArray[0];
  
      nvAuxSessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nPROVISION NV AUX:\n" );
  
      //
      // AUX index: Write is controlled by TPM2_PolicyLocality; Read is controlled by authValue and is unrestricted since authValue is set to emptyBuffer
      // Do this by setting up two policies and ORing them together when creating AuxIndex:
      // 1.  PolicyLocality(3) && PolicyCommand(NVWrite)
      // 2.  EmptyAuth policy && PolicyCommand(NVRead)
      // Page 126 of Part 1 describes how to do this.
      //
  
      // Steps:
      rval = InitNvAuxPolicySession( &nvAuxPolicyAuthHandle );
      CheckPassed( rval );
  
      // 3.  GetPolicyDigest and save it
      INIT_SIMPLE_TPM2B_SIZE( nvPolicyHash );
      rval = Tss2_Sys_PolicyGetDigest( sysContext, nvAuxPolicyAuthHandle, 0, &nvPolicyHash, 0 );
      CheckPassed( rval );
  
      // Now save the policy digest.
      DEBUG_PRINT_BUFFER( NO_PREFIX, &( nvPolicyHash.t.buffer[0] ), nvPolicyHash.t.size );
  
      // 4.  CreateNvIndex
      nvAuxSessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      nvAuxSessionData.nonce.t.size = 0;
  
      // init hmac
      nvAuxSessionData.hmac.t.size = 0;
  
      // init nvAuth
      nvAuth.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&nvAuxSessionData.sessionAttributes ) ) = 0;
  
      nvAuxSessionsData.cmdAuthsCount = 1;
      nvAuxSessionsData.cmdAuths[0] = &nvAuxSessionData;
  
      publicInfo.t.size = sizeof( TPMI_RH_NV_INDEX ) +
              sizeof( TPMI_ALG_HASH ) + sizeof( TPMA_NV ) + sizeof( UINT16) +
              sizeof( UINT16 );
      publicInfo.t.nvPublic.nvIndex = INDEX_AUX;
      publicInfo.t.nvPublic.nameAlg = TPM_ALG_SHA1;
  
      // First zero out attributes.
      *(UINT32 *)&( publicInfo.t.nvPublic.attributes ) = 0;
  
      // Now set the attributes.
      publicInfo.t.nvPublic.attributes.TPMA_NV_AUTHREAD = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_POLICYWRITE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE = 1;
      // Following commented out for convenience during development.
      // publicInfo.t.nvPublic.attributes.TPMA_NV_POLICY_DELETE = 1;
  
      publicInfo.t.nvPublic.authPolicy.t.size = GetDigestSize( TPM_ALG_SHA1 );
      memcpy( (UINT8 *)&( publicInfo.t.nvPublic.authPolicy.t.buffer ), (UINT8 *)&(nvPolicyHash.t.buffer[0]),
              nvPolicyHash.t.size );
  
      publicInfo.t.nvPublic.dataSize = NV_AUX_INDEX_SIZE;
  
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM, &nvAuxSessionsData,
              &nvAuth, &publicInfo, &nvAuxSessionsDataOut );
      CheckPassed( rval );
  
      // Now teardown session
      rval = Tss2_Sys_FlushContext( sysContext, nvAuxPolicyAuthHandle );
      CheckPassed( rval );
  }
  
  void TpmAuxWrite( int locality)
  {
      TSS2_RC rval;
      int i;
      TPMI_SH_AUTH_SESSION nvAuxPolicyAuthHandle;
      TPM2B_MAX_NV_BUFFER nvWriteData;
  
      rval = InitNvAuxPolicySession( &nvAuxPolicyAuthHandle );
      CheckPassed( rval );
  
      // Now we're going to test it.
      nvWriteData.t.size = 4;
      for( i = 0; i < nvWriteData.t.size; i++ )
          nvWriteData.t.buffer[i] = 0xff - i;
  
      nullSessionData.sessionHandle = nvAuxPolicyAuthHandle;
  
      // Make sure that session terminates after NVWrite completes.
      nullSessionData.sessionAttributes.continueSession = 0;
  
      rval = SetLocality( sysContext, locality );
      CheckPassed( rval );
  
      nullSessionsData.cmdAuthsCount = 1;
      nullSessionsData.cmdAuths[0] = &nullSessionData;
  
      rval = Tss2_Sys_NV_Write( sysContext, INDEX_AUX, INDEX_AUX, &nullSessionsData, &nvWriteData, 0, &nullSessionsDataOut );
  
      {
          TSS2_RC setLocalityRval;
          setLocalityRval = SetLocality( sysContext, 3 );
          CheckPassed( setLocalityRval );
      }
  
      if( locality == 3 || locality == 4 )
      {
          CheckPassed( rval );
  
          // No teardown of session needed, since the authorization was
          // successful.
      }
      else
      {
          CheckFailed( rval, TPM_RC_LOCALITY );
  
          // Now teardown session
          rval = Tss2_Sys_FlushContext( sysContext, nvAuxPolicyAuthHandle );
          CheckPassed( rval );
      }
  }
  
  void TpmAuxReadWriteTest()
  {
      UINT32 rval;
      int testLocality;
      TPM2B_MAX_NV_BUFFER nvData;
  
      DebugPrintf( NO_PREFIX, "TPM AUX READ/WRITE TEST\n" );
  
      nullSessionData.sessionAttributes.continueSession = 0;
  
      // Try writing it from all localities.  Only locality 3 should work.
      for( testLocality = 0; testLocality < 5; testLocality++ )
      {
          TpmAuxWrite( testLocality );
      }
  
      nullSessionData.sessionHandle = TPM_RS_PW;
  
      nullSessionsData.cmdAuths[0] = &nullSessionData;
  
      // Try reading it from all localities.  They all should work.
      for( testLocality = 0; testLocality < 5; testLocality++ )
      {
          rval = SetLocality( sysContext, testLocality );
          CheckPassed( rval );
  
          INIT_SIMPLE_TPM2B_SIZE( nvData );
          rval = TSS2_RETRY_EXP( Tss2_Sys_NV_Read( sysContext, INDEX_AUX, INDEX_AUX, &nullSessionsData, 4, 0, &nvData, &nullSessionsDataOut ));
          CheckPassed( rval );
  
          rval = SetLocality( sysContext, 3 );
          CheckPassed( rval );
      }
  }
  
  void TpmOtherIndicesReadWriteTest()
  {
      UINT32 rval;
      TPM2B_MAX_NV_BUFFER nvWriteData;
      int i;
      TPM2B_MAX_NV_BUFFER nvData;
  
      nullSessionData.sessionHandle = TPM_RS_PW;
  
      DebugPrintf( NO_PREFIX, "TPM OTHER READ/WRITE TEST\n" );
  
      nvWriteData.t.size = 4;
      for( i = 0; i < nvWriteData.t.size; i++ )
          nvWriteData.t.buffer[i] = 0xff - i;
  
      nullSessionsData.cmdAuthsCount = 1;
      nullSessionsData.cmdAuths[0] = &nullSessionData;
  
      rval = Tss2_Sys_NV_Write( sysContext, INDEX_LCP_SUP, INDEX_LCP_SUP, &nullSessionsData, &nvWriteData, 0, &nullSessionsDataOut );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_Write( sysContext, INDEX_LCP_OWN, INDEX_LCP_OWN, &nullSessionsData, &nvWriteData, 0, &nullSessionsDataOut );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( nvData );
      rval = Tss2_Sys_NV_Read( sysContext, INDEX_LCP_SUP, INDEX_LCP_SUP, &nullSessionsData, 4, 0, &nvData, &nullSessionsDataOut );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( nvData );
      rval = Tss2_Sys_NV_Read( sysContext, INDEX_LCP_OWN, INDEX_LCP_OWN, &nullSessionsData, 4, 0, &nvData, &nullSessionsDataOut );
      CheckPassed( rval );
  }
  
  void NvIndexProto()
  {
      UINT32 rval;
  
      DebugPrintf( NO_PREFIX, "\nNV INDEX PROTOTYPE TESTS:\n" );
  
  
      // AUX index: Write is controlled by TPM2_PolicyLocality; Read is controlled by authValue and is unrestricted since authValue is set to emptyBuffer
      // PS index: Write and read are unrestricted until TPM2_WriteLock. After that content is write protected
      // PO index: Write is restricted by ownerAuth; Read is controlled by authValue and is unrestricted since authValue is set to emptyBuffer
  
      // Now we need to configure NV indices
      ProvisionNvAux();
  
      ProvisionOtherIndices();
  
      TpmAuxReadWriteTest();
  
      TpmOtherIndicesReadWriteTest();
  
      // Now undefine the aux index, so that subsequent test passes will work.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM, INDEX_AUX, &nullSessionsData, &nullSessionsDataOut );
      CheckPassed( rval );
  
      // Now undefine the other indices, so that subsequent test passes will work.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM, INDEX_LCP_SUP, &nullSessionsData, &nullSessionsDataOut );
      CheckPassed( rval );
  
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM, INDEX_LCP_OWN, &nullSessionsData, &nullSessionsDataOut );
      CheckPassed( rval );
  }
  
  void TestPcrAllocate()
  {
      UINT32 rval;
      TPML_PCR_SELECTION  pcrSelection;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
      TPMI_YES_NO allocationSuccess;
      UINT32 maxPcr;
      UINT32 sizeNeeded;
      UINT32 sizeAvailable;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      DebugPrintf( NO_PREFIX, "\nPCR ALLOCATE TEST  :\n" );
  
      // Init authHandle
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      pcrSelection.count = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      rval = Tss2_Sys_PCR_Allocate( sysContext, TPM_RH_PLATFORM, &sessionsData, &pcrSelection,
              &allocationSuccess, &maxPcr, &sizeNeeded, &sizeAvailable, &sessionsDataOut);
      CheckPassed( rval );
  
      pcrSelection.count = 3;
      pcrSelection.pcrSelections[0].hash = TPM_ALG_SHA256;
      CLEAR_PCR_SELECT_BITS( pcrSelection.pcrSelections[0] );
      SET_PCR_SELECT_SIZE( pcrSelection.pcrSelections[0], 3 );
      SET_PCR_SELECT_BIT( pcrSelection.pcrSelections[0], PCR_5 );
      SET_PCR_SELECT_BIT( pcrSelection.pcrSelections[0], PCR_7 );
      pcrSelection.pcrSelections[1].hash = TPM_ALG_SHA384;
      CLEAR_PCR_SELECT_BITS( pcrSelection.pcrSelections[1] );
      SET_PCR_SELECT_SIZE( pcrSelection.pcrSelections[1], 3 );
      SET_PCR_SELECT_BIT( pcrSelection.pcrSelections[1], PCR_5 );
      SET_PCR_SELECT_BIT( pcrSelection.pcrSelections[1], PCR_8 );
      pcrSelection.pcrSelections[2].hash = TPM_ALG_SHA256;
      CLEAR_PCR_SELECT_BITS( pcrSelection.pcrSelections[2] );
      SET_PCR_SELECT_SIZE( pcrSelection.pcrSelections[2], 3 );
      SET_PCR_SELECT_BIT( pcrSelection.pcrSelections[2], PCR_6 );
  
      rval = Tss2_Sys_PCR_Allocate( sysContext, TPM_RH_PLATFORM, &sessionsData, &pcrSelection,
              &allocationSuccess, &maxPcr, &sizeNeeded, &sizeAvailable, &sessionsDataOut);
      CheckPassed( rval );
  }
  
  void TestUnseal()
  {
      UINT32 rval;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
      TPM2B_SENSITIVE_CREATE  inSensitive;
      TPML_PCR_SELECTION      creationPCR;
      TPM2B_DATA              outsideInfo;
      TPM2B_PUBLIC            inPublic;
      TPM_HANDLE loadedObjectHandle;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      TPM2B_PRIVATE outPrivate;
      TPM2B_PUBLIC outPublic;
      TPM2B_CREATION_DATA creationData;
      TPM2B_DIGEST creationHash;
      TPMT_TK_CREATION creationTicket;
      TPM2B_NAME name;
      TPM2B_SENSITIVE_DATA outData;
  
  
      const char authStr[] = "test";
      const char sensitiveData[] = "this is sensitive";
  
      DebugPrintf( NO_PREFIX, "\nUNSEAL TEST  :\n" );
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      sessionData.hmac.t.size = 2;
      sessionData.hmac.t.buffer[0] = 0x00;
      sessionData.hmac.t.buffer[1] = 0xff;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      inSensitive.t.sensitive.userAuth.t.size = sizeof( authStr ) - 1;
      memcpy( &( inSensitive.t.sensitive.userAuth.t.buffer[0] ), authStr, sizeof( authStr ) - 1 );
      inSensitive.t.sensitive.data.t.size = sizeof( sensitiveData ) - 1;
      memcpy( &( inSensitive.t.sensitive.data.t.buffer[0] ), sensitiveData, sizeof( sensitiveData ) - 1 );
  
      inPublic.t.publicArea.authPolicy.t.size = 0;
  
      inPublic.t.publicArea.unique.keyedHash.t.size = 0;
  
      outsideInfo.t.size = 0;
      creationPCR.count = 0;
  
      inPublic.t.publicArea.type = TPM_ALG_KEYEDHASH;
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA1;
  
      *(UINT32 *)&( inPublic.t.publicArea.objectAttributes) = 0;
      inPublic.t.publicArea.objectAttributes.userWithAuth = 1;
  
      inPublic.t.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_NULL;
  
      inPublic.t.publicArea.unique.keyedHash.t.size = 0;
  
      outsideInfo.t.size = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0]  = &sessionData;
  
      outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      INIT_SIMPLE_TPM2B_SIZE( outPrivate );
      rval = Tss2_Sys_Create( sysContext, handle2048rsa, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR,
              &outPrivate, &outPublic, &creationData,
              &creationHash, &creationTicket, &sessionsDataOut );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_LoadExternal ( sysContext, 0, 0, &outPublic,
              TPM_RH_PLATFORM, &loadedObjectHandle, &name, 0 );
      CheckPassed( rval );
  
      rval = Tss2_Sys_FlushContext( sysContext, loadedObjectHandle );
      CheckPassed( rval );
  
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_Load ( sysContext, handle2048rsa, &sessionsData, &outPrivate, &outPublic,
              &loadedObjectHandle, &name, &sessionsDataOut);
      CheckPassed( rval );
  
      sessionData.hmac.t.size = sizeof( authStr ) - 1;
      memcpy( &( sessionData.hmac.t.buffer[0] ), authStr, sizeof( authStr ) - 1 );
  
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_Unseal( sysContext, loadedObjectHandle, &sessionsData, &outData, &sessionsDataOut );
  
      rval = Tss2_Sys_FlushContext( sysContext, loadedObjectHandle );
  
      CheckPassed( rval );
  }
  
  
  void CreatePasswordTestNV( TPMI_RH_NV_INDEX nvIndex, char * password )
  {
      UINT32 rval;
      int i;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
      TPM2B_NV_PUBLIC publicInfo;
      TPM2B_AUTH  nvAuth;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsDataOut.rspAuthsCount = 1;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      nvAuth.t.size = strlen( password );
      for( i = 0; i < nvAuth.t.size; i++ ) {
          nvAuth.t.buffer[i] = password[i];
      }
  
      publicInfo.t.size = sizeof( TPMI_RH_NV_INDEX ) +
          sizeof( TPMI_ALG_HASH ) + sizeof( TPMA_NV ) + sizeof( UINT16) +
          sizeof( UINT16 );
      publicInfo.t.nvPublic.nvIndex = nvIndex;
      publicInfo.t.nvPublic.nameAlg = TPM_ALG_SHA1;
  
      // First zero out attributes.
      *(UINT32 *)&( publicInfo.t.nvPublic.attributes ) = 0;
  
      // Now set the attributes.
      publicInfo.t.nvPublic.attributes.TPMA_NV_AUTHREAD = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_AUTHWRITE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_PLATFORMCREATE = 1;
      publicInfo.t.nvPublic.attributes.TPMA_NV_ORDERLY = 1;
      publicInfo.t.nvPublic.authPolicy.t.size = 0;
      publicInfo.t.nvPublic.dataSize = 32;
  
      rval = Tss2_Sys_NV_DefineSpace( sysContext, TPM_RH_PLATFORM,
              &sessionsData, &nvAuth, &publicInfo, &sessionsDataOut );
      CheckPassed( rval );
  }
  
  // Password used to authorize access to the NV index.
  char password[] = "test password";
  
  void PasswordTest()
  {
      UINT32 rval;
      int i;
  
      // Authorization structure for command.
      TPMS_AUTH_COMMAND sessionData;
  
      // Authorization structure for response.
      TPMS_AUTH_RESPONSE sessionDataOut;
  
      // Create and init authorization area for command:
      // only 1 authorization area.
      TPMS_AUTH_COMMAND *sessionDataArray[1] = { &sessionData };
  
      // Create authorization area for response:
      // only 1 authorization area.
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1] = { &sessionDataOut };
  
      // Authorization array for command (only has one auth structure).
      TSS2_SYS_CMD_AUTHS sessionsData = { 1, &sessionDataArray[0] };
  
      // Authorization array for response (only has one auth structure).
      TSS2_SYS_RSP_AUTHS sessionsDataOut = { 1, &sessionDataOutArray[0] };
      TPM2B_MAX_NV_BUFFER nvWriteData;
  
      DebugPrintf( NO_PREFIX, "\nPASSWORD TESTS:\n" );
  
      // Create an NV index that will use password
      // authorizations the password will be
      // "test password".
      CreatePasswordTestNV( TPM20_INDEX_PASSWORD_TEST, password );
  
      //
      // Initialize the command authorization area.
      //
  
      // Init sessionHandle, nonce, session
      // attributes, and hmac (password).
      sessionData.sessionHandle = TPM_RS_PW;
      // Set zero sized nonce.
      sessionData.nonce.t.size = 0;
      // sessionAttributes is a bit field.  To initialize
      // it to 0, cast to a pointer to UINT8 and
      // write 0 to that pointer.
      *( (UINT8 *)&sessionData.sessionAttributes ) = 0;
  
      // Init password (HMAC field in authorization structure).
      sessionData.hmac.t.size = strlen( password );
      memcpy( &( sessionData.hmac.t.buffer[0] ),
              &( password[0] ), sessionData.hmac.t.size );
  
      // Initialize write data.
      nvWriteData.t.size = 4;
      for( i = 0; i < nvWriteData.t.size; i++ )
          nvWriteData.t.buffer[i] = 0xff - i;
  
      // Attempt write with the correct password.
      // It should pass.
      rval = Tss2_Sys_NV_Write( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &sessionsData, &nvWriteData, 0,
              &sessionsDataOut );
      // Check that the function passed as
      // expected.  Otherwise, exit.
      CheckPassed( rval );
  
      // Alter the password so it's incorrect.
      sessionData.hmac.t.buffer[4] = 0xff;
      rval = Tss2_Sys_NV_Write( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &sessionsData, &nvWriteData, 0,
              &sessionsDataOut );
      // Check that the function failed as expected,
      // since password was incorrect.  If wrong
      // response code received, exit.
      CheckFailed( rval,
              TPM_RC_S + TPM_RC_1 + TPM_RC_AUTH_FAIL );
  
      // Change hmac to null one, since null auth is
      // used to undefine the index.
      sessionData.hmac.t.size = 0;
  
      // Now undefine the index.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM,
              TPM20_INDEX_PASSWORD_TEST, &sessionsData, 0 );
      CheckPassed( rval );
  }
  
  
  void SimplePolicyTest()
  {
      UINT32 rval, sessionCmdRval;
      TPM2B_AUTH  nvAuth;
      SESSION *nvSession = NULL, *trialPolicySession = NULL;
      TPMA_NV nvAttributes;
      TPM2B_DIGEST authPolicy;
      TPM2B_NAME nvName;
      TPM2B_MAX_NV_BUFFER nvWriteData, nvReadData;
      UINT8 dataToWrite[] = { 0x00, 0xff, 0x55, 0xaa };
      int i;
      TPM2B_ENCRYPTED_SECRET encryptedSalt;
      TPMT_SYM_DEF symmetric;
      TPMA_SESSION sessionAttributes;
  
      // Command authorization area: one password session.
      TPMS_AUTH_COMMAND nvCmdAuth = { TPM_RS_PW, };
      TPMS_AUTH_COMMAND *nvCmdAuthArray[1] = { &nvCmdAuth };
      TSS2_SYS_CMD_AUTHS nvCmdAuths = { 1, &nvCmdAuthArray[0] };
  
      // Response authorization area.
      TPMS_AUTH_RESPONSE nvRspAuth;
      TPMS_AUTH_RESPONSE *nvRspAuthArray[1] = { &nvRspAuth };
      TSS2_SYS_RSP_AUTHS nvRspAuths = { 1, &nvRspAuthArray[0] };
      TPM_ALG_ID sessionAlg = TPM_ALG_SHA256;
      TPM2B_NONCE nonceCaller;
  
      nonceCaller.t.size = 0;
  
      DebugPrintf( NO_PREFIX, "\nSIMPLE POLICY TEST:\n" );
  
      //
      // Create NV index.
      //
  
      // Setup the NV index's authorization value.
      nvAuth.t.size = 0;
  
      // Zero sized encrypted salt, since the session
      // is unsalted.
      encryptedSalt.t.size = 0;
  
      // No symmetric algorithm.
      symmetric.algorithm = TPM_ALG_NULL;
  
      //
      // Create the NV index's authorization policy
      // using a trial policy session.
      //
      rval = StartAuthSessionWithParams( &trialPolicySession, TPM_RH_NULL,
              0, TPM_RH_NULL, 0, &nonceCaller, &encryptedSalt, TPM_SE_TRIAL,
              &symmetric, sessionAlg, resMgrTctiContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_PolicyAuthValue( sysContext, trialPolicySession->sessionHandle, 0, 0 );
      CheckPassed( rval );
  
      // Get policy digest.
      INIT_SIMPLE_TPM2B_SIZE( authPolicy );
      rval = Tss2_Sys_PolicyGetDigest( sysContext, trialPolicySession->sessionHandle,
              0, &authPolicy, 0 );
      CheckPassed( rval );
  
      // End the trial session by flushing it.
      rval = Tss2_Sys_FlushContext( sysContext, trialPolicySession->sessionHandle );
      CheckPassed( rval );
  
      // And remove the trial policy session from sessions table.
      rval = EndAuthSession( trialPolicySession );
      CheckPassed( rval );
  
      // Now set the NV index's attributes:
      // policyRead, authWrite, and platormCreate.
      *(UINT32 *)( (void *)&nvAttributes ) = 0;
      nvAttributes.TPMA_NV_POLICYREAD = 1;
      nvAttributes.TPMA_NV_POLICYWRITE = 1;
      nvAttributes.TPMA_NV_PLATFORMCREATE = 1;
  
      // Create the NV index.
      rval = DefineNvIndex( TPM_RH_PLATFORM, TPM_RS_PW,
              &nvAuth, &authPolicy, TPM20_INDEX_PASSWORD_TEST,
              sessionAlg, nvAttributes, 32  );
      CheckPassed( rval );
  
      // Add index and associated authorization value to
      // entity table.  This helps when we need
      // to calculate HMACs.
      AddEntity( TPM20_INDEX_PASSWORD_TEST, &nvAuth );
      CheckPassed( rval );
  
      // Get the name of the NV index.
      rval = (*HandleToNameFunctionPtr)( TPM20_INDEX_PASSWORD_TEST,
              &nvName );
      CheckPassed( rval );
  
      //
      // Start real (non-trial) policy authorization session:
      // it's an unbound and unsalted session, no symmetric
      // encryption algorithm, and SHA256 is the session's
      // hash algorithm.
      //
  
      // Zero sized encrypted salt, since the session
      // is unsalted.
      encryptedSalt.t.size = 0;
  
      // No symmetric algorithm.
      symmetric.algorithm = TPM_ALG_NULL;
  
      // Create the session.
      // Session state (session handle, nonces, etc.) gets
      // saved into nvSession structure for later use.
      rval = StartAuthSessionWithParams( &nvSession, TPM_RH_NULL,
              0, TPM_RH_NULL, 0, &nonceCaller, &encryptedSalt, TPM_SE_POLICY,
              &symmetric, sessionAlg, resMgrTctiContext );
      CheckPassed( rval );
  
      // Get the name of the session and save it in
      // the nvSession structure.
      rval = (*HandleToNameFunctionPtr)( nvSession->sessionHandle,
              &nvSession->name );
      CheckPassed( rval );
  
      // Initialize NV write data.
      nvWriteData.t.size = sizeof( dataToWrite );
      for( i = 0; i < nvWriteData.t.size; i++ )
      {
          nvWriteData.t.buffer[i] = dataToWrite[i];
      }
  
      //
      // Now setup for writing the NV index.
      //
  
      rval = Tss2_Sys_PolicyAuthValue( sysContext, nvSession->sessionHandle, 0, 0 );
      CheckPassed( rval );
  
      // Get policy digest.
      INIT_SIMPLE_TPM2B_SIZE( authPolicy );
      rval = Tss2_Sys_PolicyGetDigest( sysContext, trialPolicySession->sessionHandle,
              0, &authPolicy, 0 );
      CheckPassed( rval );
  
      // First call prepare in order to create cpBuffer.
      rval = Tss2_Sys_NV_Write_Prepare( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvWriteData, 0 );
      CheckPassed( rval );
  
      // Configure command authorization area, except for HMAC.
      nvCmdAuths.cmdAuths[0]->sessionHandle = nvSession->sessionHandle;
      nvCmdAuths.cmdAuths[0]->nonce.t.size = 1;
      nvCmdAuths.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
      *( (UINT8 *)((void *)&sessionAttributes ) ) = 0;
      nvCmdAuths.cmdAuths[0]->sessionAttributes = sessionAttributes;
      nvCmdAuths.cmdAuths[0]->sessionAttributes.continueSession = 1;
  
      // Roll nonces for command
      RollNonces( nvSession, &nvCmdAuths.cmdAuths[0]->nonce );
  
      // Complete command authorization area, by computing
      // HMAC and setting it in nvCmdAuths.
      rval = ComputeCommandHmacs( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvCmdAuths,
              TPM_RC_FAILURE );
      CheckPassed( rval );
  
      // Finally!!  Write the data to the NV index.
      // If the command is successful, the command
      // HMAC was correct.
      sessionCmdRval = Tss2_Sys_NV_Write( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, &nvWriteData, 0, &nvRspAuths );
      CheckPassed( sessionCmdRval );
  
      // Roll nonces for response
      RollNonces( nvSession, &nvRspAuths.rspAuths[0]->nonce );
  
      if( sessionCmdRval == TPM_RC_SUCCESS )
      {
          // If the command was successful, check the
          // response HMAC to make sure that the
          // response was received correctly.
          rval = CheckResponseHMACs( sysContext, sessionCmdRval,
                  &nvCmdAuths, TPM20_INDEX_PASSWORD_TEST,
                  TPM20_INDEX_PASSWORD_TEST, &nvRspAuths );
          CheckPassed( rval );
      }
  
      rval = Tss2_Sys_PolicyAuthValue( sysContext, nvSession->sessionHandle, 0, 0 );
      CheckPassed( rval );
  
      // First call prepare in order to create cpBuffer.
      rval = Tss2_Sys_NV_Read_Prepare( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, sizeof( dataToWrite ), 0 );
      CheckPassed( rval );
  
      // Roll nonces for command
      RollNonces( nvSession, &nvCmdAuths.cmdAuths[0]->nonce );
  
      // End the session after next command.
      nvCmdAuths.cmdAuths[0]->sessionAttributes.continueSession = 0;
  
      // Complete command authorization area, by computing
      // HMAC and setting it in nvCmdAuths.
      rval = ComputeCommandHmacs( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvCmdAuths,
              TPM_RC_FAILURE );
      CheckPassed( rval );
  
      // And now read the data back.
      // If the command is successful, the command
      // HMAC was correct.
      INIT_SIMPLE_TPM2B_SIZE( nvReadData );
      sessionCmdRval = Tss2_Sys_NV_Read( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, sizeof( dataToWrite ), 0,
              &nvReadData, &nvRspAuths );
      CheckPassed( sessionCmdRval );
  
      // Roll nonces for response
      RollNonces( nvSession, &nvRspAuths.rspAuths[0]->nonce );
  
      if( sessionCmdRval == TPM_RC_SUCCESS )
      {
          // If the command was successful, check the
          // response HMAC to make sure that the
          // response was received correctly.
          rval = CheckResponseHMACs( sysContext, sessionCmdRval,
                  &nvCmdAuths, TPM20_INDEX_PASSWORD_TEST,
                  TPM20_INDEX_PASSWORD_TEST, &nvRspAuths );
          CheckPassed( rval );
      }
  
      // Check that write and read data are equal.
      if( memcmp( (void *)&nvReadData.t.buffer[0],
              (void *)&nvWriteData.t.buffer[0], nvReadData.t.size ) )
      {
          DebugPrintf( NO_PREFIX, "ERROR!! read data not equal to written data\n" );
          Cleanup();
      }
  
      //
      // Now cleanup:  undefine the NV index and delete
      // the NV index's entity table entry.
      //
  
      // Setup authorization for undefining the NV index.
      nvCmdAuths.cmdAuths[0]->sessionHandle = TPM_RS_PW;
      nvCmdAuths.cmdAuths[0]->nonce.t.size = 0;
      nvCmdAuths.cmdAuths[0]->hmac.t.size = 0;
  
      // Undefine the NV index.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext,
              TPM_RH_PLATFORM, TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, 0 );
      CheckPassed( rval );
  
      // Delete the NV index's entry in the entity table.
      rval = DeleteEntity( TPM20_INDEX_PASSWORD_TEST );
      CheckPassed( rval );
  }
  
  void SimpleHmacTest()
  {
      UINT32 rval, sessionCmdRval;
      TPM2B_AUTH  nvAuth;
      SESSION *nvSession = NULL;
      TPMA_NV nvAttributes;
      TPM2B_DIGEST authPolicy;
      TPM2B_NAME nvName;
      TPM2B_MAX_NV_BUFFER nvWriteData, nvReadData;
      UINT8 dataToWrite[] = { 0x00, 0xff, 0x55, 0xaa };
      char sharedSecret[] = "shared secret";
      int i;
      TPM2B_ENCRYPTED_SECRET encryptedSalt;
      TPMT_SYM_DEF symmetric;
      TPMA_SESSION sessionAttributes;
  
      // Command authorization area: one password session.
      TPMS_AUTH_COMMAND nvCmdAuth = { TPM_RS_PW, };
      TPMS_AUTH_COMMAND *nvCmdAuthArray[1] = { &nvCmdAuth };
      TSS2_SYS_CMD_AUTHS nvCmdAuths = { 1, &nvCmdAuthArray[0] };
  
      // Response authorization area.
      TPMS_AUTH_RESPONSE nvRspAuth;
      TPMS_AUTH_RESPONSE *nvRspAuthArray[1] = { &nvRspAuth };
      TSS2_SYS_RSP_AUTHS nvRspAuths = { 1, &nvRspAuthArray[0] };
      TPM2B_NONCE nonceCaller;
  
      nonceCaller.t.size = 0;
  
      DebugPrintf( NO_PREFIX, "\nSIMPLE HMAC SESSION TEST:\n" );
  
      //
      // Create NV index.
      //
  
      // Setup the NV index's authorization value.
      nvAuth.t.size = strlen( sharedSecret );
      for( i = 0; i < nvAuth.t.size; i++ )
          nvAuth.t.buffer[i] = sharedSecret[i];
  
      // Set NV index's authorization policy
      // to zero sized policy since we won't be
      // using policy to authorize.
      authPolicy.t.size = 0;
  
      // Now set the NV index's attributes:
      // policyRead, authWrite, and platormCreate.
      *(UINT32 *)( (void *)&nvAttributes ) = 0;
      nvAttributes.TPMA_NV_AUTHREAD = 1;
      nvAttributes.TPMA_NV_AUTHWRITE = 1;
      nvAttributes.TPMA_NV_PLATFORMCREATE = 1;
  
      // Create the NV index.
      rval = DefineNvIndex( TPM_RH_PLATFORM, TPM_RS_PW,
              &nvAuth, &authPolicy, TPM20_INDEX_PASSWORD_TEST,
              TPM_ALG_SHA256, nvAttributes, 32  );
      CheckPassed( rval );
  
      // Add index and associated authorization value to
      // entity table.  This helps when we need
      // to calculate HMACs.
      AddEntity( TPM20_INDEX_PASSWORD_TEST, &nvAuth );
      CheckPassed( rval );
  
      // Get the name of the NV index.
      rval = (*HandleToNameFunctionPtr)( TPM20_INDEX_PASSWORD_TEST,
              &nvName );
      CheckPassed( rval );
  
      //
      // Start HMAC authorization session:  it's an
      // unbound and unsalted session, no symmetric
      // encryption algorithm, and SHA256 is the session's
      // hash algorithm.
      //
  
      // Zero sized encrypted salt, since the session
      // is unsalted.
      encryptedSalt.t.size = 0;
  
      // No symmetric algorithm.
      symmetric.algorithm = TPM_ALG_NULL;
  
      // Create the session.
      // Session state (session handle, nonces, etc.) gets
      // saved into nvSession structure for later use.
      rval = StartAuthSessionWithParams( &nvSession, TPM_RH_NULL,
              0, TPM_RH_NULL, 0, &nonceCaller, &encryptedSalt, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval );
  
      // Get the name of the session and save it in
      // the nvSession structure.
      rval = (*HandleToNameFunctionPtr)( nvSession->sessionHandle,
              &nvSession->name );
      CheckPassed( rval );
  
      // Initialize NV write data.
      nvWriteData.t.size = sizeof( dataToWrite );
      for( i = 0; i < nvWriteData.t.size; i++ )
      {
          nvWriteData.t.buffer[i] = dataToWrite[i];
      }
  
      //
      // Now setup for writing the NV index.
      //
  
      // First call prepare in order to create cpBuffer.
      rval = Tss2_Sys_NV_Write_Prepare( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvWriteData, 0 );
      CheckPassed( rval );
  
      // Configure command authorization area, except for HMAC.
      nvCmdAuths.cmdAuths[0]->sessionHandle = nvSession->sessionHandle;
      nvCmdAuths.cmdAuths[0]->nonce.t.size = 1;
      nvCmdAuths.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
      *( (UINT8 *)(&sessionAttributes ) ) = 0;
      nvCmdAuths.cmdAuths[0]->sessionAttributes = sessionAttributes;
      nvCmdAuths.cmdAuths[0]->sessionAttributes.continueSession = 1;
  
      // Roll nonces for command
      RollNonces( nvSession, &nvCmdAuths.cmdAuths[0]->nonce );
  
      // Complete command authorization area, by computing
      // HMAC and setting it in nvCmdAuths.
      rval = ComputeCommandHmacs( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvCmdAuths,
              TPM_RC_FAILURE );
      CheckPassed( rval );
  
      // Finally!!  Write the data to the NV index.
      // If the command is successful, the command
      // HMAC was correct.
      sessionCmdRval = Tss2_Sys_NV_Write( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, &nvWriteData, 0, &nvRspAuths );
      CheckPassed( sessionCmdRval );
  
      // Roll nonces for response
      RollNonces( nvSession, &nvRspAuths.rspAuths[0]->nonce );
  
      if( sessionCmdRval == TPM_RC_SUCCESS )
      {
          // If the command was successful, check the
          // response HMAC to make sure that the
          // response was received correctly.
          rval = CheckResponseHMACs( sysContext, sessionCmdRval,
                  &nvCmdAuths, TPM20_INDEX_PASSWORD_TEST,
                  TPM20_INDEX_PASSWORD_TEST, &nvRspAuths );
          CheckPassed( rval );
      }
  
      // First call prepare in order to create cpBuffer.
      rval = Tss2_Sys_NV_Read_Prepare( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, sizeof( dataToWrite ), 0 );
      CheckPassed( rval );
  
      // Roll nonces for command
      RollNonces( nvSession, &nvCmdAuths.cmdAuths[0]->nonce );
  
      // End the session after next command.
      nvCmdAuths.cmdAuths[0]->sessionAttributes.continueSession = 0;
  
      // Complete command authorization area, by computing
      // HMAC and setting it in nvCmdAuths.
      rval = ComputeCommandHmacs( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvCmdAuths,
              TPM_RC_FAILURE );
      CheckPassed( rval );
  
      // And now read the data back.
      // If the command is successful, the command
      // HMAC was correct.
      INIT_SIMPLE_TPM2B_SIZE( nvReadData );
      sessionCmdRval = Tss2_Sys_NV_Read( sysContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, sizeof( dataToWrite ), 0,
              &nvReadData, &nvRspAuths );
      CheckPassed( sessionCmdRval );
  
      // Roll nonces for response
      RollNonces( nvSession, &nvRspAuths.rspAuths[0]->nonce );
  
      if( sessionCmdRval == TPM_RC_SUCCESS )
      {
          // If the command was successful, check the
          // response HMAC to make sure that the
          // response was received correctly.
          rval = CheckResponseHMACs( sysContext, sessionCmdRval,
                  &nvCmdAuths, TPM20_INDEX_PASSWORD_TEST,
                  TPM20_INDEX_PASSWORD_TEST, &nvRspAuths );
          CheckPassed( rval );
      }
  
      // Check that write and read data are equal.
      if( memcmp( (void *)&nvReadData.t.buffer[0],
              (void *)&nvWriteData.t.buffer[0], nvReadData.t.size ) )
      {
          DebugPrintf( NO_PREFIX, "ERROR!! read data not equal to written data\n" );
          Cleanup();
      }
  
      //
      // Now cleanup:  undefine the NV index and delete
      // the NV index's entity table entry.
      //
  
      // Setup authorization for undefining the NV index.
      nvCmdAuths.cmdAuths[0]->sessionHandle = TPM_RS_PW;
      nvCmdAuths.cmdAuths[0]->nonce.t.size = 0;
      nvCmdAuths.cmdAuths[0]->hmac.t.size = 0;
  
      // Undefine the NV index.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext,
              TPM_RH_PLATFORM, TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, 0 );
      CheckPassed( rval );
  
      // Delete the NV index's entry in the entity table.
      rval = DeleteEntity( TPM20_INDEX_PASSWORD_TEST );
      CheckPassed( rval );
  
      rval = EndAuthSession( nvSession );
  
      CheckPassed( rval );
  
      PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
  }
  
  
  void SimpleHmacOrPolicyTest( bool hmacTest )
  {
      UINT32 rval, sessionCmdRval;
      TPM2B_AUTH  nvAuth;
      SESSION *nvSession, *trialPolicySession;
      TPMA_NV nvAttributes;
      TPM2B_DIGEST authPolicy;
      TPM2B_NAME nvName;
      TPM2B_MAX_NV_BUFFER nvWriteData, nvReadData;
      UINT8 dataToWrite[] = { 0x00, 0xff, 0x55, 0xaa };
      char sharedSecret[] = "shared secret";
      int i;
      TPM2B_ENCRYPTED_SECRET encryptedSalt;
      TPMT_SYM_DEF symmetric;
      TPMA_SESSION sessionAttributes;
      TPM_SE tpmSe;
      char *testString;
      char testStringHmac[] = "HMAC";
      char testStringPolicy[] = "POLICY";
  
      // Command authorization area: one password session.
      TPMS_AUTH_COMMAND nvCmdAuth = { TPM_RS_PW, };
      TPMS_AUTH_COMMAND *nvCmdAuthArray[1] = { &nvCmdAuth };
      TSS2_SYS_CMD_AUTHS nvCmdAuths = { 1, &nvCmdAuthArray[0] };
  
      // Response authorization area.
      TPMS_AUTH_RESPONSE nvRspAuth;
      TPMS_AUTH_RESPONSE *nvRspAuthArray[1] = { &nvRspAuth };
      TSS2_SYS_RSP_AUTHS nvRspAuths = { 1, &nvRspAuthArray[0] };
  
      TSS2_SYS_CONTEXT *simpleTestContext;
      TPM2B_NONCE nonceCaller;
  
      nonceCaller.t.size = 0;
  
      if( hmacTest )
          testString = testStringHmac;
      else
          testString = testStringPolicy;
  
      DebugPrintf( NO_PREFIX, "\nSIMPLE %s SESSION TEST:\n", testString );
  
      // Create sysContext structure.
      simpleTestContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion );
      if( simpleTestContext == 0 )
      {
          InitSysContextFailure();
      }
  
      // Setup the NV index's authorization value.
      nvAuth.t.size = strlen( sharedSecret );
      for( i = 0; i < nvAuth.t.size; i++ )
          nvAuth.t.buffer[i] = sharedSecret[i];
  
      //
      // Create NV index.
      //
      if( hmacTest )
      {
          // Setup the NV index's authorization value.
          nvAuth.t.size = strlen( sharedSecret );
          for( i = 0; i < nvAuth.t.size; i++ )
              nvAuth.t.buffer[i] = sharedSecret[i];
  
          // Set NV index's authorization policy
          // to zero sized policy since we won't be
          // using policy to authorize.
  
          authPolicy.t.size = 0;
      }
      else
      {
          // Zero sized encrypted salt, since the session
          // is unsalted.
  
          encryptedSalt.t.size = 0;
  
          // No symmetric algorithm.
          symmetric.algorithm = TPM_ALG_NULL;
  
          //
          // Create the NV index's authorization policy
          // using a trial policy session.
          //
          rval = StartAuthSessionWithParams( &trialPolicySession,
                  TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller, &encryptedSalt,
                  TPM_SE_TRIAL,
                  &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
          CheckPassed( rval );
  
          rval = Tss2_Sys_PolicyAuthValue( simpleTestContext,
                  trialPolicySession->sessionHandle, 0, 0 );
          CheckPassed( rval );
  
          // Get policy digest.
          INIT_SIMPLE_TPM2B_SIZE( authPolicy );
          rval = Tss2_Sys_PolicyGetDigest( simpleTestContext,
                  trialPolicySession->sessionHandle,
                  0, &authPolicy, 0 );
          CheckPassed( rval );
  
          // End the trial session by flushing it.
          rval = Tss2_Sys_FlushContext( simpleTestContext,
                  trialPolicySession->sessionHandle );
          CheckPassed( rval );
  
          // And remove the trial policy session from
          // sessions table.
          rval = EndAuthSession( trialPolicySession );
          CheckPassed( rval );
      }
  
      // Now set the NV index's attributes:
      // policyRead, authWrite, and platormCreate.
      *(UINT32 *)( &nvAttributes ) = 0;
      if( hmacTest )
      {
          nvAttributes.TPMA_NV_AUTHREAD = 1;
          nvAttributes.TPMA_NV_AUTHWRITE = 1;
      }
      else
      {
          nvAttributes.TPMA_NV_POLICYREAD = 1;
          nvAttributes.TPMA_NV_POLICYWRITE = 1;
      }
      nvAttributes.TPMA_NV_PLATFORMCREATE = 1;
  
      // Create the NV index.
      rval = DefineNvIndex( TPM_RH_PLATFORM, TPM_RS_PW,
              &nvAuth, &authPolicy, TPM20_INDEX_PASSWORD_TEST,
              TPM_ALG_SHA256, nvAttributes, 32  );
      CheckPassed( rval );
  
      // Add index and associated authorization value to
      // entity table.  This helps when we need
      // to calculate HMACs.
      AddEntity( TPM20_INDEX_PASSWORD_TEST, &nvAuth );
      CheckPassed( rval );
  
      // Get the name of the NV index.
      rval = (*HandleToNameFunctionPtr)(
              TPM20_INDEX_PASSWORD_TEST,
              &nvName );
      CheckPassed( rval );
  
  
      //
      // Start HMAC or real (non-trial) policy authorization session:
      // it's an unbound and unsalted session, no symmetric
      // encryption algorithm, and SHA256 is the session's
      // hash algorithm.
      //
  
      // Zero sized encrypted salt, since the session
      // is unsalted.
      encryptedSalt.t.size = 0;
  
      // No symmetric algorithm.
      symmetric.algorithm = TPM_ALG_NULL;
  
      // Create the session, hmac or policy depending
      // on hmacTest.
      // Session state (session handle, nonces, etc.) gets
      // saved into nvSession structure for later use.
      if( hmacTest )
          tpmSe = TPM_SE_HMAC;
      else
          tpmSe = TPM_SE_POLICY;
  
      rval = StartAuthSessionWithParams( &nvSession, TPM_RH_NULL,
              0, TPM_RH_NULL, 0, &nonceCaller, &encryptedSalt, tpmSe,
              &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval );
  
      // Get the name of the session and save it in
      // the nvSession structure.
      rval = (*HandleToNameFunctionPtr)( nvSession->sessionHandle,
              &(nvSession->name) );
      CheckPassed( rval );
  
      // Initialize NV write data.
      nvWriteData.t.size = sizeof( dataToWrite );
      for( i = 0; i < nvWriteData.t.size; i++ )
      {
          nvWriteData.t.buffer[i] = dataToWrite[i];
      }
  
      //
      // Now setup for writing the NV index.
      //
      if( !hmacTest )
      {
          // Send policy command.
          rval = Tss2_Sys_PolicyAuthValue( simpleTestContext,
                  nvSession->sessionHandle, 0, 0 );
          CheckPassed( rval );
      }
  
      // First call prepare in order to create cpBuffer.
      rval = Tss2_Sys_NV_Write_Prepare( simpleTestContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvWriteData, 0 );
      CheckPassed( rval );
  
      // Configure command authorization area, except for HMAC.
      nvCmdAuths.cmdAuths[0]->sessionHandle =
              nvSession->sessionHandle;
      nvCmdAuths.cmdAuths[0]->nonce.t.size = 1;
      nvCmdAuths.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
      *( (UINT8 *)(&sessionAttributes ) ) = 0;
      nvCmdAuths.cmdAuths[0]->sessionAttributes = sessionAttributes;
      nvCmdAuths.cmdAuths[0]->sessionAttributes.continueSession = 1;
  
      // Roll nonces for command
      RollNonces( nvSession, &nvCmdAuths.cmdAuths[0]->nonce );
  
      // Complete command authorization area, by computing
      // HMAC and setting it in nvCmdAuths.
      rval = ComputeCommandHmacs( simpleTestContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvCmdAuths,
              TPM_RC_FAILURE );
      CheckPassed( rval );
  
      // Finally!!  Write the data to the NV index.
      // If the command is successful, the command
      // HMAC was correct.
      sessionCmdRval = Tss2_Sys_NV_Write( simpleTestContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, &nvWriteData, 0, &nvRspAuths );
      CheckPassed( sessionCmdRval );
  
      // Roll nonces for response
      RollNonces( nvSession, &nvRspAuths.rspAuths[0]->nonce );
  
      if( sessionCmdRval == TPM_RC_SUCCESS )
      {
          // If the command was successful, check the
          // response HMAC to make sure that the
          // response was received correctly.
          rval = CheckResponseHMACs( simpleTestContext, sessionCmdRval,
                  &nvCmdAuths, TPM20_INDEX_PASSWORD_TEST,
                  TPM20_INDEX_PASSWORD_TEST, &nvRspAuths );
          CheckPassed( rval );
      }
  
      if( !hmacTest )
      {
          // Send policy command.
          rval = Tss2_Sys_PolicyAuthValue( simpleTestContext,
                  nvSession->sessionHandle, 0, 0 );
          CheckPassed( rval );
      }
      // First call prepare in order to create cpBuffer.
      rval = Tss2_Sys_NV_Read_Prepare( simpleTestContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              sizeof( dataToWrite ), 0 );
      CheckPassed( rval );
  
      // Roll nonces for command
      RollNonces( nvSession, &nvCmdAuths.cmdAuths[0]->nonce );
  
      // End the session after next command.
      nvCmdAuths.cmdAuths[0]->sessionAttributes.continueSession = 0;
  
      // Complete command authorization area, by computing
      // HMAC and setting it in nvCmdAuths.
      rval = ComputeCommandHmacs( simpleTestContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvCmdAuths,
              TPM_RC_FAILURE );
      CheckPassed( rval );
  
      // And now read the data back.
      // If the command is successful, the command
      // HMAC was correct.
      INIT_SIMPLE_TPM2B_SIZE( nvReadData );
      sessionCmdRval = Tss2_Sys_NV_Read( simpleTestContext,
              TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, sizeof( dataToWrite ), 0,
              &nvReadData, &nvRspAuths );
      CheckPassed( sessionCmdRval );
  
      // Roll nonces for response
      RollNonces( nvSession, &nvRspAuths.rspAuths[0]->nonce );
  
      if( sessionCmdRval == TPM_RC_SUCCESS )
      {
          // If the command was successful, check the
          // response HMAC to make sure that the
          // response was received correctly.
          rval = CheckResponseHMACs( simpleTestContext, sessionCmdRval,
                  &nvCmdAuths, TPM20_INDEX_PASSWORD_TEST,
                  TPM20_INDEX_PASSWORD_TEST, &nvRspAuths );
          CheckPassed( rval );
      }
  
      // Check that write and read data are equal.
      if( memcmp( (void *)&nvReadData.t.buffer[0],
              (void *)&nvWriteData.t.buffer[0], nvReadData.t.size ) )
      {
          DebugPrintf( NO_PREFIX, "ERROR!! read data not equal to written data\n" );
          Cleanup();
      }
  
      //
      // Now cleanup:  undefine the NV index and delete
      // the NV index's entity table entry.
      //
  
      // Setup authorization for undefining the NV index.
      nvCmdAuths.cmdAuths[0]->sessionHandle = TPM_RS_PW;
      nvCmdAuths.cmdAuths[0]->nonce.t.size = 0;
      nvCmdAuths.cmdAuths[0]->hmac.t.size = 0;
  
      // Undefine the NV index.
      rval = Tss2_Sys_NV_UndefineSpace( simpleTestContext,
              TPM_RH_PLATFORM, TPM20_INDEX_PASSWORD_TEST,
              &nvCmdAuths, 0 );
      CheckPassed( rval );
  
      // Delete the NV index's entry in the entity table.
      rval = DeleteEntity( TPM20_INDEX_PASSWORD_TEST );
      CheckPassed( rval );
  
      // Remove the real session from sessions table.
      rval = EndAuthSession( nvSession );
  
      CheckPassed( rval );
  
      TeardownSysContext( &simpleTestContext );
  
  }
  
  
  typedef struct {
      TPMI_DH_OBJECT tpmKey;
      TPMI_DH_ENTITY bound;
      TPM2B_MAX_BUFFER *salt;
      char hmacTestDescription[50];
  } HMAC_TEST_SETUP;
  
  TPM2B_MAX_BUFFER nullSalt = { { 0, { 0xa4 } }, };
  TPM2B_MAX_BUFFER nonNullSalt = { { 2, { 0xa5, 0 } } };
  
  HMAC_TEST_SETUP hmacTestSetups[] =
  {
  #ifndef SKIP_UNBOUND_UNSALTED_HMAC_TEST
      { TPM_RH_NULL, TPM_RH_NULL, &nullSalt, "UNBOUND/UNSALTED SESSION TEST" },
  #endif //SKIP_UNBOUND_UNSALTED_HMAC_TEST
  #ifndef SKIP_BOUND_SESSION_HMAC_TEST
      { TPM_RH_NULL, TPM20_INDEX_PASSWORD_TEST, &nullSalt, "BOUND SESSION TEST" },
  #endif //SKIP_BOUND_SESSION_HMAC_TEST
  #ifndef SKIP_SALTED_SESSION_HMAC_TEST
      { 0, TPM_RH_NULL, &nonNullSalt, "SALTED SESSION TEST" },
  #endif //SKIP_SALTED_SESSION_HMAC_TEST
  #ifndef SKIP_BOUND_SALTED_SESSION_HMAC_TEST
      { 0, TPM20_INDEX_PASSWORD_TEST, &nonNullSalt, "BOUND/SALTED SESSION TEST" },
  #endif //SKIP_BOUND_SALTED_SESSION_HMAC_TEST
  };
  
  #define PLAINTEXT_SESSION 0
  #define DECRYPT_SESSION 1
  #define ENCRYPT_SESSION 2
  
  //UINT8 decryptEncryptSetups[] = { PLAINTEXT_SESSION, DECRYPT_SESSION, ENCRYPT_SESSION };
  UINT8 decryptEncryptSetups[] = { PLAINTEXT_SESSION };
  
  #define CFB_MODE 0
  #define XOR_MODE 1
  
  void HmacSessionTest()
  {
      UINT32 rval;
      int i, j, k;
      unsigned int decryptEncryptMode;
      TPM2B_MAX_NV_BUFFER nvWriteData;
      UINT8 dataToWrite[] = { 0x00, 0xff, 0x55, 0xaa };
      TPM2B_NAME nvName;
      TPM_RC sessionCmdRval;
  
      SESSION *nvSession = NULL;
      TSS2_SYS_CONTEXT *rdSysContext;
      TSS2_SYS_CONTEXT *wrSysContext;
      TPM2B_AUTH  nvAuth;
      TPMT_SYM_DEF symmetric;
      TPM2B_NONCE nonceOlder;
  
      // Create two sysContext structures.
      rdSysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion );
      if( rdSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      wrSysContext = InitSysContext( 1000, resMgrTctiContext, &abiVersion );
      if( wrSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      char sharedSecret[] = "shared secret";
  
      char buffer1contents[] = "test";
      char buffer2contents[] = "string";
  
      TPM2B_MAX_BUFFER buffer1;
      TPM2B_MAX_BUFFER buffer2;
  
  //    TPM2B_IV ivIn, ivOut;
      TPM2B_MAX_NV_BUFFER nvData;
      TPM2B_ENCRYPTED_SECRET encryptedSalt;
  
      encryptedSalt.t.size = 0;
  //    ivIn.t.size = 0;
  //    ivOut.t.size = 0;
  
      buffer1.t.size = strlen( buffer1contents );
      memcpy (buffer1.t.buffer, buffer1contents, buffer1.t.size );
      buffer2.t.size = strlen( buffer2contents );
      memcpy (buffer2.t.buffer, buffer2contents, buffer2.t.size );
  
  
      for( j = 0; j < sizeof( hmacTestSetups ) / sizeof( HMAC_TEST_SETUP ); j++ )
      {
          if( hmacTestSetups[j].salt == &nonNullSalt )
          {
              hmacTestSetups[j].tpmKey = handle2048rsa;
          }
      }
      DebugPrintf( NO_PREFIX, "\nHMAC SESSION TESTS:\n" );
  
      for( j = 0; j < sizeof( hmacTestSetups ) / sizeof( HMAC_TEST_SETUP ); j++ )
      {
          // Iterate through variations of decrypt and encrypt sessions.
          for( k = 0; k < sizeof( decryptEncryptSetups ); k++ )
          {
              for( decryptEncryptMode = CFB_MODE; decryptEncryptMode <= XOR_MODE; decryptEncryptMode++ )
              {
                  TPMS_AUTH_COMMAND sessionData = { TPM_RS_PW, };
                  TPMS_AUTH_RESPONSE sessionDataOut;
                  TPMS_AUTH_COMMAND *sessionDataArray[1] = { &sessionData };
                  TPMS_AUTH_RESPONSE *sessionDataOutArray[1] = { &sessionDataOut };
                  TSS2_SYS_CMD_AUTHS sessionsData = { 1, &sessionDataArray[0] };
                  TSS2_SYS_RSP_AUTHS sessionsDataOut = { 1, &sessionDataOutArray[0] };
  
                  TPMT_RSA_DECRYPT  inScheme;
                  TPM2B_DATA label;
                  TPM2B_DIGEST authPolicy;
                  TPMA_NV nvAttributes;
  
                  DebugPrintf( NO_PREFIX, "\n\n%s:\n", hmacTestSetups[j].hmacTestDescription );
  
                  if( hmacTestSetups[j].tpmKey != TPM_RH_NULL )
                  {
                      sessionsData.cmdAuths[0]->hmac = loadedSha1KeyAuth;
                      sessionsData.cmdAuths[0]->sessionHandle = TPM_RS_PW;
                      sessionsData.cmdAuths[0]->nonce.t.size = 0;
                      *( (UINT8 *)(&sessionData.sessionAttributes ) ) = 0;
  
                      inScheme.scheme = TPM_ALG_OAEP;
                      inScheme.details.oaep.hashAlg = TPM_ALG_SHA1;
                      memcpy( &( label.b.buffer ), "SECRET", 1 + strlen( "SECRET" ) );
                      label.t.size = strlen( "SECRET" ) + 1;
  
                      // Encrypt salt with tpmKey.
                      INIT_SIMPLE_TPM2B_SIZE( encryptedSalt );
                      rval = Tss2_Sys_RSA_Encrypt( sysContext, handle2048rsa,
                              0, (TPM2B_PUBLIC_KEY_RSA *)( hmacTestSetups[j].salt ),
                              &inScheme, &label, (TPM2B_PUBLIC_KEY_RSA *)&encryptedSalt, 0 );
                      CheckPassed( rval );
                  }
  
                  // init hmac
                  sessionData.hmac.t.size = 0;
  
                  // NOW CREATE THE INDEX
                  authPolicy.t.size = 0;
  
                  nvAuth.t.size = strlen( sharedSecret );
                  for( i = 0; i < nvAuth.t.size; i++ )
                      nvAuth.t.buffer[i] = sharedSecret[i];
  
                  // Now set the attributes.
                  *(UINT32 *)( &nvAttributes ) = 0;
                  nvAttributes.TPMA_NV_AUTHREAD = 1;
                  nvAttributes.TPMA_NV_AUTHWRITE = 1;
                  nvAttributes.TPMA_NV_PLATFORMCREATE = 1;
  
                  sessionsData.cmdAuths[0]->sessionHandle = TPM_RS_PW;
                  sessionsData.cmdAuths[0]->nonce.t.size = 0;
                  sessionsData.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
                  sessionData.hmac.t.size = 0;
  
                  // Undefine the index in case a previous test failure left it defined.
                  rval = Tss2_Sys_NV_UndefineSpace( wrSysContext, TPM_RH_PLATFORM, TPM20_INDEX_PASSWORD_TEST, &sessionsData, 0 );
  
                  rval = DefineNvIndex( TPM_RH_PLATFORM, TPM_RS_PW, &nvAuth, &authPolicy,
                          TPM20_INDEX_PASSWORD_TEST, TPM_ALG_SHA1, nvAttributes, 32  );
                  CheckPassed( rval );
  
                  AddEntity( TPM20_INDEX_PASSWORD_TEST, &nvAuth );
                  CheckPassed( rval );
  
                  // Get the name using TPM function.
                  rval = (*HandleToNameFunctionPtr)( TPM20_INDEX_PASSWORD_TEST, &nvName );
                  CheckPassed( rval );
  
                  //
                  // Start session
                  //
                  nonceOlder.t.size = GetDigestSize( TPM_ALG_SHA1 );
                  for( i = 0; i < nonceOlder.t.size; i++ )
                      nonceOlder.t.buffer[i] = 0;
  
                  if( decryptEncryptSetups[k] == PLAINTEXT_SESSION )
                  {
                      symmetric.algorithm = TPM_ALG_NULL;
                  }
                  else if( decryptEncryptSetups[k] == DECRYPT_SESSION || decryptEncryptSetups[k] == ENCRYPT_SESSION )
                  {
                      if( decryptEncryptMode == CFB_MODE )
                      {
                          symmetric.algorithm = TPM_ALG_AES;
                          symmetric.keyBits.aes = 128;
                          symmetric.mode.aes = TPM_ALG_CFB;
                      }
                      else if( decryptEncryptMode == XOR_MODE )
                      {
                          symmetric.algorithm = TPM_ALG_XOR;
                          symmetric.keyBits.exclusiveOr = TPM_ALG_SHA256;
                      }
                  }
  
                  rval = StartAuthSessionWithParams( &nvSession, hmacTestSetups[j].tpmKey,
                          hmacTestSetups[j].salt, hmacTestSetups[j].bound, &nvAuth, &nonceOlder, &encryptedSalt,
                          TPM_SE_HMAC, &symmetric, TPM_ALG_SHA1, resMgrTctiContext );
                  CheckPassed( rval );
  
                  // Get and print name of the session.
                  rval = (*HandleToNameFunctionPtr)( nvSession->sessionHandle, &nvSession->name );
                  CheckPassed( rval );
  
                  DebugPrintf( NO_PREFIX, "Name of authSession: " );
                  PrintSizedBuffer( (TPM2B *)&nvSession->name );
  
                  // Init write data.
                  nvWriteData.t.size = sizeof( dataToWrite );
  
                  for( i = 0; i < nvWriteData.t.size; i++ )
                  {
                      nvWriteData.t.buffer[i] = dataToWrite[i];
                  }
  
                  if( decryptEncryptSetups[k] == DECRYPT_SESSION )
                  {
                      if( decryptEncryptMode == CFB_MODE )
                      {
  //                        rval = EncryptCFB( &nvSession, &( nvWriteData.b ) );
                      }
                      else if( decryptEncryptMode == XOR_MODE )
                      {
  //                        rval = EncryptXOR( &nvSession, &( nvWriteData.b ) );
                      }
                      sessionsData.cmdAuths[0]->sessionAttributes.decrypt = 1;
                  }
                  else
                  {
                      sessionsData.cmdAuths[0]->sessionAttributes.decrypt = 0;
                  }
                  sessionsData.cmdAuths[0]->sessionAttributes.encrypt = 0;
  
                  CheckPassed( rval );
  
                  sessionsData.cmdAuths[0]->sessionHandle = nvSession->sessionHandle;
                  sessionsData.cmdAuths[0]->nonce.t.size = 1;
                  sessionsData.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
  
                  // Roll nonces for command
                  RollNonces( nvSession, &sessionsData.cmdAuths[0]->nonce );
  
                  // Now try writing with bad HMAC.
                  rval = Tss2_Sys_NV_Write_Prepare( wrSysContext, TPM20_INDEX_PASSWORD_TEST,
                          TPM20_INDEX_PASSWORD_TEST, &nvWriteData, 0 );
                  CheckPassed( rval );
  
                  rval = ComputeCommandHmacs( wrSysContext,
                          TPM20_INDEX_PASSWORD_TEST,
                          TPM20_INDEX_PASSWORD_TEST, &sessionsData, TPM_RC_FAILURE );
                  CheckPassed( rval );
  
                  // Diddle with HMAC to force failure
                  sessionsData.cmdAuths[0]->hmac.t.buffer[0] =
                          ~( sessionsData.cmdAuths[0]->hmac.t.buffer[0] );
  
                  sessionCmdRval = Tss2_Sys_NV_Write( wrSysContext, TPM20_INDEX_PASSWORD_TEST,
                          TPM20_INDEX_PASSWORD_TEST,
                          &sessionsData, &nvWriteData, 0, &sessionsDataOut );
                  CheckFailed( sessionCmdRval, TPM_RC_S + TPM_RC_1 + TPM_RC_AUTH_FAIL );
  
                  // Since command failed, no need to roll nonces.
  
                  TestDictionaryAttackLockReset();
  
                  // Now try writing with good HMAC.
  
                  // Do stage 1 of NVRead, followed by stage 1 and 2 of NVWrite, followed by
                  // stage 2 of NVRead.  This tests that the staged processing is thread-safe.
                  sessionsData.cmdAuths[0]->sessionAttributes.continueSession = 0;
                  rval = Tss2_Sys_NV_Read_Prepare( rdSysContext, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, sizeof( dataToWrite ), 0 );
                  CheckPassed( rval );
  
                  sessionsData.cmdAuths[0]->sessionAttributes.continueSession = 1;
                  rval = Tss2_Sys_NV_Write_Prepare( wrSysContext, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST,
                          &nvWriteData, 0 );
                  CheckPassed( rval );
  
                  rval = ComputeCommandHmacs( wrSysContext, TPM20_INDEX_PASSWORD_TEST,
                          TPM20_INDEX_PASSWORD_TEST, &sessionsData, sessionCmdRval );
                  CheckPassed( rval );
  
                  sessionCmdRval = Tss2_Sys_NV_Write( wrSysContext,
                          TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, &sessionsData, &nvWriteData, 0, &sessionsDataOut );
                  CheckPassed( sessionCmdRval );
                  if( sessionCmdRval == TPM_RC_SUCCESS )
                  {
                      // Roll nonces for response
                      RollNonces( nvSession, &sessionsDataOut.rspAuths[0]->nonce );
  
                      rval = CheckResponseHMACs( wrSysContext, sessionCmdRval,
                              &sessionsData, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, &sessionsDataOut );
                      CheckPassed( rval );
                  }
  
                  // Roll nonces for command
                  RollNonces( nvSession, &sessionsData.cmdAuths[0]->nonce );
  
                  sessionsData.cmdAuths[0]->sessionAttributes.continueSession = 0;
                  rval = ComputeCommandHmacs( rdSysContext, TPM20_INDEX_PASSWORD_TEST,
                         TPM20_INDEX_PASSWORD_TEST, &sessionsData, sessionCmdRval );
                  CheckPassed( rval );
  
                  if( decryptEncryptSetups[k] == ENCRYPT_SESSION )
                  {
                      sessionsData.cmdAuths[0]->sessionAttributes.encrypt = 1;
                  }
                  else
                  {
                      sessionsData.cmdAuths[0]->sessionAttributes.encrypt = 0;
                  }
                  sessionsData.cmdAuths[0]->sessionAttributes.decrypt = 0;
  
                  INIT_SIMPLE_TPM2B_SIZE( nvData );
                  sessionCmdRval = Tss2_Sys_NV_Read( rdSysContext, TPM20_INDEX_PASSWORD_TEST,
                          TPM20_INDEX_PASSWORD_TEST, &sessionsData, sizeof( dataToWrite ), 0, &nvData, &sessionsDataOut );
                  CheckPassed( sessionCmdRval );
                  if( sessionCmdRval == TPM_RC_SUCCESS )
                  {
                      // Roll nonces for response
                      RollNonces( nvSession, &sessionsDataOut.rspAuths[0]->nonce );
  
                      rval = CheckResponseHMACs( rdSysContext, sessionCmdRval,
                              &sessionsData, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, &sessionsDataOut );
                      CheckPassed( rval );
  
                      if( decryptEncryptSetups[k] == ENCRYPT_SESSION )
                      {
                          if( decryptEncryptMode == CFB_MODE )
                          {
  //                            rval = EncryptCFB( nvSession, &( nvData.b ) );
                          }
                          else if( decryptEncryptMode == XOR_MODE )
                          {
  //                            rval = EncryptXOR( nvSession, &( nvData.b ) );
                          }
                          CheckPassed( rval );
                      }
  
                      // Check that write actually worked.
                      rval = CompareTPM2B( &(nvWriteData.b), &(nvData.b) );
                      CheckPassed( rval );
                  }
  
                  //
                  // NOTE:  When running against version of the simulator for TPM spec versions later
                  // than version 0.98, in order for the session to act as a bound session when accessing
                  // the bind entity, we will need to restart the session here since the name of the bound
                  // entity changed.
                  //
                  if( hmacTestSetups[j].bound != TPM_RH_NULL )
                  {
                      rval = EndAuthSession( nvSession );
                      CheckPassed( rval );
  
                      //
                      // Start session
                      //
                      nonceOlder.t.size = GetDigestSize( TPM_ALG_SHA1 );
                      for( i = 0; i < nonceOlder.t.size; i++ )
                          nonceOlder.t.buffer[i] = 0;
  
                      symmetric.algorithm = TPM_ALG_AES;
                      symmetric.keyBits.aes = 128;
                      symmetric.mode.aes = TPM_ALG_CFB;
  
                      rval = StartAuthSessionWithParams( &nvSession, hmacTestSetups[j].tpmKey,  hmacTestSetups[j].salt, hmacTestSetups[j].bound, &nvAuth, &nonceOlder, &encryptedSalt, TPM_SE_HMAC, &symmetric, TPM_ALG_SHA1, resMgrTctiContext );
                      CheckPassed( rval );
  
                      CopySizedByteBuffer( &( nvSession->authValueBind.b ), &( nvAuth.b ) );
  
                      // Now try writing with good HMAC.
                      sessionsData.cmdAuths[0]->sessionHandle = nvSession->sessionHandle;
                      sessionsData.cmdAuths[0]->nonce.t.size = 1;
                      sessionsData.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
                      sessionsData.cmdAuths[0]->sessionAttributes.continueSession = 1;
                      sessionsData.cmdAuths[0]->sessionAttributes.decrypt = 1;
  
                      // TBD:  Need to encrypt data before sending.
  
                      rval = Tss2_Sys_NV_Write_Prepare( wrSysContext, TPM20_INDEX_PASSWORD_TEST,
                              TPM20_INDEX_PASSWORD_TEST, &nvWriteData, 0 );
                      CheckPassed( rval );
  
                      // Roll nonces for command
                      RollNonces( nvSession, &sessionsData.cmdAuths[0]->nonce );
  
                      rval = ComputeCommandHmacs( wrSysContext, TPM20_INDEX_PASSWORD_TEST,
                              TPM20_INDEX_PASSWORD_TEST, &sessionsData, TPM_RC_FAILURE );
                      CheckPassed( rval );
  
                      sessionCmdRval = Tss2_Sys_NV_Write( wrSysContext, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, &sessionsData, &nvWriteData, 0, &sessionsDataOut );
                      sessionsData.cmdAuths[0]->sessionAttributes.decrypt = 0;
                      CheckPassed( sessionCmdRval );
                      if( sessionCmdRval == TPM_RC_SUCCESS )
                      {
                          // Roll nonces for response
                          RollNonces( nvSession, &sessionsDataOut.rspAuths[0]->nonce );
  
                          rval = CheckResponseHMACs( wrSysContext, sessionCmdRval,
                                  &sessionsData, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, &sessionsDataOut );
                          CheckPassed( rval );
                      }
  
                      // Need to do GetSessionAuditDigest to check that audit digest changed.
  
                      sessionsData.cmdAuths[0]->sessionAttributes.continueSession = 0;
                      sessionsData.cmdAuths[0]->sessionAttributes.encrypt = 1;
                      sessionsData.cmdAuths[0]->sessionAttributes.audit = 1;
  
                      rval = Tss2_Sys_NV_Read_Prepare( rdSysContext, TPM20_INDEX_PASSWORD_TEST,
                              TPM20_INDEX_PASSWORD_TEST, sizeof( dataToWrite ), 0 );
                      CheckPassed( rval );
  
                      // Roll nonces for command
                      RollNonces( nvSession, &sessionsData.cmdAuths[0]->nonce );
  
                      rval = ComputeCommandHmacs( rdSysContext, TPM20_INDEX_PASSWORD_TEST,
                              TPM20_INDEX_PASSWORD_TEST, &sessionsData, sessionCmdRval );
                      CheckPassed( rval );
  
                      INIT_SIMPLE_TPM2B_SIZE( nvData );
                      sessionCmdRval = Tss2_Sys_NV_Read( rdSysContext, TPM20_INDEX_PASSWORD_TEST,
                              TPM20_INDEX_PASSWORD_TEST, &sessionsData, sizeof( dataToWrite ), 0, &nvData, &sessionsDataOut );
                      sessionsData.cmdAuths[0]->sessionAttributes.encrypt = 0;
                      sessionsData.cmdAuths[0]->sessionAttributes.audit = 0;
                      if( sessionCmdRval == TPM_RC_SUCCESS )
                      {
                          // Roll nonces for response
                          RollNonces( nvSession, &sessionsDataOut.rspAuths[0]->nonce );
  
                          rval = CheckResponseHMACs( rdSysContext, sessionCmdRval,
                                  &sessionsData, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, &sessionsDataOut );
                          CheckPassed( rval );
                      }
  
                      // TBD:  Need to decrypt response data.
  
                      CheckPassed( rval );
                      // TBD:  Need to do GetSessionAuditDigest to check that audit digest changed.
                  }
  
                  // Removed comparison for now until we figure out how to properly
                  // encrypt data before writing to NV index.
                  //        rval = CompareTPM2B( &(nvWriteData.b), &(nvData.b) );
                  //        CheckPassed( rval );
  
                  sessionsData.cmdAuths[0]->sessionHandle = TPM_RS_PW;
                  sessionsData.cmdAuths[0]->nonce.t.size = 0;
                  sessionsData.cmdAuths[0]->nonce.t.buffer[0] = 0xa5;
                  sessionData.hmac.t.size = 0;
                  // Now undefine the index.
                  rval = Tss2_Sys_NV_UndefineSpace( wrSysContext, TPM_RH_PLATFORM, TPM20_INDEX_PASSWORD_TEST, &sessionsData, 0 );
                  CheckPassed( rval );
                  rval = DeleteEntity( TPM20_INDEX_PASSWORD_TEST );
                  CheckPassed( rval );
                  rval = EndAuthSession( nvSession );
                  CheckPassed( rval );
              }
          }
      }
  
      TeardownSysContext( &wrSysContext );
      TeardownSysContext( &rdSysContext );
  
  }
  
  UINT32 writeDataString = 0xdeadbeef;
  
  void TestEncryptDecryptSession()
  {
      TSS2_RC             rval = TSS2_RC_SUCCESS;
      SESSION             *encryptDecryptSession = NULL;
      TPMT_SYM_DEF        symmetric;
      TPM2B_MAX_NV_BUFFER writeData, encryptedWriteData;
      TPM2B_MAX_NV_BUFFER encryptedReadData, decryptedReadData,
                          readData;
      size_t              decryptParamSize;
      uint8_t             *decryptParamBuffer;
      size_t              encryptParamSize;
      uint8_t             *encryptParamBuffer;
      TPM2B_AUTH          nvAuth;
      TPM2B_DIGEST        authPolicy;
      TPMA_NV             nvAttributes;
      int                 i;
      TPMA_SESSION        sessionAttributes;
      TPM2B_NONCE         nonceCaller;
  
      nonceCaller.t.size = 0;
  
      // Authorization structure for undefine command.
      TPMS_AUTH_COMMAND nvUndefineAuth;
  
      // Create and init authorization area for undefine command:
      // only 1 authorization area.
      TPMS_AUTH_COMMAND *nvUndefineAuthArray[1] = { &nvUndefineAuth };
  
      // Authorization array for command (only has one auth structure).
      TSS2_SYS_CMD_AUTHS nvUndefineAuths = { 1, &nvUndefineAuthArray[0] };
  
      DebugPrintf( NO_PREFIX, "\n\nDECRYPT/ENCRYPT SESSION TESTS:\n" );
  
      writeData.t.size = sizeof( writeDataString );
      memcpy( (void *)&writeData.t.buffer, (void *)&writeDataString,
              sizeof( writeDataString ) );
  
  
      // Create NV index with empty auth value.
      *(UINT32 *)( (void *)&nvAttributes ) = 0;
      nvAttributes.TPMA_NV_AUTHREAD = 1;
      nvAttributes.TPMA_NV_AUTHWRITE = 1;
      nvAttributes.TPMA_NV_PLATFORMCREATE = 1;
  
      // No authorization required.
      authPolicy.t.size = 0;
      nvAuth.t.size = 0;
      rval = DefineNvIndex( TPM_RH_PLATFORM, TPM_RS_PW,
              &nvAuth, &authPolicy, TPM20_INDEX_TEST1,
              TPM_ALG_SHA1, nvAttributes,
              sizeof( writeDataString ) );
  
      //
      // 1st pass with CFB mode.
      // 2nd pass with XOR mode.
      //
      for( i = 0; i < 2; i++ )
      {
          // Authorization structure for NV
          // read/write commands.
          TPMS_AUTH_COMMAND nvRdWrCmdAuth;
  
          // Authorization structure for
          // encrypt/decrypt session.
          TPMS_AUTH_COMMAND decryptEncryptSessionCmdAuth;
  
          // Create and init authorization area for
          // NV read/write commands:
          // 2 authorization areas.
          TPMS_AUTH_COMMAND *nvRdWrCmdAuthArray[2] =
                  { &nvRdWrCmdAuth, &decryptEncryptSessionCmdAuth };
  
          // Authorization array for commands
          // (has two auth structures).
          TSS2_SYS_CMD_AUTHS nvRdWrCmdAuths =
                  { 2, &nvRdWrCmdAuthArray[0] };
  
          // Authorization structure for NV read/write responses.
          TPMS_AUTH_RESPONSE nvRdWrRspAuth;
          // Authorization structure for decrypt/encrypt
          // session responses.
          TPMS_AUTH_RESPONSE decryptEncryptSessionRspAuth;
  
          // Create and init authorization area for NV
          // read/write responses:  2 authorization areas.
          TPMS_AUTH_RESPONSE *nvRdWrRspAuthArray[2] =
                  { &nvRdWrRspAuth, &decryptEncryptSessionRspAuth };
          // Authorization array for responses
          // (has two auth structures).
          TSS2_SYS_RSP_AUTHS nvRdWrRspAuths =
                  { 2, &nvRdWrRspAuthArray[0] };
  
          // Setup session parameters.
          if( i == 0 )
          {
              // AES encryption/decryption and CFB mode.
              symmetric.algorithm = TPM_ALG_AES;
              symmetric.keyBits.aes = 128;
              symmetric.mode.aes = TPM_ALG_CFB;
          }
          else
          {
              // XOR encryption/decryption.
              symmetric.algorithm = TPM_ALG_XOR;
              symmetric.keyBits.exclusiveOr = TPM_ALG_SHA256;
          }
  
          // Start policy session for decrypt/encrypt session.
          rval = StartAuthSessionWithParams( &encryptDecryptSession,
                  TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller, 0, TPM_SE_POLICY,
                  &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
          CheckPassed( rval );
  
          //
          // Write TPM index with encrypted parameter used
          // as the data to write.  Set session for encrypt.
          // Use asynchronous APIs to do this.
          //
          // 1st time:  use null buffer, 2nd time use populated one;
          // this tests different cases for SetDecryptParam function.
          //
  
          // Prepare the input parameters, using unencypted
          // write data.  This will be encrypted before the
          // command is sent to the TPM.
          rval = Tss2_Sys_NV_Write_Prepare( sysContext,
                  TPM20_INDEX_TEST1, TPM20_INDEX_TEST1,
                  ( i == 0 ? (TPM2B_MAX_NV_BUFFER *)0 : &writeData ),
                  0 );
          CheckPassed( rval );
  
          // Set up password authorization session structure.
          nvRdWrCmdAuth.sessionHandle = TPM_RS_PW;
          nvRdWrCmdAuth.nonce.t.size = 0;
          *( (UINT8 *)((void *)&nvRdWrCmdAuth.sessionAttributes ) ) = 0;
          nvRdWrCmdAuth.hmac.t.size = nvAuth.t.size;
          memcpy( (void *)&nvRdWrCmdAuth.hmac.t.buffer[0],
                  (void *)&nvAuth.t.buffer[0],
                  nvRdWrCmdAuth.hmac.t.size );
  
          // Set up encrypt/decrypt session structure.
          decryptEncryptSessionCmdAuth.sessionHandle =
                  encryptDecryptSession->sessionHandle;
          decryptEncryptSessionCmdAuth.nonce.t.size = 0;
          *( (UINT8 *)((void *)&sessionAttributes ) ) = 0;
          decryptEncryptSessionCmdAuth.sessionAttributes =
                  sessionAttributes;
          decryptEncryptSessionCmdAuth.sessionAttributes.continueSession
                  = 1;
          decryptEncryptSessionCmdAuth.sessionAttributes.decrypt = 1;
          decryptEncryptSessionCmdAuth.hmac.t.size = 0;
  
          rval = Tss2_Sys_SetCmdAuths( sysContext, &nvRdWrCmdAuths );
          CheckPassed( rval );
  
          // Get decrypt parameter.
          rval = Tss2_Sys_GetDecryptParam( sysContext,
                  &decryptParamSize,
                  (const uint8_t **)&decryptParamBuffer );
          CheckPassed( rval );
  
          if( i == 0 )
          {
              // 1st pass:  test case of Prepare inputting a NULL decrypt
              // param; decryptParamSize should be 0.
              if( decryptParamSize != 0 )
              {
                  DebugPrintf( NO_PREFIX, "ERROR!! decryptParamSize != 0\n" );
                  Cleanup();
              }
          }
  
          // Roll nonces for command.
          RollNonces( encryptDecryptSession,
                  &decryptEncryptSessionCmdAuth.nonce );
  
          // Encrypt write data.
          rval = EncryptCommandParam( encryptDecryptSession,
                  (TPM2B_MAX_BUFFER *)&encryptedWriteData,
                  (TPM2B_MAX_BUFFER *)&writeData, &nvAuth );
          CheckPassed( rval );
  
          // Now set decrypt parameter.
          rval = Tss2_Sys_SetDecryptParam( sysContext,
                  (uint8_t )encryptedWriteData.t.size,
                  (uint8_t *)&encryptedWriteData.t.buffer[0] );
          CheckPassed( rval );
  
          // Now write the data to the NV index.
          rval = Tss2_Sys_ExecuteAsync( sysContext );
          CheckPassed( rval );
  
          rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
          CheckPassed( rval );
  
          rval = Tss2_Sys_GetRspAuths( sysContext, &nvRdWrRspAuths );
          CheckPassed( rval );
  
          // Roll the nonces for response
          RollNonces( encryptDecryptSession,
                  &nvRdWrRspAuths.rspAuths[1]->nonce );
  
  
          // Don't need nonces for anything else, so roll
          // the nonces for next command.
          RollNonces( encryptDecryptSession,
                  &decryptEncryptSessionCmdAuth.nonce );
  
          // Now read the data without encrypt set.
          nvRdWrCmdAuths.cmdAuthsCount = 1;
          nvRdWrRspAuths.rspAuthsCount = 1;
          INIT_SIMPLE_TPM2B_SIZE( readData );
          rval = Tss2_Sys_NV_Read( sysContext, TPM20_INDEX_TEST1,
                  TPM20_INDEX_TEST1, &nvRdWrCmdAuths,
                  sizeof( writeDataString ), 0, &readData,
                  &nvRdWrRspAuths );
          CheckPassed( rval );
          nvRdWrCmdAuths.cmdAuthsCount = 2;
          nvRdWrRspAuths.rspAuthsCount = 2;
  
          // Roll the nonces for response
          RollNonces( encryptDecryptSession,
                  &nvRdWrRspAuths.rspAuths[1]->nonce );
  
          // Check that write and read data are equal.  This
          // verifies that the decrypt session was setup correctly.
          // If it wasn't, the data stored in the TPM would still
          // be encrypted, and this test would fail.
          if( memcmp( (void *)&readData.t.buffer[0],
                  (void *)&writeData.t.buffer[0], readData.t.size ) )
          {
              DebugPrintf( NO_PREFIX, "ERROR!! read data not equal to written data\n" );
              Cleanup();
          }
  
          //
          // Read TPM index with encrypt session; use
          // synchronous APIs to do this.
          //
  
          rval = Tss2_Sys_NV_Read_Prepare( sysContext, TPM20_INDEX_TEST1,
                  TPM20_INDEX_TEST1, sizeof( writeDataString ), 0 );
          CheckPassed( rval );
  
          // Roll the nonces for next command.
          RollNonces( encryptDecryptSession,
                  &decryptEncryptSessionCmdAuth.nonce );
  
          decryptEncryptSessionCmdAuth.sessionAttributes.decrypt = 0;
          decryptEncryptSessionCmdAuth.sessionAttributes.encrypt = 1;
          decryptEncryptSessionCmdAuth.sessionAttributes.continueSession =
                  1;
  
          rval = Tss2_Sys_SetCmdAuths( sysContext, &nvRdWrCmdAuths );
          CheckPassed( rval );
  
          //
          // Now Read the data.
          //
          rval = Tss2_Sys_Execute( sysContext );
          CheckPassed( rval );
  
          rval = Tss2_Sys_GetEncryptParam( sysContext, &encryptParamSize,
                  (const uint8_t **)&encryptParamBuffer );
          CheckPassed( rval );
  
          rval = Tss2_Sys_GetRspAuths( sysContext, &nvRdWrRspAuths );
          CheckPassed( rval );
  
          // Roll the nonces for response
          RollNonces( encryptDecryptSession,
                  &nvRdWrRspAuths.rspAuths[1]->nonce );
  
          // Decrypt read data.
          encryptedReadData.t.size = encryptParamSize;
          memcpy( (void *)&encryptedReadData.t.buffer[0],
                  (void *)encryptParamBuffer, encryptParamSize );
          INIT_SIMPLE_TPM2B_SIZE( decryptedReadData );
          rval = DecryptResponseParam( encryptDecryptSession,
                  (TPM2B_MAX_BUFFER *)&decryptedReadData,
                  (TPM2B_MAX_BUFFER *)&encryptedReadData, &nvAuth );
          CheckPassed( rval );
  
          // Roll the nonces.
          RollNonces( encryptDecryptSession,
                  &nvRdWrRspAuths.rspAuths[1]->nonce );
  
          rval = Tss2_Sys_SetEncryptParam( sysContext,
                  (uint8_t)decryptedReadData.t.size,
                  (uint8_t *)&decryptedReadData.t.buffer[0] );
          CheckPassed( rval );
  
          // Get the command results, in this case the read data.
          INIT_SIMPLE_TPM2B_SIZE( readData );
          rval = Tss2_Sys_NV_Read_Complete( sysContext, &readData );
          CheckPassed( rval );
  
          DebugPrintf( NO_PREFIX, "Decrypted read data = " );
          DEBUG_PRINT_BUFFER( NO_PREFIX, &readData.t.buffer[0], (UINT32 )readData.t.size );
  
          // Check that write and read data are equal.
          if( memcmp( (void *)&readData.t.buffer[0],
                  (void *)&writeData.t.buffer[0], readData.t.size ) )
          {
              DebugPrintf( NO_PREFIX, "ERROR!! read data not equal to written data\n" );
              Cleanup();
          }
  
          rval = Tss2_Sys_FlushContext( sysContext,
                  encryptDecryptSession->sessionHandle );
          CheckPassed( rval );
  
          rval = EndAuthSession( encryptDecryptSession );
          CheckPassed( rval );
      }
  
      // Set authorization for NV undefine command.
      nvUndefineAuth.sessionHandle = TPM_RS_PW;
      nvUndefineAuth.nonce.t.size = 0;
      *( (UINT8 *)((void *)&nvUndefineAuth.sessionAttributes ) ) = 0;
      nvUndefineAuth.hmac.t.size = 0;
  
      // Undefine NV index.
      rval = Tss2_Sys_NV_UndefineSpace( sysContext,
              TPM_RH_PLATFORM, TPM20_INDEX_TEST1, &nvUndefineAuths, 0 );
      CheckPassed( rval );
  }
  
  void GetSetDecryptParamTests()
  {
      TPM2B_MAX_NV_BUFFER nvWriteData = { { 4, { 0xde, 0xad, 0xbe, 0xef, } } };
      TPM2B_MAX_NV_BUFFER nvWriteData1 = { { 4, { 0x01, 0x01, 0x02, 0x03, } } };
      const uint8_t *decryptParamBuffer;
      size_t decryptParamSize;
      size_t cpBufferUsedSize1, cpBufferUsedSize2;
      const uint8_t *cpBuffer1, *cpBuffer2;
      TSS2_RC rval;
      int i;
      TSS2_SYS_CONTEXT *decryptParamTestSysContext;
  
      DebugPrintf( NO_PREFIX, "\nGET/SET DECRYPT PARAM TESTS:\n" );
  
      // Create two sysContext structures.
      decryptParamTestSysContext = InitSysContext( MAX_NV_BUFFER_SIZE, resMgrTctiContext, &abiVersion );
      if( decryptParamTestSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      // Test for bad sequence:  Tss2_Sys_GetDecryptParam
      rval = Tss2_Sys_GetDecryptParam( decryptParamTestSysContext, &decryptParamSize, &decryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE );
  
      // Test for bad sequence:  Tss2_Sys_SetDecryptParam
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 4, &( nvWriteData.t.buffer[0] ) );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE );
  
      // NOTE:  Two tests for BAD_SEQUENCE for GetDecryptParam and SetDecryptParam after ExecuteAsync
      // are in the GetSetEncryptParamTests function, just because it's easier to do this way.
  
      // Do Prepare.
      rval = Tss2_Sys_NV_Write_Prepare( decryptParamTestSysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvWriteData1, 0x55aa );
      CheckPassed( rval );
  
      // Test for bad reference:  Tss2_Sys_GetDecryptParam
      rval = Tss2_Sys_GetDecryptParam( 0, &decryptParamSize, &decryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
      rval = Tss2_Sys_GetDecryptParam( decryptParamTestSysContext, 0, &decryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
      rval = Tss2_Sys_GetDecryptParam( decryptParamTestSysContext, &decryptParamSize, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
  
      // Test for bad reference:  Tss2_Sys_SetDecryptParam
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 4, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
      rval = Tss2_Sys_SetDecryptParam( 0, 4, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
  
      // Test for bad size.
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 5, &( nvWriteData.t.buffer[0] ) );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SIZE );
  
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 3, &( nvWriteData.t.buffer[0] ) );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SIZE );
  
      // Test for good size.
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 4, &( nvWriteData.t.buffer[0] ) );
      CheckPassed( rval );
  
      // Make sure that the set operation really did the right thing.
      rval = Tss2_Sys_GetDecryptParam( decryptParamTestSysContext, &decryptParamSize, &decryptParamBuffer );
      CheckPassed( rval );
      for( i = 0; i < 4; i++ )
      {
          if( decryptParamBuffer[i] != nvWriteData.t.buffer[i] )
          {
              DebugPrintf( NO_PREFIX, "ERROR!!  decryptParamBuffer[%d] s/b: %2.2x, was: %2.2x\n", i, nvWriteData.t.buffer[i], decryptParamBuffer[i] );
              Cleanup();
          }
      }
  
      rval = Tss2_Sys_GetCpBuffer( decryptParamTestSysContext, &cpBufferUsedSize1, &cpBuffer1 );
      CheckPassed( rval );
  
  #ifdef DEBUG
      DebugPrintf( NO_PREFIX, "cpBuffer = ");
  #endif
      DEBUG_PRINT_BUFFER( NO_PREFIX, (UINT8 *)cpBuffer1, cpBufferUsedSize1 );
  
      // Test for no decrypt param.
      rval = Tss2_Sys_NV_Read_Prepare( decryptParamTestSysContext, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, sizeof( nvWriteData ) - 2, 0 );
      CheckPassed( rval );
  
      rval = Tss2_Sys_GetDecryptParam( decryptParamTestSysContext, &decryptParamSize, &decryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_NO_DECRYPT_PARAM );
  
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 4, &( nvWriteData.t.buffer[0] ) );
      CheckFailed( rval, TSS2_SYS_RC_NO_DECRYPT_PARAM );
  
      // Null decrypt param.
      rval = Tss2_Sys_NV_Write_Prepare( decryptParamTestSysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, 0, 0x55aa );
      CheckPassed( rval );
  
      rval = Tss2_Sys_GetDecryptParam( decryptParamTestSysContext, &decryptParamSize, &decryptParamBuffer );
      CheckPassed( rval );
  
      // Check that size == 0.
      if( decryptParamSize != 0 )
      {
          DebugPrintf( NO_PREFIX, "ERROR!!  decryptParamSize s/b: 0, was: %u\n", (unsigned int)decryptParamSize );
          Cleanup();
      }
  
      // Test for insufficient size.
      rval = Tss2_Sys_GetCpBuffer( decryptParamTestSysContext, &cpBufferUsedSize2, &cpBuffer2 );
      CheckPassed( rval );
      nvWriteData.t.size = MAX_NV_BUFFER_SIZE -
              BE_TO_HOST_32(((TPM20_Header_In *)(((_TSS2_SYS_CONTEXT_BLOB *)decryptParamTestSysContext)->tpmInBuffPtr))->commandSize) + 1;
  
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, nvWriteData.t.size, &( nvWriteData.t.buffer[0] ) );
      CheckFailed( rval, TSS2_SYS_RC_INSUFFICIENT_CONTEXT );
  
      // Test that one less will work.  This tests that we're checking the correct corner case.
      nvWriteData.t.size -= 1;
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, nvWriteData.t.size, &( nvWriteData.t.buffer[0] ) );
      CheckPassed( rval );
  
  
      rval = Tss2_Sys_NV_Write_Prepare( decryptParamTestSysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, 0, 0x55aa );
      CheckPassed( rval );
  
      rval = Tss2_Sys_GetDecryptParam( decryptParamTestSysContext, &decryptParamSize, &decryptParamBuffer );
      CheckPassed( rval );
  
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 4, &( nvWriteData.t.buffer[0] ) );
      CheckPassed( rval );
  
      rval = Tss2_Sys_GetCpBuffer( decryptParamTestSysContext, &cpBufferUsedSize2, &cpBuffer2 );
      CheckPassed( rval );
  
  #ifdef DEBUG
      DebugPrintf( NO_PREFIX, "cpBuffer = ");
  #endif
      DEBUG_PRINT_BUFFER( NO_PREFIX, (UINT8 *)cpBuffer2, cpBufferUsedSize2 );
  
      if( cpBufferUsedSize1 != cpBufferUsedSize2 )
      {
          DebugPrintf( NO_PREFIX, "ERROR!!  cpBufferUsedSize1(%x) != cpBufferUsedSize2(%x)\n", (UINT32)cpBufferUsedSize1, (UINT32)cpBufferUsedSize2 );
          Cleanup();
      }
      for( i = 0; i < (int)cpBufferUsedSize1; i++ )
      {
          if( cpBuffer1[i] != cpBuffer2[i] )
          {
              DebugPrintf( NO_PREFIX, "ERROR!! cpBufferUsedSize1[%d] s/b: %2.2x, was: %2.2x\n", i, cpBuffer1[i], cpBuffer2[i] );
              Cleanup();
          }
      }
  
      // Test case of zero sized decrypt param, another case of bad size.
      nvWriteData1.t.size = 0;
      rval = Tss2_Sys_NV_Write_Prepare( decryptParamTestSysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvWriteData1, 0x55aa );
      CheckPassed( rval );
  
      rval = Tss2_Sys_SetDecryptParam( decryptParamTestSysContext, 1, &( nvWriteData.t.buffer[0] ) );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SIZE );
  
      TeardownSysContext( &decryptParamTestSysContext );
  }
  
  void SysFinalizeTests()
  {
      DebugPrintf( NO_PREFIX, "\nSYS FINALIZE TESTS:\n" );
  
      Tss2_Sys_Finalize( 0 );
  
      // Note:  other cases tested by other tests.
  }
  
  void GetContextSizeTests()
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
      TSS2_SYS_CONTEXT *testSysContext;
  
      DebugPrintf( NO_PREFIX, "\nSYS GETCONTEXTSIZE TESTS:\n" );
  
      testSysContext = InitSysContext( 9, resMgrTctiContext, &abiVersion );
      if( testSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      rval = Tss2_Sys_Startup( testSysContext, TPM_SU_CLEAR );
      CheckFailed( rval, TSS2_TYPES_RC_INSUFFICIENT_BUFFER );
  
  	rval = Tss2_Sys_GetTestResult_Prepare( testSysContext );
  	CheckPassed( rval );
  
      // Note:  other cases tested by other tests.
  
      TeardownSysContext( &testSysContext );
  }
  
  void GetTctiContextTests()
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
      TSS2_SYS_CONTEXT *testSysContext;
      TSS2_TCTI_CONTEXT *tctiContext;
  
      DebugPrintf( NO_PREFIX, "\nSYS GETTCTICONTEXT TESTS:\n" );
  
      testSysContext = InitSysContext( 9, resMgrTctiContext, &abiVersion );
      if( testSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      rval = Tss2_Sys_GetTctiContext( testSysContext, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
      rval = Tss2_Sys_GetTctiContext( 0, &tctiContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
      TeardownSysContext( &testSysContext );
  }
  
  void PrepareTests()
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
      TSS2_SYS_CONTEXT *testSysContext;
  
      DebugPrintf( NO_PREFIX, "\nSYS PREPARE TESTS:\n" );
  
      testSysContext = InitSysContext( 0, resMgrTctiContext, &abiVersion );
      if( testSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      // Test for bad reference.
      rval = Tss2_Sys_GetTestResult_Prepare( 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
      // Test for bad sequence:  after ExecuteAsync
      rval = Tss2_Sys_GetTestResult_Prepare( testSysContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ExecuteAsync( testSysContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_GetTestResult_Prepare( testSysContext );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE );
  
      rval = Tss2_Sys_ExecuteFinish( testSysContext, -1 );
      CheckPassed( rval );
  
      // Test for bad sequence:  after Execute
      rval = Tss2_Sys_GetTestResult_Prepare( testSysContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_Execute( testSysContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_GetTestResult_Prepare( testSysContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_GetTestResult_Prepare( testSysContext );
      CheckPassed( rval );
  
      // Test for other NULL params
      rval = Tss2_Sys_Create_Prepare( testSysContext, 0xffffffff, 0, 0, 0, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE );
  
      TeardownSysContext( &testSysContext );
  }
  
  void  RmZeroSizedResponseTest()
  {
      SESSION *encryptSession = NULL;
      TPM2B_NONCE nonceCaller;
      TPMT_SYM_DEF symmetric;
  	TSS2_RC rval = TSS2_RC_SUCCESS;
  
      //
      // Tests what happens in RM when receive comes back with 0 sized response.
      // This happens when a command is sent to the simulator but the simulator
      // isn't "powered on".
      // Added this test because this took me a while to understand, and I
      // never want to have to debug this again.
      //
  
      DebugPrintf( NO_PREFIX, "\nRM ZERO SIZED RESPONSE TEST:\n" );
  
      rval = PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
  
      nonceCaller.t.size = 1;
      nonceCaller.t.buffer[0] = 0xa5;
  
      // AES encryption/decryption and CFB mode.
      symmetric.algorithm = TPM_ALG_AES;
      symmetric.keyBits.aes = 128;
      symmetric.mode.aes = TPM_ALG_CFB;
  
      // Start policy session for encrypt session.
      rval = StartAuthSessionWithParams( &encryptSession,
              TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller, 0, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckFailed( rval, TSS2_TCTI_RC_IO_ERROR );
  }
  
  
  void CmdRspAuthsTests()
  {
      SESSION *encryptSession = NULL, *decryptSession = NULL,
          *auditSession = NULL;
      TPM2B_NONCE nonceCaller, nonceTpm;
      TPMT_SYM_DEF symmetric;
  	TSS2_RC rval = TSS2_RC_SUCCESS;
      int i;
      TPM2B_ENCRYPTED_SECRET	encryptedSalt;
  	UINT32 savedMaxCommandSize, savedResponseSize;
  
      TSS2_SYS_CONTEXT *otherSysContext;
      TPM_HANDLE testSessionHandle;
  
      TPMS_AUTH_COMMAND encryptCmdAuth, decryptCmdAuth, auditCmdAuth;
      TPMS_AUTH_COMMAND *cmdAuthArray[3] = { &encryptCmdAuth, &decryptCmdAuth, &auditCmdAuth };
      TSS2_SYS_CMD_AUTHS cmdAuths = { 3, &cmdAuthArray[0] };
  
      TPMS_AUTH_RESPONSE encryptRspAuth, decryptRspAuth, auditRspAuth;
      TPMS_AUTH_RESPONSE *rspAuthArray[3] =
              { &encryptRspAuth, &decryptRspAuth, &auditRspAuth };
      TSS2_SYS_RSP_AUTHS rspAuths = { 3, &rspAuthArray[0] };
  
      DebugPrintf( NO_PREFIX, "\nSETCMDAUTHS TESTS:\n" );
  
      nonceCaller.t.size = SHA256_DIGEST_SIZE;
  
      for( i = 0; i < nonceCaller.t.size; i++ )
      {
          nonceCaller.t.buffer[i] = 0xa5;
      }
  
      // AES encryption/decryption and CFB mode.
      symmetric.algorithm = TPM_ALG_AES;
      symmetric.keyBits.aes = 128;
      symmetric.mode.aes = TPM_ALG_CFB;
  
      // Start encrypt session.
      rval = StartAuthSessionWithParams( &encryptSession,
              TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller, 0, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval ); // #1
  
      // Start decrypt session.
      rval = StartAuthSessionWithParams( &decryptSession,
              TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller, 0, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval );  // #2
  
      // Start audit session.
      rval = StartAuthSessionWithParams( &auditSession,
              TPM_RH_NULL, 0, TPM_RH_NULL, 0, &nonceCaller, 0, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256, resMgrTctiContext );
      CheckPassed( rval ); // #3
  
      encryptCmdAuth.sessionHandle = encryptSession->sessionHandle;
      encryptCmdAuth.nonce.t.size = 0;
      *( (UINT8 *)((void *)&encryptCmdAuth.sessionAttributes ) ) = 0;
      encryptCmdAuth.sessionAttributes.encrypt = 1;
      encryptCmdAuth.hmac.t.size = 0;
  
      decryptCmdAuth.sessionHandle = decryptSession->sessionHandle;
      decryptCmdAuth.nonce.t.size = 0;
      *( (UINT8 *)((void *)&decryptCmdAuth.sessionAttributes ) ) = 0;
      decryptCmdAuth.sessionAttributes.decrypt = 1;
      decryptCmdAuth.hmac.t.size = 0;
  
      auditCmdAuth.sessionHandle = auditSession->sessionHandle;
      auditCmdAuth.nonce.t.size = 0;
      *( (UINT8 *)((void *)&auditCmdAuth.sessionAttributes ) ) = 0;
      auditCmdAuth.sessionAttributes.audit = 1;
      auditCmdAuth.hmac.t.size = 0;
  
      // Test for bad sequence.
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #4
  
      encryptedSalt.t.size = 0;
      rval = Tss2_Sys_StartAuthSession_Prepare( sysContext,
              TPM_RH_NULL, TPM_RH_NULL, &nonceCaller, &encryptedSalt, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256 );
      CheckPassed( rval ); // #5
  
      // Test for bad reference.
      rval = Tss2_Sys_SetCmdAuths( 0, &cmdAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #6
  
      rval = Tss2_Sys_SetCmdAuths( sysContext, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #7
  
      // Test for count == 0; this should pass.
      cmdAuths.cmdAuthsCount= 0;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckPassed( rval ); // #8
  
      // Test for bad value.
      cmdAuths.cmdAuthsCount= 3;
      cmdAuthArray[0] = 0;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE ); // #9
  
      cmdAuthArray[0] = &encryptCmdAuth;
      cmdAuthArray[1] = 0;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE ); // #10
  
      cmdAuthArray[1] = &decryptCmdAuth;
      cmdAuthArray[2] = 0;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE ); // #11
      cmdAuthArray[2] = &auditCmdAuth;
  
      // Test for insufficient context.
      cmdAuths.cmdAuthsCount= 0;
      savedMaxCommandSize = ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize;
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize = sizeof( TPM20_Header_In ) + 3 * sizeof( TPM_HANDLE ) - 1;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckPassed( rval ); // #12
  
      cmdAuths.cmdAuthsCount= 0;
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize = sizeof( TPM20_Header_In ) + 3 * sizeof( TPM_HANDLE );
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckPassed( rval );// #13
  
      cmdAuths.cmdAuthsCount= 3;
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize = sizeof( TPM20_Header_In ) + 3 * sizeof( TPM_HANDLE );
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckFailed( rval, TSS2_SYS_RC_INSUFFICIENT_CONTEXT ); // #14
  
      // Do successful one; use this to get size of command.
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize = savedMaxCommandSize;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckPassed( rval ); // #15
  
      // Then set maxCommandSize to the the previously gotten commandSize - 1.  This should fail.
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize = GetCommandSize( sysContext ) - 1;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckFailed( rval, TSS2_SYS_RC_INSUFFICIENT_CONTEXT ); // #16
  
      // Reset size of sysContext.
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize = savedMaxCommandSize;
  
      // Setup for response auths test.
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->maxCommandSize = BE_TO_HOST_32( savedMaxCommandSize );
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckPassed( rval ); // #15
  
  	DebugPrintf( NO_PREFIX, "\nGETRSPAUTHS TESTS:\n" );
  
      // Test for bad sequence.
      rval = Tss2_Sys_GetRspAuths( sysContext, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #1
  
      otherSysContext = InitSysContext( 0, resMgrTctiContext, &abiVersion );
      if( otherSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      //
      // Test for command that failed:  invalid handle.
      //
      rval = Tss2_Sys_StartAuthSession_Prepare( otherSysContext,
              0xffffffff, TPM_RH_NULL, &nonceCaller, &encryptedSalt, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256 );
      CheckPassed( rval ); // #2
  
      rval = Tss2_Sys_Execute( otherSysContext );
      CheckFailed( rval, (TPM_RC_VALUE | TPM_RC_1 | TPM_RC_H) ); // #3
  
      rval = Tss2_Sys_GetRspAuths( otherSysContext, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #4
  
      //
      // Test for command that can never take sessions.
      //
      rval = Tss2_Sys_ReadClock_Prepare( otherSysContext );
      CheckPassed( rval ); // #5
  
      rval = Tss2_Sys_Execute( otherSysContext );
      CheckPassed( rval ); // #6
  
      rval = Tss2_Sys_GetRspAuths( otherSysContext, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #7
  
      // Setup for testing for bad references and other conditions.
      rval = Tss2_Sys_StartAuthSession_Prepare( sysContext,
              TPM_RH_NULL, TPM_RH_NULL, &nonceCaller, &encryptedSalt, TPM_SE_HMAC,
              &symmetric, TPM_ALG_SHA256 );
      CheckPassed( rval ); // #8
  
      cmdAuths.cmdAuthsCount = 2;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &cmdAuths );
      CheckPassed( rval ); // #9
  
  	rval = Tss2_Sys_Execute( sysContext );
      CheckPassed( rval ); // #10
  
      // Test for bad reference.
      rval = Tss2_Sys_GetRspAuths( 0, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #11
  
      rval = Tss2_Sys_GetRspAuths( sysContext, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #12
  
      // Test for bad count.
      rspAuths.rspAuthsCount = 0;
      rval = Tss2_Sys_GetRspAuths( sysContext, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE ); // #13
  
      // Test for non-matching count: specified count doesn't
      // match returned count.
      rspAuths.rspAuthsCount = 1;
      rval = Tss2_Sys_GetRspAuths( sysContext, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_INVALID_SESSIONS ); // #14
  
      // Test for non-matching count: cmd auth count doesn't
      // match returned auth count.
      rspAuths.rspAuthsCount = 3;
      savedResponseSize = ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->rsp_header.size;
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->rsp_header.size = savedResponseSize - 5;
      rval = Tss2_Sys_GetRspAuths( sysContext, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_INVALID_SESSIONS ); // #15
  
      // Test for malformed response.
      rspAuths.rspAuthsCount = 2;
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->rsp_header.size = savedResponseSize - 7;
      rval = Tss2_Sys_GetRspAuths( sysContext, &rspAuths );
      CheckFailed( rval, TSS2_SYS_RC_MALFORMED_RESPONSE ); // #16
  
      // Ths one should pass.
      ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->rsp_header.size = savedResponseSize;
      rval = Tss2_Sys_GetRspAuths( sysContext, &rspAuths );
      CheckPassed( rval ); // #17
  
      // Check for bad sequence.
      INIT_SIMPLE_TPM2B_SIZE( nonceTpm );
      rval = Tss2_Sys_StartAuthSession_Complete( sysContext,
              &testSessionHandle, &nonceTpm );
      CheckPassed( rval ); // #17
  
      // Now delete sessions.
      rval = EndAuthSession( encryptSession );
      CheckPassed( rval );
  
      rval = EndAuthSession( decryptSession );
      CheckPassed( rval );
  
      rval = EndAuthSession( auditSession );
      CheckPassed( rval );
  }
  
  void GetSetEncryptParamTests()
  {
      TPM2B_MAX_NV_BUFFER nvWriteData = { { 4, { 0xde, 0xad, 0xbe, 0xef, } } };
      const uint8_t *encryptParamBuffer;
      const uint8_t encryptParamBuffer1[4] = { 01, 02, 03, 04 };
      size_t encryptParamSize;
      TSS2_RC rval;
      int i;
      TPM2B_DIGEST authPolicy;
      TPMA_NV nvAttributes;
      TPM2B_AUTH  nvAuth;
  
      TPMS_AUTH_COMMAND sessionData = { TPM_RS_PW, };
      TPMS_AUTH_RESPONSE sessionDataOut;
      TPMS_AUTH_COMMAND *sessionDataArray[1] = { &sessionData };
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1] = { &sessionDataOut };
      TSS2_SYS_CMD_AUTHS sessionsData = { 1, &sessionDataArray[0] };
      TSS2_SYS_RSP_AUTHS sessionsDataOut = { 1, &sessionDataOutArray[0] };
  
      TPM2B_MAX_NV_BUFFER nvReadData;
      const uint8_t 		*cpBuffer;
  
      DebugPrintf( NO_PREFIX, "\nGET/SET ENCRYPT PARAM TESTS:\n" );
  
      // Do Prepare.
      rval = Tss2_Sys_NV_Write_Prepare( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvWriteData, 0 );
      CheckPassed( rval ); // #1
  
      // Test for bad sequence
      rval = Tss2_Sys_GetEncryptParam( sysContext, &encryptParamSize, &encryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #2
  
      rval = Tss2_Sys_SetEncryptParam( sysContext, 4, &( nvWriteData.t.buffer[0] ) );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #3
  
      // Create NV index
  
      // Set empty policy and auth value.
      authPolicy.t.size = 0;
      nvAuth.t.size = 0;
  
      // Now set the attributes.
      *(UINT32 *)( (void *)&nvAttributes ) = 0;
      nvAttributes.TPMA_NV_AUTHREAD = 1;
      nvAttributes.TPMA_NV_AUTHWRITE = 1;
      nvAttributes.TPMA_NV_PLATFORMCREATE = 1;
  
      rval = DefineNvIndex( TPM_RH_PLATFORM, TPM_RS_PW, &nvAuth, &authPolicy,
              TPM20_INDEX_PASSWORD_TEST, TPM_ALG_SHA1, nvAttributes, 32  );
      CheckPassed( rval ); // #4
  
      // Write the index.
      rval = Tss2_Sys_NV_Write_Prepare( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &nvWriteData, 0 );
      CheckPassed( rval ); // #5
  
      // NOTE: add GetCpBuffer tests here, just because its easier.
      rval = Tss2_Sys_GetCpBuffer( 0, (size_t *)4, (const uint8_t **)4 );
  	CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #6
  
      rval = Tss2_Sys_GetCpBuffer( sysContext, (size_t *)0, (const uint8_t **)4 );
  	CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #7
  
      rval = Tss2_Sys_GetCpBuffer( sysContext, (size_t *)4, (const uint8_t **)0 );
  	CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #8
  
  
      rval = Tss2_Sys_SetCmdAuths( sysContext, &sessionsData );
      CheckPassed( rval ); // #9
  
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed( rval ); // #10
  
      // NOTE: Stick two tests for BAD_SEQUENCE for GetDecryptParam and SetDecryptParam here, just
      // because it's easier to do this way.
      rval = Tss2_Sys_GetDecryptParam( sysContext, (size_t *)4, (const uint8_t **)4 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #11
  
      rval = Tss2_Sys_SetDecryptParam( sysContext, 10, (uint8_t *)4 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #12
  
      // NOTE: Stick test for BAD_SEQUENCE for GetCpBuffer here, just
      // because it's easier to do this way.
      rval = Tss2_Sys_GetCpBuffer( sysContext, (size_t *)4, &cpBuffer );
  	CheckFailed( rval, TSS2_SYS_RC_BAD_SEQUENCE ); // #13
  
      // Now finish the write command so that TPM isn't stuck trying
      // to send a response.
      rval = Tss2_Sys_ExecuteFinish( sysContext, -1 );
      CheckPassed( rval ); // #14
  
      // Test GetEncryptParam for no encrypt param case.
      rval = Tss2_Sys_GetEncryptParam( sysContext, &encryptParamSize, &encryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_NO_ENCRYPT_PARAM ); // #15
  
      // Test SetEncryptParam for no encrypt param case.
      rval = Tss2_Sys_SetEncryptParam( sysContext, encryptParamSize, encryptParamBuffer1 );
      CheckFailed( rval, TSS2_SYS_RC_NO_ENCRYPT_PARAM ); // #16
  
      // Now read it and do tests on get/set encrypt functions
      rval = Tss2_Sys_NV_Read_Prepare( sysContext, TPM20_INDEX_PASSWORD_TEST, TPM20_INDEX_PASSWORD_TEST, 4, 0 );
      CheckPassed( rval ); // #17
  
      INIT_SIMPLE_TPM2B_SIZE( nvReadData );
      rval = Tss2_Sys_NV_Read( sysContext, TPM20_INDEX_PASSWORD_TEST,
              TPM20_INDEX_PASSWORD_TEST, &sessionsData, 4, 0, &nvReadData, &sessionsDataOut );
      CheckPassed( rval ); // #18
  
      rval = Tss2_Sys_GetEncryptParam( sysContext, &encryptParamSize, &encryptParamBuffer );
      CheckPassed( rval ); // #19
  
      // Test case of encryptParamSize being too small.
      encryptParamSize--;
      rval = Tss2_Sys_SetEncryptParam( sysContext, encryptParamSize, encryptParamBuffer1 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SIZE ); // #20
      encryptParamSize += 2;
  
      // Size too large...
      rval = Tss2_Sys_SetEncryptParam( sysContext, encryptParamSize, encryptParamBuffer1 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_SIZE ); // #21
  
      encryptParamSize--;
      rval = Tss2_Sys_SetEncryptParam( sysContext, encryptParamSize, encryptParamBuffer1 );
      CheckPassed( rval ); // #22
  
      rval = Tss2_Sys_GetEncryptParam( sysContext, &encryptParamSize, &encryptParamBuffer );
      CheckPassed( rval ); // #23
  
      // Test that encryptParamBuffer is the same as encryptParamBuffer1
      for( i = 0; i < 4; i++ )
      {
          if( encryptParamBuffer[i] != encryptParamBuffer1[i] )
          {
              DebugPrintf( NO_PREFIX, "ERROR!! encryptParamBuffer[%d] s/b: %2.2x, was: %2.2x\n", i, encryptParamBuffer[i], encryptParamBuffer1[i] );
              Cleanup();
          }
      }
  
      rval = Tss2_Sys_NV_UndefineSpace( sysContext, TPM_RH_PLATFORM, TPM20_INDEX_PASSWORD_TEST, &sessionsData, 0 );
      CheckPassed( rval ); // #24
  
  
      // Test for bad reference
      rval = Tss2_Sys_GetEncryptParam( 0, &encryptParamSize, &encryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #25
  
      rval = Tss2_Sys_GetEncryptParam( sysContext, 0, &encryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #26
  
      rval = Tss2_Sys_GetEncryptParam( sysContext, &encryptParamSize, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #27
  
      rval = Tss2_Sys_SetEncryptParam( sysContext, 4, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #28
  
      rval = Tss2_Sys_SetEncryptParam( 0, 4, encryptParamBuffer );
      CheckFailed( rval, TSS2_SYS_RC_BAD_REFERENCE ); // #29
  }
  
  void TestRM()
  {
      TSS2_TCTI_CONTEXT *otherResMgrTctiContext = 0;
      TSS2_SYS_CONTEXT *otherSysContext;
      TPM2B_SENSITIVE_CREATE  inSensitive;
      TPM2B_PUBLIC            inPublic;
      TPM2B_DATA              outsideInfo;
      TPML_PCR_SELECTION      creationPCR;
      TPMS_AUTH_COMMAND sessionData;
      TPMS_AUTH_RESPONSE sessionDataOut;
      TSS2_SYS_CMD_AUTHS sessionsData;
  
      TSS2_SYS_RSP_AUTHS sessionsDataOut;
      TPM2B_NAME name;
      TPM2B_PUBLIC outPublic;
      TPM2B_CREATION_DATA creationData;
      TPM2B_DIGEST creationHash;
      TPMT_TK_CREATION creationTicket;
  
      TPMS_AUTH_COMMAND *sessionDataArray[1];
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
      TSS2_RC rval = TSS2_RC_SUCCESS;
  
      TPMS_CONTEXT context;
      TSS2_TCTI_CONTEXT *tctiContext;
  
      TPMI_DH_CONTEXT loadedHandle, newHandle, newNewHandle, newHandleDummy;
      TPMS_CONTEXT    newContext;
      char otherResMgrInterfaceName[] = "Test RM Resource Manager";
  
      DebugPrintf( NO_PREFIX, "\nRM TESTS:\n" );
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.data.t.size = 0;
      inSensitive.t.size = loadedSha1KeyAuth.b.size + 2;
  
      inPublic.t.publicArea.type = TPM_ALG_RSA;
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA1;
  
      // First clear attributes bit field.
      *(UINT32 *)&( inPublic.t.publicArea.objectAttributes) = 0;
      inPublic.t.publicArea.objectAttributes.restricted = 1;
      inPublic.t.publicArea.objectAttributes.userWithAuth = 1;
      inPublic.t.publicArea.objectAttributes.decrypt = 1;
      inPublic.t.publicArea.objectAttributes.fixedTPM = 1;
      inPublic.t.publicArea.objectAttributes.fixedParent = 1;
      inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin = 1;
  
      inPublic.t.publicArea.authPolicy.t.size = 0;
  
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_ECB;
      inPublic.t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 1024;
      inPublic.t.publicArea.parameters.rsaDetail.exponent = 0;
  
      inPublic.t.publicArea.unique.rsa.t.size = 0;
  
      outsideInfo.t.size = 0;
      creationPCR.count = 0;
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      rval = InitSocketTctiContext( &rmInterfaceConfig, &otherResMgrTctiContext);
      if( rval != TSS2_RC_SUCCESS )
      {
          DebugPrintf( NO_PREFIX, "Resource Mgr, %s, failed initialization: 0x%x.  Exiting...\n", otherResMgrInterfaceName, rval );
          Cleanup();
          return;
      }
  
      otherSysContext = InitSysContext( 0, otherResMgrTctiContext, &abiVersion );
      if( otherSysContext == 0 )
      {
          InitSysContextFailure();
      }
  
      // TEST WITH AN INVALID COMMAND CODE.
  
      rval = Tss2_Sys_Startup_Prepare( sysContext, TPM_SU_CLEAR );
      CheckPassed(rval);
  
      //
      // Alter the CC by altering the CC field in sysContext.
      //
      // WARNING:  This is something only a test application should do. Do
      // not use this as sample code.
      //
      ((TPM20_Header_In *)( ( (_TSS2_SYS_CONTEXT_BLOB *)sysContext )->tpmInBuffPtr) )->commandCode = TPM_CC_FIRST - 1;
      rval = Tss2_Sys_Execute( sysContext );
      CheckFailed( rval, TPM_RC_COMMAND_CODE );
  
      // TEST OWNERSHIP
  
      // Try to access a key created by the first TCTI context.
      sessionData.hmac.t.size = 2;
      sessionData.hmac.t.buffer[0] = 0x00;
      sessionData.hmac.t.buffer[1] = 0xff;
  
      inPublic.t.publicArea.type = TPM_ALG_RSA;
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA1;
  
      // First clear attributes bit field.
      *(UINT32 *)&( inPublic.t.publicArea.objectAttributes) = 0;
      inPublic.t.publicArea.objectAttributes.restricted = 1;
      inPublic.t.publicArea.objectAttributes.userWithAuth = 1;
      inPublic.t.publicArea.objectAttributes.decrypt = 1;
      inPublic.t.publicArea.objectAttributes.fixedTPM = 1;
      inPublic.t.publicArea.objectAttributes.fixedParent = 1;
      inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin = 1;
  
      inPublic.t.publicArea.authPolicy.t.size = 0;
  
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_ECB;
      inPublic.t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 2048;
      inPublic.t.publicArea.parameters.rsaDetail.exponent = 0;
  
      inPublic.t.publicArea.unique.rsa.t.size = 0;
  
      outsideInfo.t.size = 0;
  
  
      // This one should pass, because the same context is allowed to save the context.
      rval = Tss2_Sys_ContextSave( sysContext, handle2048rsa, &context );
      CheckPassed( rval );
  
      // This one should pass, since we saved the context first.
      rval = Tss2_Sys_ContextLoad( otherSysContext, &context, &loadedHandle );
      CheckPassed( rval );
  
      rval = Tss2_Sys_FlushContext( otherSysContext, loadedHandle );
      CheckPassed( rval );
  
      // NOW, DO SOME LOCALITY TESTS
  
      // Test with null tctiContext ptr.
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)otherResMgrTctiContext)->setLocality)( 0, 0 );
      CheckFailed( rval, TSS2_TCTI_RC_BAD_REFERENCE );
  
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)otherResMgrTctiContext)->setLocality)( otherResMgrTctiContext, 0 );
      CheckPassed( rval );
  
      // Now try changing localities between send and receive.
      rval = Tss2_Sys_ContextLoad( otherSysContext, &context, &loadedHandle );
      CheckPassed( rval );
  
      rval = Tss2_Sys_FlushContext_Prepare( otherSysContext, loadedHandle );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ExecuteAsync( otherSysContext );
      CheckPassed( rval );
  
      // This should fail because locality is changing between send and receive.
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)otherResMgrTctiContext)->setLocality)( otherResMgrTctiContext, 1 );
      CheckFailed( rval, TSS2_TCTI_RC_BAD_SEQUENCE );
  
      rval = Tss2_Sys_ExecuteFinish( otherSysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckPassed( rval );
  
      // NOW, DO SOME CANCEL TESTS
  
      rval = Tss2_Sys_GetTctiContext( sysContext, &tctiContext );
      CheckPassed( rval );
  
      // Try cancel with null tctiContext ptr.
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)otherResMgrTctiContext)->cancel)( 0 );
      CheckFailed( rval, TSS2_TCTI_RC_BAD_REFERENCE );
  
      // Try cancel when no commands are pending.
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)otherResMgrTctiContext)->cancel)( otherResMgrTctiContext );
      CheckFailed( rval, TSS2_TCTI_RC_BAD_SEQUENCE );
  
      // Then try cancel with a pending command:  send cancel before blocking _Finish call.
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 2048;
      rval = Tss2_Sys_CreatePrimary_Prepare( sysContext, TPM_RH_PLATFORM, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR );
      CheckPassed( rval );
  
      //
      // NOTE: there are race conditions in tests that use cancel and
      // are expecting to receive the CANCEL response code.  The tests
      // typically pass, but may occasionally fail on the order of
      // 1 out of 500 or so test passes.
      //
      // The OS could delay the test app long enough for the TPM to
      // complete the CreatePrimary before the test app gets to run
      // again.  To make these tests robust would require some way to
      // create a critical section in the test app.
      //
      sessionData.hmac.t.size = 0;
      sessionData.nonce.t.size = 0;
      rval = Tss2_Sys_SetCmdAuths( sysContext, &sessionsData );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed( rval );
  
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->cancel)( tctiContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TPM_RC_CANCELED );
  
       // Then try cancel with a pending command:  send cancel after non-blocking _Finish call.
      rval = Tss2_Sys_CreatePrimary_Prepare( sysContext, TPM_RH_PLATFORM, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR );
      CheckPassed( rval );
  
      rval = Tss2_Sys_SetCmdAuths( sysContext, &sessionsData );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, 0 );
      CheckFailed( rval, TSS2_TCTI_RC_TRY_AGAIN );
  
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)tctiContext)->cancel)( tctiContext );
      CheckPassed( rval );
  
  	rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckFailed( rval, TPM_RC_CANCELED );
  
      // Then try cancel from a different connection:  it should just get a sequence error.
      rval = Tss2_Sys_CreatePrimary_Prepare( sysContext, TPM_RH_PLATFORM, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR );
      CheckPassed( rval );
  
      rval = Tss2_Sys_SetCmdAuths( sysContext, &sessionsData );
      CheckPassed( rval );
  
      rval = Tss2_Sys_ExecuteAsync( sysContext );
      CheckPassed( rval );
  
      rval = (((TSS2_TCTI_CONTEXT_COMMON_V1 *)otherResMgrTctiContext)->cancel)( otherResMgrTctiContext );
      CheckFailed( rval, TSS2_TCTI_RC_BAD_SEQUENCE );
  
      rval = Tss2_Sys_ExecuteFinish( sysContext, TSS2_TCTI_TIMEOUT_BLOCK );
      CheckPassed( rval );
  
      outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( name );
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      creationHash.t.size = sizeof( creationHash );
      rval = Tss2_Sys_CreatePrimary_Complete( sysContext, &newHandle, &outPublic, &creationData,
              &creationHash, &creationTicket, &name );
      CheckPassed( rval );
  
      //
      // Now try saving context for object and loading it using a different connection.
      //
  
      // First save context.
      rval = Tss2_Sys_ContextSave( sysContext, newHandle, &newContext );
      CheckPassed( rval );
  
      //
      // Now create an object with different hierarchy.  This will make sure that
      // RM is getting correct hierarchy in it's table.
      // NOTE:  this test can only be verified by looking at RM output.
      //
  	outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( name );
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      rval = Tss2_Sys_CreatePrimary( sysContext, TPM_RH_ENDORSEMENT, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR, &newHandleDummy, &outPublic, &creationData, &creationHash,
  			&creationTicket, &name, &sessionsDataOut );
      CheckPassed( rval );
  
      // Now try loading the context using a different connection.
      rval = Tss2_Sys_ContextLoad( otherSysContext, &newContext, &newNewHandle );
      CheckPassed( rval );
  
      // Flush original connection's object.
      rval = Tss2_Sys_FlushContext( sysContext, newHandle );
      CheckPassed( rval );
  
      // Now flush new object from other connection.  Should work.
      rval = Tss2_Sys_FlushContext( otherSysContext, newNewHandle );
      CheckPassed( rval );
  
      // Now flush dummy object.
      rval = Tss2_Sys_FlushContext( sysContext, newHandleDummy );
      CheckPassed( rval );
  
      TeardownTctiContext( &otherResMgrTctiContext );
  
      TeardownSysContext( &otherSysContext );
  }
  
  void EcEphemeralTest()
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
      TPM2B_ECC_POINT Q;
      UINT16 counter;
  
      DebugPrintf( NO_PREFIX, "\nEC Ephemeral TESTS:\n" );
  
      // Test SAPI for case of Q size field not being set to 0.
      INIT_SIMPLE_TPM2B_SIZE( Q );
      rval = Tss2_Sys_EC_Ephemeral( sysContext, 0, TPM_ECC_BN_P256, &Q, &counter, 0 );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE );
  
      Q.t.size = 0;
      rval = Tss2_Sys_EC_Ephemeral( sysContext, 0, TPM_ECC_BN_P256, &Q, &counter, 0 );
      CheckPassed( rval );
  }
  
  void TestCreate1()
  {
      UINT32 rval;
      TPM2B_SENSITIVE_CREATE  inSensitive = { { sizeof( TPM2B_SENSITIVE_CREATE ) - 2, } };
      TPM2B_PUBLIC            inPublic = { { sizeof( TPM2B_PUBLIC ) - 2, } };
      TPM2B_DATA              outsideInfo = { { sizeof( TPM2B_DATA ) - 2, } };
      TPML_PCR_SELECTION      creationPCR;
  
      TPMS_AUTH_COMMAND sessionData = { TPM_RS_PW, };
      TPMS_AUTH_RESPONSE sessionDataOut;
      TPMS_AUTH_COMMAND *sessionDataArray[1] = { &sessionData };
      TPMS_AUTH_RESPONSE *sessionDataOutArray[1] = { &sessionDataOut };
      TSS2_SYS_CMD_AUTHS sessionsData = { 1, &sessionDataArray[0] };
      TSS2_SYS_RSP_AUTHS sessionsDataOut = { 1, &sessionDataOutArray[0] };
  
      TPM2B_NAME name = { { sizeof( TPM2B_NAME ) - 2, } };
      TPM2B_PUBLIC outPublic = { { sizeof( TPM2B_PUBLIC ) - 2, } };
      TPM2B_CREATION_DATA creationData =  { { sizeof( TPM2B_CREATION_DATA ) - 2, } };
      TPM2B_DIGEST creationHash = { { sizeof( TPM2B_DIGEST ) - 2, } };
      TPMT_TK_CREATION creationTicket = { 0, 0, { { sizeof( TPM2B_DIGEST ) - 2, } } };
  
      sessionDataArray[0] = &sessionData;
      sessionDataOutArray[0] = &sessionDataOut;
  
      sessionsDataOut.rspAuths = &sessionDataOutArray[0];
      sessionsData.cmdAuths = &sessionDataArray[0];
  
      sessionsDataOut.rspAuthsCount = 1;
  
      printf( "\nCREATE PRIMARY, encrypt and decrypt TESTS:\n" );
  
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.userAuth = loadedSha1KeyAuth;
      inSensitive.t.sensitive.data.t.size = 0;
      inSensitive.t.size = loadedSha1KeyAuth.b.size + 2;
  
      inPublic.t.publicArea.type = TPM_ALG_RSA;
      inPublic.t.publicArea.nameAlg = TPM_ALG_SHA1;
  
      // First clear attributes bit field.
      *(UINT32 *)&( inPublic.t.publicArea.objectAttributes) = 0;
      inPublic.t.publicArea.objectAttributes.restricted = 1;
      inPublic.t.publicArea.objectAttributes.userWithAuth = 1;
      inPublic.t.publicArea.objectAttributes.decrypt = 1;
      inPublic.t.publicArea.objectAttributes.fixedTPM = 1;
      inPublic.t.publicArea.objectAttributes.fixedParent = 1;
      inPublic.t.publicArea.objectAttributes.sensitiveDataOrigin = 1;
  
      inPublic.t.publicArea.authPolicy.t.size = 0;
  
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
      inPublic.t.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_ECB;
      inPublic.t.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 1024;
      inPublic.t.publicArea.parameters.rsaDetail.exponent = 0;
  
      inPublic.t.publicArea.unique.rsa.t.size = 0;
  
      outsideInfo.t.size = 0;
      creationPCR.count = 0;
  
      sessionData.sessionHandle = TPM_RS_PW;
  
      // Init nonce.
      sessionData.nonce.t.size = 0;
  
      // init hmac
      sessionData.hmac.t.size = 0;
  
      // Init session attributes
      *( (UINT8 *)((void *)&sessionData.sessionAttributes ) ) = 0;
  
      sessionsData.cmdAuthsCount = 1;
      sessionsData.cmdAuths[0] = &sessionData;
  
      inPublic.t.publicArea.parameters.rsaDetail.keyBits = 2048;
  
      // Do SAPI test for non-zero sized outPublic
      outPublic.t.size = 0xff;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_CreatePrimary( sysContext, TPM_RH_OWNER, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR, &handle2048rsa, &outPublic, &creationData, &creationHash,
              &creationTicket, &name, &sessionsDataOut );
      CheckFailed( rval, TSS2_SYS_RC_BAD_VALUE );
  
      outPublic.t.size = 0;
      creationData.t.size = 0;
      INIT_SIMPLE_TPM2B_SIZE( creationHash );
      INIT_SIMPLE_TPM2B_SIZE( name );
      rval = Tss2_Sys_CreatePrimary( sysContext, TPM_RH_OWNER, &sessionsData, &inSensitive, &inPublic,
              &outsideInfo, &creationPCR, &handle2048rsa, &outPublic, &creationData, &creationHash,
              &creationTicket, &name, &sessionsDataOut );
      CheckPassed( rval );
  
      printf( "\nNew key successfully created in owner hierarchy (RSA 2048).  Handle: 0x%8.8x\n",
              handle2048rsa );
      printf( "Name of created primary key: " );
      PrintSizedBuffer( (TPM2B *)&name );
  
      char buffer1contents[] = "test";
      //char buffer2contents[] = "string";
  
      TPMI_DH_OBJECT keyHandle = handle2048rsa;
      TPMT_RSA_DECRYPT inScheme;
      TPM2B_PUBLIC_KEY_RSA message;
      TPM2B_PUBLIC_KEY_RSA outData;
  
      message.t.size = strlen(buffer1contents);
      memcpy(message.t.buffer, buffer1contents, message.t.size);
  
      inScheme.scheme = TPM_ALG_NULL;
  
      //printf("keyHandle: %x\n", keyHandle);
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_RSA_Encrypt(sysContext, keyHandle, &sessionsData, &message, &inScheme, &outsideInfo, &outData, &sessionsDataOut);
      if( tpmSpecVersion >= 124 ) {
          CheckFailed( rval, TPM_RC_S + TPM_RC_1 + TPM_RC_HANDLE );
      } else {
          CheckFailed( rval, TPM_RC_1 + TPM_RC_HANDLE );
      }
  
      INIT_SIMPLE_TPM2B_SIZE( outData );
      rval = Tss2_Sys_RSA_Encrypt(sysContext, keyHandle, 0, &message, &inScheme, &outsideInfo, &outData, &sessionsDataOut);
      CheckPassed( rval );
  
      int i;
      for (i=0; i<message.t.size; i++)
      	printf("\nlabel size:%d, label buffer:%x, outData size:%d, outData buffer:%x, msg size:%d, msg buffer:%x", outsideInfo.t.size, outsideInfo.t.buffer[i], outData.t.size, outData.t.buffer[i], message.t.size, message.t.buffer[i]);
      CheckPassed(rval);
  }
  
  int
  test_invoke (TSS2_SYS_CONTEXT *sapi_context)
  {
      TSS2_RC rval = TSS2_RC_SUCCESS;
  
      sysContext = sapi_context;
      rval = Tss2_Sys_GetTctiContext (sapi_context, &resMgrTctiContext);
      if (rval != TSS2_RC_SUCCESS) {
          printf ("Failed to get TCTI context from sapi_context: 0x%" PRIx32
                  "\n", rval);
          return 1;
      }
  
      nullSessionsDataOut.rspAuthsCount = 1;
      nullSessionsDataOut.rspAuths[0]->nonce = nullSessionNonceOut;
      nullSessionsDataOut.rspAuths[0]->hmac = nullSessionHmac;
      nullSessionNonceOut.t.size = 0;
      nullSessionNonce.t.size = 0;
  
      loadedSha1KeyAuth.t.size = 2;
      loadedSha1KeyAuth.t.buffer[0] = 0x00;
      loadedSha1KeyAuth.t.buffer[1] = 0xff;
  
      rval = PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
      CheckPassed( rval );
  
      InitEntities();
  
      InitNullSession( &nullSessionData);
  
      SysFinalizeTests();
  
      GetContextSizeTests();
  
      GetTctiContextTests();
  
      GetSetDecryptParamTests();
  
  #ifdef SKIP_RM_ZERO_SIZED_RESPONSE_TEST
      printf("*** Skipping rm zero sized response tests\n");
  #else
      RmZeroSizedResponseTest();
  #endif
  
      TestTpmStartup();
  
      // Run this directly after Startup tests to test for
      // a resource mgr corner case with SaveContext.
      TestStartAuthSession();
  
      GetTpmVersion();
  
      GetTpmManufacturer();
  
  #ifdef SKIP_CMD_RSP_AUTH_TEST
      printf("** Skipping cmd rsp auth tests\n");
  #else
      CmdRspAuthsTests();
  #endif
  
      PrepareTests();
  
      // Clear DA lockout.
      TestDictionaryAttackLockReset();
  
      TestDictionaryAttackLockReset();
  
      TestCreate();
  
  #ifdef SKIP_TEST_CREATE1_TEST
      printf("** Skipping TestCreate1()\n");
  #else
      TestCreate1();
  #endif // SKIP_TEST_CREATE1_TEST
  
      TestSapiApis();
  
      TestHierarchyControl();
  
      NvIndexProto();
  
      GetSetEncryptParamTests();
  
      TestEncryptDecryptSession();
      SimpleHmacOrPolicyTest( true );
  #ifdef SKIP_SIMPLE_HMAC_OR_POLCY_FALSE_TEST
      printf("** Skipping SimpleHmacOrPolicyTest(false)\n");
  #else
      SimpleHmacOrPolicyTest( false );
  #endif //SKIP_SIMPLE_HMAC_OR_POLCY_FALSE_TEST
  
      TestTpmGetCapability();
  
      TestPcrExtend();
  #ifdef SKIP_HASH_TEST
      printf("** Skpping hash test\n");
  #else
      TestHash();
  #endif
  
      TestPolicy();
      TestTpmClear();
      TestChangeEps();
      TestChangePps();
      TestHierarchyChangeAuth();
      TestShutdown();
      TestNV();
      TestCreate();
  #ifdef SKIP_EVICT_TEST
      printf("** Skipping TestEvict()\n");
  #else
      TestEvict();
  #endif
      NvIndexProto();
      PasswordTest();
      HmacSessionTest();
      TestQuote();
      TestDictionaryAttackLockReset();
      TestPcrAllocate();
      TestUnseal();
  #ifdef SKIP_RM_TEST
      printf("** Skipping TestRM()\n");
  #else
      TestRM();
  #endif
      EcEphemeralTest();
      // Clear out RM entries for objects.
      rval = Tss2_Sys_FlushContext( sysContext, handle2048rsa );
      CheckPassed( rval );
      rval = Tss2_Sys_FlushContext( sysContext, loadedSha1KeyHandle );
      CheckPassed( rval );
  
      PlatformCommand( resMgrTctiContext, MS_SIM_POWER_OFF );
      return 0;
  }
  